Jan Lindström <jplindst@mariadb.org> writes:
Here is necessary changes. I have run whole mysql-test-run and I did not see any failures, thus is is mostly safe. I say mostly, because we really do not have much test cases that would use multimaster setup and try to get conflicting transactions generated from local clients against slave thread.
Thanks a lot! I will try to come up with some test cases for this, with replication and external transactions that conflict and show the problem. In parallel, I tried running the parallel replication slaves with READ COMMITTED; that also seems to work and can get Elena able to continue testing. But this change is potentially more correct; I will let you know when I have some test results. - Kristian.
=================================
jan@jan-GE70-0NC-0ND ~/mysql/10.0-mdev5914 $ bzr diff === modified file 'include/mysql/plugin.h' --- include/mysql/plugin.h 2014-02-26 14:28:07 +0000 +++ include/mysql/plugin.h 2014-03-21 09:05:58 +0000 @@ -617,6 +617,7 @@ int thd_in_lock_tables(const MYSQL_THD thd); int thd_tablespace_op(const MYSQL_THD thd); long long thd_test_options(const MYSQL_THD thd, long long test_options); +unsigned long long thd_group_commit_id(const MYSQL_THD thd); int thd_sql_command(const MYSQL_THD thd); void **thd_ha_data(const MYSQL_THD thd, const struct handlerton *hton); void thd_storage_lock_wait(MYSQL_THD thd, long long value);
=== modified file 'include/mysql/plugin_audit.h.pp' --- include/mysql/plugin_audit.h.pp 2013-12-22 16:11:20 +0000 +++ include/mysql/plugin_audit.h.pp 2014-03-21 09:06:17 +0000 @@ -298,6 +298,7 @@ int thd_in_lock_tables(const void* thd); int thd_tablespace_op(const void* thd); long long thd_test_options(const void* thd, long long test_options); +unsigned long long thd_group_commit_id(const void* thd); int thd_sql_command(const void* thd); void **thd_ha_data(const void* thd, const struct handlerton *hton); void thd_storage_lock_wait(void* thd, long long value);
=== modified file 'include/mysql/plugin_auth.h.pp' --- include/mysql/plugin_auth.h.pp 2013-12-22 16:11:20 +0000 +++ include/mysql/plugin_auth.h.pp 2014-03-21 09:06:35 +0000 @@ -298,6 +298,7 @@ int thd_in_lock_tables(const void* thd); int thd_tablespace_op(const void* thd); long long thd_test_options(const void* thd, long long test_options); +unsigned long long thd_group_commit_id(const void* thd); int thd_sql_command(const void* thd); void **thd_ha_data(const void* thd, const struct handlerton *hton); void thd_storage_lock_wait(void* thd, long long value);
=== modified file 'include/mysql/plugin_ftparser.h.pp' --- include/mysql/plugin_ftparser.h.pp 2013-12-22 16:11:20 +0000 +++ include/mysql/plugin_ftparser.h.pp 2014-03-21 09:06:59 +0000 @@ -251,6 +251,7 @@ int thd_in_lock_tables(const void* thd); int thd_tablespace_op(const void* thd); long long thd_test_options(const void* thd, long long test_options); +unsigned long long thd_group_commit_id(const void* thd); int thd_sql_command(const void* thd); void **thd_ha_data(const void* thd, const struct handlerton *hton); void thd_storage_lock_wait(void* thd, long long value);
=== modified file 'sql/sql_class.cc' --- sql/sql_class.cc 2014-03-20 14:36:45 +0000 +++ sql/sql_class.cc 2014-03-21 09:07:12 +0000 @@ -675,6 +675,12 @@ }
extern "C" +unsigned long long thd_group_commit_id(const THD *thd) +{ + return thd->rpl_group_commit_id; +} + +extern "C" int thd_sql_command(const THD *thd) { return (int) thd->lex->sql_command;
=== modified file 'storage/innobase/handler/ha_innodb.cc' --- storage/innobase/handler/ha_innodb.cc 2014-02-26 18:36:33 +0000 +++ storage/innobase/handler/ha_innodb.cc 2014-03-20 15:42:27 +0000 @@ -2048,6 +2048,8 @@ trx->check_unique_secondary = !thd_test_options( thd, OPTION_RELAXED_UNIQUE_CHECKS);
+ trx->group_commit_id = thd_group_commit_id(thd); + DBUG_VOID_RETURN; }
=== modified file 'storage/innobase/include/trx0trx.h' --- storage/innobase/include/trx0trx.h 2014-02-26 18:36:33 +0000 +++ storage/innobase/include/trx0trx.h 2014-03-20 15:28:19 +0000 @@ -840,6 +840,7 @@ or the state last time became TRX_STATE_ACTIVE */ trx_id_t id; /*!< transaction id */ + ib_uint64_t group_commit_id;/*!< Group commit id or 0 */ XID xid; /*!< X/Open XA transaction identification to identify a transaction branch */
=== modified file 'storage/innobase/lock/lock0lock.cc' --- storage/innobase/lock/lock0lock.cc 2014-02-26 18:22:48 +0000 +++ storage/innobase/lock/lock0lock.cc 2014-03-21 09:32:54 +0000 @@ -1020,6 +1020,23 @@ return(FALSE); }
+ if (trx->group_commit_id != 0 && + lock2->trx->group_commit_id != 0 && + trx->group_commit_id == lock2->trx->group_commit_id && + (type_mode & LOCK_GAP || lock_rec_get_gap(lock2))) { + /* No lock request needs to wait GAP locks if + transactions belong to the same group commit group. + This is because we have already verified these + transactions on master that they do not conflict + on record locks but as they could be executed on + different order on slave we should not wait for + gap locks here. Note that parallel replication + makes sure that transaction commits are executed + in the same order in master and slave. */ + + return (FALSE); + } + return(TRUE); }
=== modified file 'storage/xtradb/handler/ha_innodb.cc' --- storage/xtradb/handler/ha_innodb.cc 2014-02-26 18:21:23 +0000 +++ storage/xtradb/handler/ha_innodb.cc 2014-03-20 15:42:41 +0000 @@ -2308,6 +2308,8 @@
trx->fake_changes = THDVAR(thd, fake_changes);
+ trx->group_commit_id = thd_group_commit_id(thd); + #ifdef EXTENDED_SLOWLOG if (thd_log_slow_verbosity(thd) & (1ULL << SLOG_V_INNODB)) { trx->take_stats = TRUE;
=== modified file 'storage/xtradb/include/trx0trx.h' --- storage/xtradb/include/trx0trx.h 2014-02-26 18:21:23 +0000 +++ storage/xtradb/include/trx0trx.h 2014-03-20 15:28:20 +0000 @@ -861,6 +861,7 @@ or the state last time became TRX_STATE_ACTIVE */ trx_id_t id; /*!< transaction id */ + ib_uint64_t group_commit_id;/*!< Group commit id or 0 */ XID xid; /*!< X/Open XA transaction identification to identify a transaction branch */
=== modified file 'storage/xtradb/lock/lock0lock.cc' --- storage/xtradb/lock/lock0lock.cc 2013-12-22 16:06:50 +0000 +++ storage/xtradb/lock/lock0lock.cc 2014-03-21 09:32:46 +0000 @@ -1021,6 +1021,23 @@ return(FALSE); }
+ if (trx->group_commit_id != 0 && + lock2->trx->group_commit_id != 0 && + trx->group_commit_id == lock2->trx->group_commit_id && + (type_mode & LOCK_GAP || lock_rec_get_gap(lock2))) { + /* No lock request needs to wait GAP locks if + transactions belong to the same group commit group. + This is because we have already verified these + transactions on master that they do not conflict + on record locks but as they could be executed on + different order on slave we should not wait for + gap locks here. Note that parallel replication + makes sure that transaction commits are executed + in the same order in master and slave. */ + + return (FALSE); + } + return(TRUE); }