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)
/*
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 len, got;
int len, got, found_foreign_xids=0, found_my_xids=0;
handlerton **ht= handlertons, **end_ht=ht+total_ha;
XID *list=0;
bool dry_run=(commit_list==0 && tc_heuristic_recover==0);
DBUG_ENTER("ha_recover");
DBUG_ASSERT(total_ha_2pc);
DBUG_ASSERT(commit_list || tc_heuristic_recover);
/* commit_list and tc_heuristic_recover cannot be set both */
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)
{
......@@ -761,7 +793,7 @@ int ha_recover(HASH *commit_list)
}
if (!list)
{
my_error(ER_OUTOFMEMORY, MYF(0), len);
sql_print_error(ER(ER_OUTOFMEMORY), len*sizeof(XID));
DBUG_RETURN(1);
}
......@@ -775,7 +807,16 @@ int ha_recover(HASH *commit_list)
{
my_xid x=list[i].get_my_xid();
if (!x) // not "mine" - that is generated by external TM
{
found_foreign_xids++;
continue;
}
if (dry_run)
{
found_my_xids++;
continue;
}
// recovery mode
if (commit_list ?
hash_search(commit_list, (byte *)&x, sizeof(x)) != 0 :
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
......@@ -788,6 +829,19 @@ int ha_recover(HASH *commit_list)
}
}
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);
}
......@@ -1385,7 +1439,7 @@ ulonglong handler::get_auto_increment()
/*
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
the 'table' structure:
table->s->path
......
......@@ -1033,7 +1033,7 @@ extern Le_creator le_creator;
extern char language[FN_REFLEN], reg_ext[FN_EXTLEN];
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 log_error_file[FN_REFLEN];
extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
extern double last_query_cost;
extern double log_10[32];
extern ulonglong log_10_int[20];
......
......@@ -366,7 +366,7 @@ char* log_error_file_ptr= log_error_file;
char mysql_real_data_home[FN_REFLEN],
language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
*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)];
const char *opt_date_time_formats[3];
......@@ -457,7 +457,7 @@ static my_bool opt_do_pstack, opt_noacl, opt_bootstrap, opt_myisam_log;
static int cleanup_done;
static ulong opt_specialflag, opt_myisam_block_size;
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 **defaults_argv;
static char *opt_bin_logname;
......@@ -2800,6 +2800,11 @@ server.");
unireg_abort(1);
}
if (ha_recover(0))
{
unireg_abort(1);
}
if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
WRITE_CACHE, 0, max_binlog_size, 0))
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