Commit 6b98e786 authored by unknown's avatar unknown

if no xa recovery (or after it):

  warning on startup if prepared foreign xids
  error on startup if prepared our xids
  temporarily: always rollback prepared our xids instead of an error


sql/mysql_priv.h:
  opt_tc_log_file made extern
sql/mysqld.cc:
  opt_tc_log_file made extern
  always call ha_recover() even if no previous crash was detected
parent f609d604
...@@ -744,16 +744,48 @@ int ha_commit_or_rollback_by_xid(LEX_STRING *ident, bool commit) ...@@ -744,16 +744,48 @@ int ha_commit_or_rollback_by_xid(LEX_STRING *ident, bool commit)
/* /*
recover() step of xa recover() step of xa
NOTE
there are three modes of operation:
- automatic recover after a crash
in this case commit_list != 0, tc_heuristic_recover==0
all xids from commit_list are committed, others are rolled back
- manual (heuristic) recover
in this case commit_list==0, tc_heuristic_recover != 0
DBA has explicitly specified that all prepared transactions should
be committed (or rolled back).
- no recovery (MySQL did not detect a crash)
in this case commit_list==0, tc_heuristic_recover == 0
there should be no prepared transactions in this case.
*/ */
int ha_recover(HASH *commit_list) int ha_recover(HASH *commit_list)
{ {
int len, got; int len, got, found_foreign_xids=0, found_my_xids=0;
handlerton **ht= handlertons, **end_ht=ht+total_ha; handlerton **ht= handlertons, **end_ht=ht+total_ha;
XID *list=0; XID *list=0;
bool dry_run=(commit_list==0 && tc_heuristic_recover==0);
DBUG_ENTER("ha_recover"); DBUG_ENTER("ha_recover");
DBUG_ASSERT(total_ha_2pc); /* commit_list and tc_heuristic_recover cannot be set both */
DBUG_ASSERT(commit_list || tc_heuristic_recover); DBUG_ASSERT(commit_list==0 || tc_heuristic_recover==0);
/* if either is set, total_ha_2pc must be set too */
DBUG_ASSERT((commit_list==0 && tc_heuristic_recover==0) || total_ha_2pc>0);
if (total_ha_2pc == 0)
DBUG_RETURN(0);
#ifndef WILL_BE_DELETED_LATER
/*
for now, only InnoDB supports 2pc. It means we can always safely
rollback all pending transactions, without risking inconsistent data
*/
DBUG_ASSERT(total_ha_2pc == opt_bin_log+1); // only InnoDB and binlog
tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
dry_run=FALSE;
#endif
for (len= MAX_XID_LIST_SIZE ; list==0 && len > MIN_XID_LIST_SIZE; len/=2) for (len= MAX_XID_LIST_SIZE ; list==0 && len > MIN_XID_LIST_SIZE; len/=2)
{ {
...@@ -761,7 +793,7 @@ int ha_recover(HASH *commit_list) ...@@ -761,7 +793,7 @@ int ha_recover(HASH *commit_list)
} }
if (!list) if (!list)
{ {
my_error(ER_OUTOFMEMORY, MYF(0), len); sql_print_error(ER(ER_OUTOFMEMORY), len*sizeof(XID));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -775,7 +807,16 @@ int ha_recover(HASH *commit_list) ...@@ -775,7 +807,16 @@ int ha_recover(HASH *commit_list)
{ {
my_xid x=list[i].get_my_xid(); my_xid x=list[i].get_my_xid();
if (!x) // not "mine" - that is generated by external TM if (!x) // not "mine" - that is generated by external TM
{
found_foreign_xids++;
continue;
}
if (dry_run)
{
found_my_xids++;
continue; continue;
}
// recovery mode
if (commit_list ? if (commit_list ?
hash_search(commit_list, (byte *)&x, sizeof(x)) != 0 : hash_search(commit_list, (byte *)&x, sizeof(x)) != 0 :
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT) tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
...@@ -788,6 +829,19 @@ int ha_recover(HASH *commit_list) ...@@ -788,6 +829,19 @@ int ha_recover(HASH *commit_list)
} }
} }
my_free((gptr)list, MYF(0)); my_free((gptr)list, MYF(0));
if (found_foreign_xids)
sql_print_warning("Found %d prepared XA transactions", found_foreign_xids);
if (dry_run && found_my_xids)
{
sql_print_error("Found %d prepared transactions! It means that mysqld was "
"not shut down properly last time and critical recovery "
"information (last binlog or %s file) was manually deleted "
"after a crash. You have to start mysqld with "
"--tc-heuristic-recover switch to commit or rollback "
"pending transactions.",
found_my_xids, opt_tc_log_file);
DBUG_RETURN(1);
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1385,7 +1439,7 @@ ulonglong handler::get_auto_increment() ...@@ -1385,7 +1439,7 @@ ulonglong handler::get_auto_increment()
/* /*
Print error that we got from handler function Print error that we got from handler function
NOTE: NOTE
In case of delete table it's only safe to use the following parts of In case of delete table it's only safe to use the following parts of
the 'table' structure: the 'table' structure:
table->s->path table->s->path
......
...@@ -1033,7 +1033,7 @@ extern Le_creator le_creator; ...@@ -1033,7 +1033,7 @@ extern Le_creator le_creator;
extern char language[FN_REFLEN], reg_ext[FN_EXTLEN]; extern char language[FN_REFLEN], reg_ext[FN_EXTLEN];
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN]; extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file; extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
extern char log_error_file[FN_REFLEN]; extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
extern double last_query_cost; extern double last_query_cost;
extern double log_10[32]; extern double log_10[32];
extern ulonglong log_10_int[20]; extern ulonglong log_10_int[20];
......
...@@ -366,7 +366,7 @@ char* log_error_file_ptr= log_error_file; ...@@ -366,7 +366,7 @@ char* log_error_file_ptr= log_error_file;
char mysql_real_data_home[FN_REFLEN], char mysql_real_data_home[FN_REFLEN],
language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
*mysqld_user,*mysqld_chroot, *opt_init_file, *mysqld_user,*mysqld_chroot, *opt_init_file,
*opt_init_connect, *opt_init_slave, *opt_init_connect, *opt_init_slave, *opt_tc_log_file,
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
const char *opt_date_time_formats[3]; const char *opt_date_time_formats[3];
...@@ -457,7 +457,7 @@ static my_bool opt_do_pstack, opt_noacl, opt_bootstrap, opt_myisam_log; ...@@ -457,7 +457,7 @@ static my_bool opt_do_pstack, opt_noacl, opt_bootstrap, opt_myisam_log;
static int cleanup_done; static int cleanup_done;
static ulong opt_specialflag, opt_myisam_block_size; static ulong opt_specialflag, opt_myisam_block_size;
static char *opt_logname, *opt_update_logname, *opt_binlog_index_name; static char *opt_logname, *opt_update_logname, *opt_binlog_index_name;
static char *opt_slow_logname, *opt_tc_log_file, *opt_tc_heuristic_recover; static char *opt_slow_logname, *opt_tc_heuristic_recover;
static char *mysql_home_ptr, *pidfile_name_ptr; static char *mysql_home_ptr, *pidfile_name_ptr;
static char **defaults_argv; static char **defaults_argv;
static char *opt_bin_logname; static char *opt_bin_logname;
...@@ -2800,6 +2800,11 @@ server."); ...@@ -2800,6 +2800,11 @@ server.");
unireg_abort(1); unireg_abort(1);
} }
if (ha_recover(0))
{
unireg_abort(1);
}
if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
WRITE_CACHE, 0, max_binlog_size, 0)) WRITE_CACHE, 0, max_binlog_size, 0))
unireg_abort(1); unireg_abort(1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment