Commit 99e581ec authored by serg@serg.mylan's avatar serg@serg.mylan

sql/ha_innodb.cc

    protect prepare-...-commit with a mutex to ensure that commits in binlog and in the innodb have the same order
    store binlog position with the commit
parent f8ed839c
...@@ -390,8 +390,9 @@ struct trx_struct{ ...@@ -390,8 +390,9 @@ struct trx_struct{
dulint table_id; /* table id if the preceding field is dulint table_id; /* table id if the preceding field is
TRUE */ TRUE */
/*------------------------------*/ /*------------------------------*/
int active_trans; /* whether a transaction in MySQL int active_trans; /* 1 - if a transaction in MySQL
is active */ is active. 2 - if prepare_commit_mutex
was taken */
void* mysql_thd; /* MySQL thread handle corresponding void* mysql_thd; /* MySQL thread handle corresponding
to this trx, or NULL */ to this trx, or NULL */
char** mysql_query_str;/* pointer to the field in mysqld_thd char** mysql_query_str;/* pointer to the field in mysqld_thd
......
...@@ -45,7 +45,8 @@ have disables the InnoDB inlining in this file. */ ...@@ -45,7 +45,8 @@ have disables the InnoDB inlining in this file. */
#include "ha_innodb.h" #include "ha_innodb.h"
pthread_mutex_t innobase_mutex; pthread_mutex_t innobase_share_mutex, // to protect innobase_open_files
prepare_commit_mutex; // to force correct commit order in binlog
bool innodb_inited= 0; bool innodb_inited= 0;
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB /* Store MySQL definition of 'byte': in Linux it is char while InnoDB
...@@ -1266,7 +1267,8 @@ innobase_init(void) ...@@ -1266,7 +1267,8 @@ innobase_init(void)
(void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0, (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
(hash_get_key) innobase_get_key, 0, 0); (hash_get_key) innobase_get_key, 0, 0);
pthread_mutex_init(&innobase_mutex, MY_MUTEX_INIT_FAST); pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
innodb_inited= 1; innodb_inited= 1;
/* If this is a replication slave and we needed to do a crash recovery, /* If this is a replication slave and we needed to do a crash recovery,
...@@ -1320,7 +1322,8 @@ innobase_end(void) ...@@ -1320,7 +1322,8 @@ innobase_end(void)
hash_free(&innobase_open_tables); hash_free(&innobase_open_tables);
my_free(internal_innobase_data_file_path, my_free(internal_innobase_data_file_path,
MYF(MY_ALLOW_ZERO_PTR)); MYF(MY_ALLOW_ZERO_PTR));
pthread_mutex_destroy(&innobase_mutex); pthread_mutex_destroy(&innobase_share_mutex);
pthread_mutex_destroy(&prepare_commit_mutex);
} }
DBUG_RETURN(err); DBUG_RETURN(err);
...@@ -1478,9 +1481,20 @@ innobase_commit( ...@@ -1478,9 +1481,20 @@ innobase_commit(
/* We were instructed to commit the whole transaction, or /* We were instructed to commit the whole transaction, or
this is an SQL statement end and autocommit is on */ this is an SQL statement end and autocommit is on */
/* We need current binlog position for HotBackup to work.
Note, the position is current because of prepare_commit_mutex */
trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
trx->mysql_log_offset =
(ib_longlong)mysql_bin_log.get_log_file()->pos_in_file;
innobase_commit_low(trx); innobase_commit_low(trx);
if (trx->active_trans == 2) {
pthread_mutex_unlock(&prepare_commit_mutex);
}
trx->active_trans = 0; trx->active_trans = 0;
} else { } else {
/* We just mark the SQL statement ended and do not do a /* We just mark the SQL statement ended and do not do a
transaction commit */ transaction commit */
...@@ -5842,7 +5856,7 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length, ...@@ -5842,7 +5856,7 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
static INNOBASE_SHARE *get_share(const char *table_name) static INNOBASE_SHARE *get_share(const char *table_name)
{ {
INNOBASE_SHARE *share; INNOBASE_SHARE *share;
pthread_mutex_lock(&innobase_mutex); pthread_mutex_lock(&innobase_share_mutex);
uint length=(uint) strlen(table_name); uint length=(uint) strlen(table_name);
if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables, if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
(mysql_byte*) table_name, (mysql_byte*) table_name,
...@@ -5856,7 +5870,7 @@ static INNOBASE_SHARE *get_share(const char *table_name) ...@@ -5856,7 +5870,7 @@ static INNOBASE_SHARE *get_share(const char *table_name)
strmov(share->table_name,table_name); strmov(share->table_name,table_name);
if (my_hash_insert(&innobase_open_tables, (mysql_byte*) share)) if (my_hash_insert(&innobase_open_tables, (mysql_byte*) share))
{ {
pthread_mutex_unlock(&innobase_mutex); pthread_mutex_unlock(&innobase_share_mutex);
my_free((gptr) share,0); my_free((gptr) share,0);
return 0; return 0;
} }
...@@ -5865,13 +5879,13 @@ static INNOBASE_SHARE *get_share(const char *table_name) ...@@ -5865,13 +5879,13 @@ static INNOBASE_SHARE *get_share(const char *table_name)
} }
} }
share->use_count++; share->use_count++;
pthread_mutex_unlock(&innobase_mutex); pthread_mutex_unlock(&innobase_share_mutex);
return share; return share;
} }
static void free_share(INNOBASE_SHARE *share) static void free_share(INNOBASE_SHARE *share)
{ {
pthread_mutex_lock(&innobase_mutex); pthread_mutex_lock(&innobase_share_mutex);
if (!--share->use_count) if (!--share->use_count)
{ {
hash_delete(&innobase_open_tables, (mysql_byte*) share); hash_delete(&innobase_open_tables, (mysql_byte*) share);
...@@ -5879,7 +5893,7 @@ static void free_share(INNOBASE_SHARE *share) ...@@ -5879,7 +5893,7 @@ static void free_share(INNOBASE_SHARE *share)
pthread_mutex_destroy(&share->mutex); pthread_mutex_destroy(&share->mutex);
my_free((gptr) share, MYF(0)); my_free((gptr) share, MYF(0));
} }
pthread_mutex_unlock(&innobase_mutex); pthread_mutex_unlock(&innobase_share_mutex);
} }
/********************************************************************* /*********************************************************************
...@@ -6318,15 +6332,19 @@ innobase_xa_prepare( ...@@ -6318,15 +6332,19 @@ innobase_xa_prepare(
FALSE - the current SQL statement ended */ FALSE - the current SQL statement ended */
{ {
int error = 0; int error = 0;
trx_t* trx; trx_t* trx = check_trx_exists(thd);
if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
pthread_mutex_lock(&prepare_commit_mutex);
trx->active_trans = 2;
}
if (!thd->variables.innodb_support_xa) { if (!thd->variables.innodb_support_xa) {
return(0); return(0);
} }
trx = check_trx_exists(thd);
trx->xid=thd->transaction.xid; trx->xid=thd->transaction.xid;
/* Release a possible FIFO ticket and search latch. Since we will /* Release a possible FIFO ticket and search latch. Since we will
......
...@@ -526,7 +526,6 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg) ...@@ -526,7 +526,6 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
/* /*
RETURN RETURN
-1 - cannot prepare
0 - ok 0 - ok
1 - error, transaction was rolled back 1 - error, transaction was rolled back
*/ */
...@@ -539,8 +538,6 @@ int ha_prepare(THD *thd) ...@@ -539,8 +538,6 @@ int ha_prepare(THD *thd)
#ifdef USING_TRANSACTIONS #ifdef USING_TRANSACTIONS
if (trans->nht) if (trans->nht)
{ {
if (trans->no_2pc)
DBUG_RETURN(-1);
for (; *ht; ht++) for (; *ht; ht++)
{ {
int err; int err;
......
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