mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
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
This commit is contained in:
@ -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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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;
|
continue;
|
||||||
|
}
|
||||||
|
if (dry_run)
|
||||||
|
{
|
||||||
|
found_my_xids++;
|
||||||
|
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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()
|
|||||||
/*
|
/*
|
||||||
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;
|
|||||||
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;
|
|||||||
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;
|
|||||||
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.");
|
|||||||
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);
|
||||||
|
Reference in New Issue
Block a user