summaryrefslogtreecommitdiff
path: root/storage/xtradb
diff options
context:
space:
mode:
authorNirbhay Choubey <nirbhay@skysql.com>2014-03-26 15:17:51 -0400
committerNirbhay Choubey <nirbhay@skysql.com>2014-03-26 15:17:51 -0400
commit09e3094945694277a550cccc8bd1fd11338474b1 (patch)
tree9ce09379a64d7d2ca4486beb89346eb99c3da6d0 /storage/xtradb
parentc509f48b8e9cd0714154722aee2c9b8e62d1bc94 (diff)
parent71dafbf9c2cae382c5174bd3ce73472b97013d62 (diff)
downloadmariadb-git-09e3094945694277a550cccc8bd1fd11338474b1.tar.gz
Merging wsrep specific changes from InnoDB to
xtradb (r3683..3808).
Diffstat (limited to 'storage/xtradb')
-rw-r--r--storage/xtradb/handler/ha_innodb.cc40
-rw-r--r--storage/xtradb/handler/ha_innodb.h69
-rw-r--r--storage/xtradb/include/ha_prototypes.h28
-rw-r--r--storage/xtradb/include/sync0sync.ic3
-rw-r--r--storage/xtradb/include/trx0sys.h34
-rw-r--r--storage/xtradb/include/trx0sys.ic3
-rw-r--r--storage/xtradb/lock/lock0lock.cc44
-rw-r--r--storage/xtradb/row/row0ins.cc23
-rw-r--r--storage/xtradb/row/row0upd.cc382
-rw-r--r--storage/xtradb/srv/srv0conc.cc62
-rw-r--r--storage/xtradb/trx/trx0sys.cc46
-rw-r--r--storage/xtradb/trx/trx0trx.cc2
12 files changed, 450 insertions, 286 deletions
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index e963e07cc2c..61287e73acc 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -1471,15 +1471,14 @@ innobase_srv_conc_exit_innodb(
/*==========================*/
trx_t* trx) /*!< in: transaction handle */
{
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return;
#endif /* WITH_WSREP */
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
-#endif /* UNIV_SYNC_DEBUG */
-
/* This is to avoid making an unnecessary function call. */
if (trx->declared_to_be_inside_innodb
&& trx->n_tickets_to_enter_innodb == 0) {
@@ -3968,6 +3967,11 @@ innobase_commit_low(
/*================*/
trx_t* trx) /*!< in: transaction handle */
{
+ if (trx_is_started(trx)) {
+
+ trx_commit_for_mysql(trx);
+ }
+
#ifdef WITH_WSREP
THD* thd = (THD*)trx->mysql_thd;
const char* tmp = 0;
@@ -3986,11 +3990,6 @@ innobase_commit_low(
}
#endif /* WITH_WSREP */
- if (trx_is_started(trx)) {
-
- trx_commit_for_mysql(trx);
- }
-
#ifdef WITH_WSREP
if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); }
#endif /* WITH_WSREP */
@@ -6048,8 +6047,13 @@ wsrep_innobase_mysql_sort(
ut_a(str_length <= tmp_length);
memcpy(tmp_str, str, str_length);
+ //tmp_length = charset->coll->strnxfrm(charset, str, str_length,
+ // tmp_str, str_length);
+ /* Note: in MySQL 5.6:
+ */
tmp_length = charset->coll->strnxfrm(charset, str, str_length,
- str_length, tmp_str, tmp_length, 0);
+ str_length, tmp_str, tmp_length, 0);
+ /**/
DBUG_ASSERT(tmp_length == str_length);
break;
@@ -6592,10 +6596,10 @@ innobase_read_from_2_little_endian(
return((uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1]))));
}
-#ifdef WITH_WSREP
/*******************************************************************//**
Stores a key value for a row to a buffer.
@return key value length as stored in buff */
+#ifdef WITH_WSREP
UNIV_INTERN
uint
wsrep_store_key_val_for_row(
@@ -8559,7 +8563,8 @@ func_exit:
innobase_active_small();
#ifdef WITH_WSREP
- if (!err && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
+ if (error == DB_SUCCESS &&
+ wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
wsrep_on(user_thd)) {
DBUG_PRINT("wsrep", ("update row key"));
@@ -17830,8 +17835,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
WSREP_DEBUG("kill query for: %ld",
wsrep_thd_thread_id(thd));
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu",
victim_trx->id);
@@ -17848,6 +17851,8 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
case WSREP_WARNING:
WSREP_DEBUG("cancel commit warning: %llu",
victim_trx->id);
+ wsrep_thd_UNLOCK(thd);
+ wsrep_thd_awake(thd, signal);
DBUG_RETURN(1);
break;
case WSREP_OK:
@@ -17865,6 +17870,8 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
break;
}
}
+ wsrep_thd_UNLOCK(thd);
+ wsrep_thd_awake(thd, signal);
break;
case QUERY_EXEC:
/* it is possible that victim trx is itself waiting for some
@@ -17883,7 +17890,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
lock_cancel_waiting_and_release(wait_lock);
}
- wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal);
} else {
/* abort currently executing query */
@@ -17891,7 +17897,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
wsrep_thd_thread_id(thd)));
WSREP_DEBUG("kill query for: %ld",
wsrep_thd_thread_id(thd));
- wsrep_thd_UNLOCK(thd);
/* Note that innobase_kill_connection will take lock_mutex
and trx_mutex */
wsrep_thd_awake(thd, signal);
@@ -17950,16 +17955,15 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
WSREP_DEBUG("signaling aborter");
mysql_cond_signal(&COND_wsrep_rollback);
mysql_mutex_unlock(&LOCK_wsrep_rollback);
- wsrep_thd_UNLOCK(thd);
break;
}
default:
WSREP_WARN("bad wsrep query state: %d",
wsrep_thd_query_state(thd));
- wsrep_thd_UNLOCK(thd);
break;
}
+ wsrep_thd_UNLOCK(thd);
DBUG_RETURN(0);
}
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index 9c4a715642a..103b72dd4f9 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -458,6 +458,40 @@ __attribute__((nonnull));
extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file);
struct trx_t;
+#ifdef WITH_WSREP
+#include <wsrep_mysqld.h>
+//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2);
+
+extern "C" bool wsrep_thd_is_wsrep_on(THD *thd);
+
+extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd);
+extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd);
+extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd);
+extern "C" const char * wsrep_thd_exec_mode_str(THD *thd);
+extern "C" const char * wsrep_thd_conflict_state_str(THD *thd);
+extern "C" const char * wsrep_thd_query_state_str(THD *thd);
+extern "C" wsrep_ws_handle_t* wsrep_thd_ws_handle(THD *thd);
+
+extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
+extern "C" void wsrep_thd_set_query_state(
+ THD *thd, enum wsrep_query_state state);
+extern "C" void wsrep_thd_set_conflict_state(
+ THD *thd, enum wsrep_conflict_state state);
+
+extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id);
+
+extern "C"void wsrep_thd_LOCK(THD *thd);
+extern "C"void wsrep_thd_UNLOCK(THD *thd);
+extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd);
+extern "C" time_t wsrep_thd_query_start(THD *thd);
+extern "C" my_thread_id wsrep_thd_thread_id(THD *thd);
+extern "C" int64_t wsrep_thd_trx_seqno(THD *thd);
+extern "C" query_id_t wsrep_thd_query_id(THD *thd);
+extern "C" char * wsrep_thd_query(THD *thd);
+extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
+extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
+extern "C" void wsrep_thd_awake(THD* thd, my_bool signal);
+#endif
extern const struct _ft_vft ft_vft_result;
@@ -495,6 +529,9 @@ innobase_index_name_is_reserved(
__attribute__((nonnull, warn_unused_result));
/*****************************************************************//**
+#ifdef WITH_WSREP
+extern "C" int wsrep_trx_is_aborting(void *thd_ptr);
+#endif
Determines InnoDB table flags.
@retval true if successful, false if error */
UNIV_INTERN
@@ -657,35 +694,3 @@ innobase_copy_frm_flags_from_table_share(
/*=====================================*/
dict_table_t* innodb_table, /*!< in/out: InnoDB table */
const TABLE_SHARE* table_share); /*!< in: table share */
-
-#ifdef WITH_WSREP
-#include <wsrep_mysqld.h>
-//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2);
-extern "C" int wsrep_trx_is_aborting(void *thd_ptr);
-
-extern "C" bool wsrep_thd_is_wsrep_on(THD *thd);
-
-extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd);
-extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd);
-extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd);
-
-extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
-extern "C" void wsrep_thd_set_query_state(
- THD *thd, enum wsrep_query_state state);
-extern "C" void wsrep_thd_set_conflict_state(
- THD *thd, enum wsrep_conflict_state state);
-
-extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id);
-
-extern "C"void wsrep_thd_LOCK(THD *thd);
-extern "C"void wsrep_thd_UNLOCK(THD *thd);
-extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd);
-extern "C" time_t wsrep_thd_query_start(THD *thd);
-extern "C" my_thread_id wsrep_thd_thread_id(THD *thd);
-extern "C" int64_t wsrep_thd_trx_seqno(THD *thd);
-extern "C" query_id_t wsrep_thd_query_id(THD *thd);
-extern "C" char * wsrep_thd_query(THD *thd);
-extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
-extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
-extern "C" void wsrep_thd_awake(THD *thd, my_bool signal);
-#endif
diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index d1652c1f0d8..7d8224820c6 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -285,6 +285,19 @@ innobase_casedn_str(
/*================*/
char* a); /*!< in/out: string to put in lower case */
+#ifdef WITH_WSREP
+UNIV_INTERN
+int
+wsrep_innobase_kill_one_trx(void *thd_ptr,
+ const trx_t *bf_trx, trx_t *victim_trx, ibool signal);
+extern "C" int wsrep_thd_is_brute_force(void *thd_ptr);
+int wsrep_trx_order_before(void *thd1, void *thd2);
+void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
+ unsigned char* str, unsigned int str_length);
+int
+wsrep_on(void *thd_ptr);
+extern "C" int wsrep_is_wsrep_xid(const void*);
+#endif /* WITH_WSREP */
/**********************************************************************//**
Determines the connection character set.
@return connection character set */
@@ -375,21 +388,6 @@ thd_flush_log_at_trx_commit(
/*================================*/
void* thd);
-#ifdef WITH_WSREP
-UNIV_INTERN
-int
-wsrep_innobase_kill_one_trx(void *thd_ptr,
- const trx_t *bf_trx, trx_t *victim_trx, ibool signal);
-
-extern "C" int wsrep_thd_is_brute_force(void *thd_ptr);
-int wsrep_trx_order_before(void *thd1, void *thd2);
-void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
- unsigned char* str, unsigned int str_length);
-//UNIV_INTERN
-int
-wsrep_on(void *thd_ptr);
-extern "C" int wsrep_is_wsrep_xid(const void*);
-#endif /* WITH_WSREP */
/**********************************************************************//**
Get the current setting of the lower_case_table_names global parameter from
mysqld.cc. We do a dirty read because for one there is no synchronization
diff --git a/storage/xtradb/include/sync0sync.ic b/storage/xtradb/include/sync0sync.ic
index d6a95156ff4..0c9d530abcb 100644
--- a/storage/xtradb/include/sync0sync.ic
+++ b/storage/xtradb/include/sync0sync.ic
@@ -255,7 +255,10 @@ mutex_enter_func(
ulint line) /*!< in: line where locked */
{
ut_ad(mutex_validate(mutex));
+#ifndef WITH_WSREP
+ /* this cannot be be granted when BF trx kills a trx in lock wait state */
ut_ad(!mutex_own(mutex));
+#endif /* WITH_WSREP */
/* Note that we do not peek at the value of lock_word before trying
the atomic test_and_set; we could peek, and possibly save time. */
diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h
index 48da2bfcc3c..7892fdd0bf1 100644
--- a/storage/xtradb/include/trx0sys.h
+++ b/storage/xtradb/include/trx0sys.h
@@ -41,10 +41,10 @@ Created 3/26/1996 Heikki Tuuri
#include "ut0bh.h"
#include "read0types.h"
#include "page0types.h"
+#include "ut0bh.h"
#ifdef WITH_WSREP
#include "trx0xa.h"
#endif /* WITH_WSREP */
-#include "ut0bh.h"
typedef UT_LIST_BASE_NODE_T(trx_t) trx_list_t;
@@ -328,6 +328,19 @@ UNIV_INTERN
void
trx_sys_print_mysql_binlog_offset(void);
/*===================================*/
+#ifdef WITH_WSREP
+/** Update WSREP checkpoint XID in sys header. */
+void
+trx_sys_update_wsrep_checkpoint(
+ const XID* xid, /*!< in: WSREP XID */
+ trx_sysf_t* sys_header, /*!< in: sys_header */
+ mtr_t* mtr); /*!< in: mtr */
+
+void
+/** Read WSREP checkpoint XID from sys header. */
+trx_sys_read_wsrep_checkpoint(
+ XID* xid); /*!< out: WSREP XID */
+#endif /* WITH_WSREP */
/*****************************************************************//**
Prints to stderr the MySQL master log offset info in the trx system header if
the magic number shows it valid. */
@@ -485,19 +498,6 @@ trx_sys_validate_trx_list(void);
/*===========================*/
#endif /* UNIV_DEBUG */
-#ifdef WITH_WSREP
-/** Update WSREP checkpoint XID in sys header. */
-void
-trx_sys_update_wsrep_checkpoint(
- const XID* xid, /*!< in: WSREP XID */
- trx_sysf_t* sys_header, /*!< in: sys_header */
- mtr_t* mtr); /*!< in: mtr */
-void
-/** Read WSREP checkpoint XID from sys header. */
-trx_sys_read_wsrep_checkpoint(
- XID* xid); /*!< out: WSREP XID */
-#endif /* WITH_WSREP */
-
/* The automatically created system rollback segment has this id */
#define TRX_SYS_SYSTEM_RSEG_ID 0
@@ -570,10 +570,8 @@ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
#define TRX_SYS_MYSQL_LOG_NAME 12 /*!< MySQL log file name */
#ifdef WITH_WSREP
-/* We hijack TRX_SYS_MYSQL_MASTER_LOG_INFO, it seems to be completely unused
- otherwise (see comments for MySQL bug #34058). */
-/** */
-#define TRX_SYS_WSREP_XID_INFO TRX_SYS_MYSQL_MASTER_LOG_INFO
+/* The offset to WSREP XID headers */
+#define TRX_SYS_WSREP_XID_INFO (UNIV_PAGE_SIZE - 3500)
#define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0
#define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265
diff --git a/storage/xtradb/include/trx0sys.ic b/storage/xtradb/include/trx0sys.ic
index 699148cff6d..6024c1dc94e 100644
--- a/storage/xtradb/include/trx0sys.ic
+++ b/storage/xtradb/include/trx0sys.ic
@@ -474,7 +474,10 @@ trx_id_t
trx_sys_get_new_trx_id(void)
/*========================*/
{
+#ifndef WITH_WSREP
+ /* wsrep_fake_trx_id violates this assert */
ut_ad(mutex_own(&trx_sys->mutex));
+#endif /* WITH_WSREP */
/* VERY important: after the database is started, max_trx_id value is
divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if
diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc
index 8773e2e1868..c6cb885ca4f 100644
--- a/storage/xtradb/lock/lock0lock.cc
+++ b/storage/xtradb/lock/lock0lock.cc
@@ -981,7 +981,6 @@ lock_rec_has_to_wait(
&& !lock_mode_compatible(static_cast<enum lock_mode>(
LOCK_MODE_MASK & type_mode),
lock_get_mode(lock2))) {
-
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
@@ -1021,7 +1020,7 @@ lock_rec_has_to_wait(
}
return FALSE;
}
- }
+ }
#endif /* WITH_WSREP */
/* We have somewhat complex rules when gap type record locks
@@ -1630,14 +1629,13 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */
#ifdef WITH_WSREP
-static void
-wsrep_kill_victim(trx_t *trx, lock_t *lock) {
+static
+void
+wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(lock->trx));
-
my_bool bf_this = wsrep_thd_is_brute_force(trx->mysql_thd);
my_bool bf_other = wsrep_thd_is_brute_force(lock->trx->mysql_thd);
-
if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
@@ -1677,12 +1675,11 @@ wsrep_kill_victim(trx_t *trx, lock_t *lock) {
}
}
wsrep_innobase_kill_one_trx(trx->mysql_thd,
- (const trx_t*)trx, lock->trx, TRUE);
+ (const trx_t*) trx, lock->trx, TRUE);
}
}
}
-#endif /* WITH_WSREP */
-
+#endif
/*********************************************************************//**
Checks if some other transaction has a conflicting explicit lock request
in the queue, so that we have to wait.
@@ -1719,6 +1716,7 @@ lock_rec_other_has_conflicting(
#else
if (lock_rec_has_to_wait(trx, mode, lock, is_supremum)) {
#endif /* WITH_WSREP */
+
return(lock);
}
}
@@ -1879,7 +1877,7 @@ lock_t*
lock_rec_create(
/*============*/
#ifdef WITH_WSREP
- lock_t* const c_lock, /* conflicting lock */
+ lock_t* const c_lock, /* conflicting lock */
que_thr_t* thr,
#endif
ulint type_mode,/*!< in: lock mode and wait
@@ -1940,8 +1938,8 @@ lock_rec_create(
lock->type_mode |= WSREP_BF;
}
#endif /* WITH_WSREP */
-
lock->index = index;
+
lock->un_member.rec_lock.space = space;
lock->un_member.rec_lock.page_no = page_no;
lock->un_member.rec_lock.n_bits = n_bytes * 8;
@@ -2144,7 +2142,7 @@ lock_rec_enqueue_waiting(
lock = lock_rec_create(
type_mode | LOCK_WAIT, block, heap_no,
index, trx, TRUE);
-#endif /* WITH_WSREP */
+#endif /*WITH_WSREP */
} else {
ut_ad(lock->type_mode & LOCK_WAIT);
ut_ad(lock->type_mode & LOCK_CONV_BY_OTHER);
@@ -2401,7 +2399,8 @@ lock_rec_lock_fast(
#else
lock = lock_rec_create(
mode, block, heap_no, index, trx, FALSE);
-#endif /* WITH_WSREP */
+#endif
+
}
status = LOCK_REC_SUCCESS_CREATED;
} else {
@@ -2454,11 +2453,11 @@ lock_rec_lock_slow(
que_thr_t* thr) /*!< in: query thread */
{
trx_t* trx;
- lock_t* lock;
- dberr_t err = DB_SUCCESS;
#ifdef WITH_WSREP
- lock_t* c_lock = NULL;
+ lock_t* c_lock(NULL);
#endif
+ lock_t* lock;
+ dberr_t err = DB_SUCCESS;
ut_ad(lock_mutex_own());
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
@@ -2533,6 +2532,7 @@ enqueue_waiting:
err = lock_rec_enqueue_waiting(
mode, block, heap_no, lock, index, thr);
#endif /* WITH_WSREP */
+
} else if (!impl) {
/* Set the requested lock on the record, note that
we already own the transaction mutex. */
@@ -4040,20 +4040,18 @@ lock_deadlock_select_victim(
if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) {
/* The joining transaction is 'smaller',
choose it as the victim and roll it back. */
-
#ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd))
return(ctx->start);
else
#endif /* WITH_WSREP */
- return(ctx->start);
+ return(ctx->start);
}
-
#ifdef WITH_WSREP
- if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd)) {
+ if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd))
return(ctx->start);
- }
-#endif
+ else
+#endif /* WITH_WSREP */
return(ctx->wait_lock->trx);
}
@@ -4426,6 +4424,7 @@ lock_table_create(
ut_ad(table->n_ref_count > 0 || !table->can_be_evicted);
UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
+
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
UT_LIST_INSERT_AFTER(
@@ -4464,7 +4463,6 @@ lock_table_create(
}
if (c_lock) trx_mutex_exit(c_lock->trx);
#else
-
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
#endif /* WITH_WSREP */
diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc
index d36d589e6c6..c29c1f56d3f 100644
--- a/storage/xtradb/row/row0ins.cc
+++ b/storage/xtradb/row/row0ins.cc
@@ -919,7 +919,7 @@ row_ins_invalidate_query_cache(
mem_free(buf);
}
#ifdef WITH_WSREP
-ulint wsrep_append_foreign_key(trx_t *trx,
+dberr_t wsrep_append_foreign_key(trx_t *trx,
dict_foreign_t* foreign,
const rec_t* clust_rec,
dict_index_t* clust_index,
@@ -1278,20 +1278,19 @@ row_ins_foreign_check_on_constraint(
cascade->state = UPD_NODE_UPDATE_CLUSTERED;
#ifdef WITH_WSREP
- err = (dberr_t)wsrep_append_foreign_key(
- thr_get_trx(thr),
- foreign,
- clust_rec,
- clust_index,
- FALSE, FALSE);
-
+ err = wsrep_append_foreign_key(
+ thr_get_trx(thr),
+ foreign,
+ clust_rec,
+ clust_index,
+ FALSE, FALSE);
if (err != DB_SUCCESS) {
fprintf(stderr,
"WSREP: foreign key append failed: %d\n", err);
} else
#endif /* WITH_WSREP */
err = row_update_cascade_for_mysql(thr, cascade,
- foreign->foreign_table);
+ foreign->foreign_table);
if (foreign->foreign_table->n_foreign_key_checks_running == 0) {
fprintf(stderr,
@@ -1629,11 +1628,11 @@ run_again:
if (check_ref) {
err = DB_SUCCESS;
#ifdef WITH_WSREP
- err = (dberr_t) wsrep_append_foreign_key(
+ err = wsrep_append_foreign_key(
thr_get_trx(thr),
foreign,
- rec,
- check_index,
+ rec,
+ check_index,
check_ref, TRUE);
#endif /* WITH_WSREP */
goto end_scan;
diff --git a/storage/xtradb/row/row0upd.cc b/storage/xtradb/row/row0upd.cc
index 9d40848c2fc..9b733410c00 100644
--- a/storage/xtradb/row/row0upd.cc
+++ b/storage/xtradb/row/row0upd.cc
@@ -176,25 +176,47 @@ func_exit:
}
#ifdef WITH_WSREP
-ulint
-wsrep_append_foreign_key(
- trx_t* trx,
- dict_foreign_t* foreign,
- const rec_t* clust_rec,
- dict_index_t* clust_index,
- ibool referenced,
- ibool shared);
+static
+ibool
+wsrep_row_upd_index_is_foreign(
+/*========================*/
+ dict_index_t* index, /*!< in: index */
+ trx_t* trx) /*!< in: transaction */
+{
+ dict_table_t* table = index->table;
+ dict_foreign_t* foreign;
+ ibool froze_data_dict = FALSE;
+ ibool is_referenced = FALSE;
-ulint
-wsrep_row_upd_check_foreign_constraints(
- upd_node_t* node, /*!< in: row update node */
- btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the
- cursor position is lost in this function! */
- dict_table_t* table, /*!< in: table in question */
- dict_index_t* index, /*!< in: index of the cursor */
- ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */
- que_thr_t* thr, /*!< in: query thread */
- mtr_t* mtr); /*!< in: mtr */
+ if (!UT_LIST_GET_FIRST(table->foreign_list)) {
+
+ return(FALSE);
+ }
+
+ if (trx->dict_operation_lock_mode == 0) {
+ row_mysql_freeze_data_dictionary(trx);
+ froze_data_dict = TRUE;
+ }
+
+ foreign = UT_LIST_GET_FIRST(table->foreign_list);
+
+ while (foreign) {
+ if (foreign->foreign_index == index) {
+
+ is_referenced = TRUE;
+ goto func_exit;
+ }
+
+ foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ }
+
+func_exit:
+ if (froze_data_dict) {
+ row_mysql_unfreeze_data_dictionary(trx);
+ }
+
+ return(is_referenced);
+}
#endif /* WITH_WSREP */
/*********************************************************************//**
@@ -314,7 +336,123 @@ run_again:
}
err = DB_SUCCESS;
+func_exit:
+ if (got_s_lock) {
+ row_mysql_unfreeze_data_dictionary(trx);
+ }
+
+ mem_heap_free(heap);
+
+ return(err);
+}
+#ifdef WITH_WSREP
+static
+dberr_t
+wsrep_row_upd_check_foreign_constraints(
+/*=================================*/
+ upd_node_t* node, /*!< in: row update node */
+ btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the
+ cursor position is lost in this function! */
+ dict_table_t* table, /*!< in: table in question */
+ dict_index_t* index, /*!< in: index of the cursor */
+ ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */
+ que_thr_t* thr, /*!< in: query thread */
+ mtr_t* mtr) /*!< in: mtr */
+{
+ dict_foreign_t* foreign;
+ mem_heap_t* heap;
+ dtuple_t* entry;
+ trx_t* trx;
+ const rec_t* rec;
+ ulint n_ext;
+ dberr_t err;
+ ibool got_s_lock = FALSE;
+
+ if (UT_LIST_GET_FIRST(table->foreign_list) == NULL) {
+
+ return(DB_SUCCESS);
+ }
+
+ trx = thr_get_trx(thr);
+
+ rec = btr_pcur_get_rec(pcur);
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
+ heap = mem_heap_create(500);
+
+ entry = row_rec_to_index_entry(rec, index, offsets,
+ &n_ext, heap);
+
+ mtr_commit(mtr);
+
+ mtr_start(mtr);
+
+ if (trx->dict_operation_lock_mode == 0) {
+ got_s_lock = TRUE;
+
+ row_mysql_freeze_data_dictionary(trx);
+ }
+
+ foreign = UT_LIST_GET_FIRST(table->foreign_list);
+
+ while (foreign) {
+ /* Note that we may have an update which updates the index
+ record, but does NOT update the first fields which are
+ referenced in a foreign key constraint. Then the update does
+ NOT break the constraint. */
+
+ if (foreign->foreign_index == index
+ && (node->is_delete
+ || row_upd_changes_first_fields_binary(
+ entry, index, node->update,
+ foreign->n_fields))) {
+
+ if (foreign->referenced_table == NULL) {
+ foreign->referenced_table =
+ dict_table_open_on_name(
+ foreign->referenced_table_name_lookup,
+ FALSE, FALSE, DICT_ERR_IGNORE_NONE);
+ }
+
+ if (foreign->referenced_table) {
+ mutex_enter(&(dict_sys->mutex));
+
+ (foreign->referenced_table
+ ->n_foreign_key_checks_running)++;
+
+ mutex_exit(&(dict_sys->mutex));
+ }
+
+ /* NOTE that if the thread ends up waiting for a lock
+ we will release dict_operation_lock temporarily!
+ But the counter on the table protects 'foreign' from
+ being dropped while the check is running. */
+
+ err = row_ins_check_foreign_constraint(
+ TRUE, foreign, table, entry, thr);
+
+ if (foreign->referenced_table) {
+ mutex_enter(&(dict_sys->mutex));
+
+ ut_a(foreign->referenced_table
+ ->n_foreign_key_checks_running > 0);
+
+ (foreign->referenced_table
+ ->n_foreign_key_checks_running)--;
+
+ mutex_exit(&(dict_sys->mutex));
+ }
+ if (err != DB_SUCCESS) {
+
+ goto func_exit;
+ }
+ }
+
+ foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ }
+
+ err = DB_SUCCESS;
func_exit:
if (got_s_lock) {
row_mysql_unfreeze_data_dictionary(trx);
@@ -326,6 +464,7 @@ func_exit:
return(err);
}
+#endif /* WITH_WSREP */
/*********************************************************************//**
Creates an update node for a query graph.
@@ -1700,6 +1839,9 @@ row_upd_sec_index_entry(
index = node->index;
referenced = row_upd_index_is_referenced(index, trx);
+#ifdef WITH_WSREP
+ ibool foreign = wsrep_row_upd_index_is_foreign(index, trx);
+#endif /* WITH_WSREP */
heap = mem_heap_create(1024);
@@ -1830,6 +1972,9 @@ row_upd_sec_index_entry(
row_ins_sec_index_entry() below */
if (!rec_get_deleted_flag(
rec, dict_table_is_comp(index->table))) {
+#ifdef WITH_WSREP
+ que_node_t *parent = que_node_get_parent(node);
+#endif /* WITH_WSREP */
err = btr_cur_del_mark_set_sec_rec(
0, btr_cur, TRUE, thr, &mtr);
@@ -1848,29 +1993,32 @@ row_upd_sec_index_entry(
index, offsets, thr, &mtr);
}
#ifdef WITH_WSREP
- if (err == DB_SUCCESS && !referenced) {
+ if (err == DB_SUCCESS && !referenced &&
+ !(parent && que_node_get_type(parent) ==
+ QUE_NODE_UPDATE &&
+ ((upd_node_t*)parent)->cascade_node == node) &&
+ foreign
+ ) {
ulint* offsets =
rec_get_offsets(
- rec, index, NULL, ULINT_UNDEFINED,
- &heap);
- err = (dberr_t) wsrep_row_upd_check_foreign_constraints(
+ rec, index, NULL, ULINT_UNDEFINED,
+ &heap);
+ err = wsrep_row_upd_check_foreign_constraints(
node, &pcur, index->table,
index, offsets, thr, &mtr);
-
switch (err) {
case DB_SUCCESS:
case DB_NO_REFERENCED_ROW:
err = DB_SUCCESS;
break;
case DB_DEADLOCK:
- if (wsrep_debug)
- fprintf (stderr,
- "WSREP: sec index FK check fail for deadlock");
+ if (wsrep_debug) fprintf (stderr,
+ "WSREP: sec index FK check fail for deadlock");
break;
default:
- fprintf (stderr,
- "WSREP: referenced FK check fail: %d",
- err);
+ fprintf (stderr,
+ "WSREP: referenced FK check fail: %d",
+ (int)err);
break;
}
}
@@ -2015,123 +2163,6 @@ row_upd_clust_rec_by_insert_inherit_func(
return(inherit);
}
-#ifdef WITH_WSREP
-ulint
-wsrep_row_upd_check_foreign_constraints(
-/*=================================*/
- upd_node_t* node, /*!< in: row update node */
- btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the
- cursor position is lost in this function! */
- dict_table_t* table, /*!< in: table in question */
- dict_index_t* index, /*!< in: index of the cursor */
- ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */
- que_thr_t* thr, /*!< in: query thread */
- mtr_t* mtr) /*!< in: mtr */
-{
- dict_foreign_t* foreign;
- mem_heap_t* heap;
- dtuple_t* entry;
- trx_t* trx;
- const rec_t* rec;
- ulint n_ext;
- ulint err;
- ibool got_s_lock = FALSE;
-
- if (UT_LIST_GET_FIRST(table->foreign_list) == NULL) {
-
- return(DB_SUCCESS);
- }
-
- trx = thr_get_trx(thr);
-
- rec = btr_pcur_get_rec(pcur);
- ut_ad(rec_offs_validate(rec, index, offsets));
-
- heap = mem_heap_create(500);
-
- entry = row_rec_to_index_entry(rec, index, offsets, &n_ext, heap);
-
- mtr_commit(mtr);
-
- mtr_start(mtr);
-
- if (trx->dict_operation_lock_mode == 0) {
- got_s_lock = TRUE;
-
- row_mysql_freeze_data_dictionary(trx);
- }
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign) {
- /* Note that we may have an update which updates the index
- record, but does NOT update the first fields which are
- referenced in a foreign key constraint. Then the update does
- NOT break the constraint. */
-
- if (foreign->foreign_index == index
- && (node->is_delete
- || row_upd_changes_first_fields_binary(
- entry, index, node->update,
- foreign->n_fields))) {
-
- if (foreign->referenced_table == NULL) {
- foreign->referenced_table =
- dict_table_open_on_name(
- foreign->referenced_table_name_lookup,
- FALSE, FALSE, DICT_ERR_IGNORE_NONE);
- }
-
- if (foreign->referenced_table) {
- mutex_enter(&(dict_sys->mutex));
-
- (foreign->referenced_table
- ->n_foreign_key_checks_running)++;
-
- mutex_exit(&(dict_sys->mutex));
- }
-
- /* NOTE that if the thread ends up waiting for a lock
- we will release dict_operation_lock temporarily!
- But the counter on the table protects 'foreign' from
- being dropped while the check is running. */
-
- err = row_ins_check_foreign_constraint(
- TRUE, foreign, table, entry, thr);
-
- if (foreign->referenced_table) {
- mutex_enter(&(dict_sys->mutex));
-
- ut_a(foreign->referenced_table
- ->n_foreign_key_checks_running > 0);
-
- (foreign->referenced_table
- ->n_foreign_key_checks_running)--;
-
- mutex_exit(&(dict_sys->mutex));
- }
-
- if (err != DB_SUCCESS) {
-
- goto func_exit;
- }
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
- err = DB_SUCCESS;
-func_exit:
- if (got_s_lock) {
- row_mysql_unfreeze_data_dictionary(trx);
- }
-
- mem_heap_free(heap);
-
- return(err);
-}
-#endif /* WITH_WSREP */
-
/***********************************************************//**
Marks the clustered index record deleted and inserts the updated version
of the record to the index. This function should be used when the ordering
@@ -2148,6 +2179,9 @@ row_upd_clust_rec_by_insert(
que_thr_t* thr, /*!< in: query thread */
ibool referenced,/*!< in: TRUE if index may be referenced in
a foreign key constraint */
+#ifdef WITH_WSREP
+ ibool foreign, /*!< in: TRUE if index is foreign key index */
+#endif /* WITH_WSREP */
mtr_t* mtr) /*!< in/out: mtr; gets committed here */
{
mem_heap_t* heap;
@@ -2161,6 +2195,9 @@ row_upd_clust_rec_by_insert(
rec_t* rec;
ulint* offsets = NULL;
+#ifdef WITH_WSREP
+ que_node_t *parent = que_node_get_parent(node);
+#endif /* WITH_WSREP */
ut_ad(node);
ut_ad(dict_index_is_clust(index));
@@ -2241,23 +2278,26 @@ err_exit:
}
}
#ifdef WITH_WSREP
- if (!referenced) {
- err = (dberr_t) wsrep_row_upd_check_foreign_constraints(
+ if (!referenced &&
+ !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE &&
+ ((upd_node_t*)parent)->cascade_node == node) &&
+ foreign
+ ) {
+ err = wsrep_row_upd_check_foreign_constraints(
node, pcur, table, index, offsets, thr, mtr);
-
switch (err) {
case DB_SUCCESS:
case DB_NO_REFERENCED_ROW:
err = DB_SUCCESS;
break;
case DB_DEADLOCK:
- if (wsrep_debug) fprintf (stderr,
+ if (wsrep_debug) fprintf (stderr,
"WSREP: insert FK check fail for deadlock");
break;
default:
fprintf (stderr,
- "WSREP: referenced FK check fail: %d",
- err);
+ "WSREP: referenced FK check fail: %d",
+ (int)err);
break;
}
if (err != DB_SUCCESS) {
@@ -2495,6 +2535,9 @@ row_upd_del_mark_clust_rec(
ibool referenced,
/*!< in: TRUE if index may be referenced in
a foreign key constraint */
+#ifdef WITH_WSREP
+ ibool foreign,/*!< in: TRUE if index is foreign key index */
+#endif /* WITH_WSREP */
mtr_t* mtr) /*!< in: mtr; gets committed here */
{
btr_pcur_t* pcur;
@@ -2502,6 +2545,7 @@ row_upd_del_mark_clust_rec(
dberr_t err;
#ifdef WITH_WSREP
rec_t* rec;
+ que_node_t *parent = que_node_get_parent(node);
#endif /* WITH_WSREP */
ut_ad(node);
@@ -2524,25 +2568,27 @@ row_upd_del_mark_clust_rec(
#endif /* WITH_WSREP */
err = btr_cur_del_mark_set_clust_rec(
- btr_cur_get_block(btr_cur),
#ifdef WITH_WSREP
- rec, index, offsets, thr, mtr);
+ btr_cur_get_block(btr_cur), rec,
#else
- btr_cur_get_rec(btr_cur), index, offsets, thr, mtr);
+ btr_cur_get_block(btr_cur), btr_cur_get_rec(btr_cur),
#endif /* WITH_WSREP */
-
+ index, offsets, thr, mtr);
if (err == DB_SUCCESS && referenced) {
/* NOTE that the following call loses the position of pcur ! */
err = row_upd_check_references_constraints(
node, pcur, index->table, index, offsets, thr, mtr);
}
-
#ifdef WITH_WSREP
- if (err == DB_SUCCESS && !referenced) {
- err = (dberr_t) wsrep_row_upd_check_foreign_constraints(
+ if (err == DB_SUCCESS && !referenced &&
+ !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE &&
+ ((upd_node_t*)parent)->cascade_node == node) &&
+ thr_get_trx(thr) &&
+ foreign
+ ) {
+ err = wsrep_row_upd_check_foreign_constraints(
node, pcur, index->table, index, offsets, thr, mtr);
-
switch (err) {
case DB_SUCCESS:
case DB_NO_REFERENCED_ROW:
@@ -2554,8 +2600,8 @@ row_upd_del_mark_clust_rec(
break;
default:
fprintf (stderr,
- "WSREP: clust rec referenced FK check fail: %u",
- err);
+ "WSREP: clust rec referenced FK check fail: %d",
+ (int)err);
break;
}
}
@@ -2592,6 +2638,10 @@ row_upd_clust_step(
index = dict_table_get_first_index(node->table);
referenced = row_upd_index_is_referenced(index, thr_get_trx(thr));
+#ifdef WITH_WSREP
+ ibool foreign = wsrep_row_upd_index_is_foreign(
+ index, thr_get_trx(thr));
+#endif /* WITH_WSREP */
pcur = node->pcur;
@@ -2688,7 +2738,11 @@ row_upd_clust_step(
if (node->is_delete) {
err = row_upd_del_mark_clust_rec(
+#ifdef WITH_WSREP
+ node, index, offsets, thr, referenced, foreign, &mtr);
+#else
node, index, offsets, thr, referenced, &mtr);
+#endif /* WITH_WSREP */
if (err == DB_SUCCESS) {
node->state = UPD_NODE_UPDATE_ALL_SEC;
@@ -2733,7 +2787,11 @@ row_upd_clust_step(
externally! */
err = row_upd_clust_rec_by_insert(
+#ifdef WITH_WSREP
+ node, index, thr, referenced, foreign, &mtr);
+#else
node, index, thr, referenced, &mtr);
+#endif /* WITH_WSREP */
if (err != DB_SUCCESS) {
diff --git a/storage/xtradb/srv/srv0conc.cc b/storage/xtradb/srv/srv0conc.cc
index a1dd90a024a..59f8fa9a939 100644
--- a/storage/xtradb/srv/srv0conc.cc
+++ b/storage/xtradb/srv/srv0conc.cc
@@ -91,6 +91,9 @@ struct srv_conc_slot_t{
reserved may still be TRUE at that
point */
srv_conc_node_t srv_conc_queue; /*!< queue node */
+#ifdef WITH_WSREP
+ void *thd; /*!< to see priority */
+#endif
};
/** Queue of threads waiting to get in */
@@ -150,6 +153,9 @@ srv_conc_init(void)
conc_slot->event = os_event_create();
ut_a(conc_slot->event);
+#ifdef WITH_WSREP
+ conc_slot->thd = NULL;
+#endif /* WITH_WSREP */
}
#endif /* !HAVE_ATOMIC_BUILTINS */
}
@@ -207,6 +213,16 @@ srv_conc_enter_innodb_with_atomics(
for (;;) {
ulint sleep_in_us;
+#ifdef WITH_WSREP
+ if (wsrep_on(trx->mysql_thd) &&
+ wsrep_trx_is_aborting(trx->mysql_thd)) {
+ if (wsrep_debug)
+ fprintf(stderr,
+ "srv_conc_enter due to MUST_ABORT");
+ srv_conc_force_enter_innodb(trx);
+ return;
+ }
+#endif /* WITH_WSREP */
if (srv_conc.n_active < (lint) srv_thread_concurrency) {
ulint n_active;
@@ -325,6 +341,9 @@ srv_conc_exit_innodb_without_atomics(
slot = NULL;
if (srv_conc.n_active < (lint) srv_thread_concurrency) {
+#ifdef WITH_WSREP
+ srv_conc_slot_t* wsrep_slot;
+#endif
/* Look for a slot where a thread is waiting and no other
thread has yet released the thread */
@@ -335,6 +354,19 @@ srv_conc_exit_innodb_without_atomics(
/* No op */
}
+#ifdef WITH_WSREP
+ /* look for aborting trx, they must be released asap */
+ wsrep_slot= slot;
+ while (wsrep_slot && (wsrep_slot->wait_ended == TRUE ||
+ !wsrep_trx_is_aborting(wsrep_slot->thd))) {
+ wsrep_slot = UT_LIST_GET_NEXT(srv_conc_queue, wsrep_slot);
+ }
+ if (wsrep_slot) {
+ slot = wsrep_slot;
+ if (wsrep_debug)
+ fprintf(stderr, "WSREP: releasing aborting thd\n");
+ }
+#endif
if (slot != NULL) {
slot->wait_ended = TRUE;
@@ -394,6 +426,13 @@ retry:
return;
}
+#ifdef WITH_WSREP
+ if (wsrep_on(trx->mysql_thd) &&
+ wsrep_thd_is_brute_force(trx->mysql_thd)) {
+ srv_conc_force_enter_innodb(trx);
+ return;
+ }
+#endif
/* If the transaction is not holding resources, let it sleep
for srv_thread_sleep_delay microseconds, and try again then */
@@ -461,6 +500,9 @@ retry:
/* Add to the queue */
slot->reserved = TRUE;
slot->wait_ended = FALSE;
+#ifdef WITH_WSREP
+ slot->thd = trx->mysql_thd;
+#endif
UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot);
@@ -468,6 +510,18 @@ retry:
srv_conc.n_waiting++;
+#ifdef WITH_WSREP
+ if (wsrep_on(trx->mysql_thd) &&
+ wsrep_trx_is_aborting(trx->mysql_thd)) {
+ os_fast_mutex_unlock(&srv_conc_mutex);
+ if (wsrep_debug)
+ fprintf(stderr, "srv_conc_enter due to MUST_ABORT");
+ trx->declared_to_be_inside_innodb = TRUE;
+ trx->n_tickets_to_enter_innodb = srv_n_free_tickets_to_enter;
+ return;
+ }
+ trx->wsrep_event = slot->event;
+#endif /* WITH_WSREP */
os_fast_mutex_unlock(&srv_conc_mutex);
/* Go to wait for the event; when a thread leaves InnoDB it will
@@ -491,6 +545,9 @@ retry:
os_event_wait(slot->event);
thd_wait_end(trx->mysql_thd);
+#ifdef WITH_WSREP
+ trx->wsrep_event = NULL;
+#endif /* WITH_WSREP */
trx->op_info = "";
@@ -508,6 +565,9 @@ retry:
incremented the thread counter on behalf of this thread */
slot->reserved = FALSE;
+#ifdef WITH_WSREP
+ slot->thd = NULL;
+#endif
UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot);
@@ -629,7 +689,7 @@ wsrep_srv_conc_cancel_wait(
thread */
{
#ifdef HAVE_ATOMIC_BUILTINS
- /* aborting transactions will enter innodb by force in
+ /* aborting transactions will enter innodb by force in
srv_conc_enter_innodb_with_atomics(). No need to cancel here,
thr will wake up after os_sleep and let to enter innodb
*/
diff --git a/storage/xtradb/trx/trx0sys.cc b/storage/xtradb/trx/trx0sys.cc
index bc61691a684..ed3d177820f 100644
--- a/storage/xtradb/trx/trx0sys.cc
+++ b/storage/xtradb/trx/trx0sys.cc
@@ -213,7 +213,8 @@ trx_sys_update_mysql_binlog_offset(
{
#ifndef WITH_WSREP
trx_sysf_t* sys_header;
-#endif
+#endif /* !WITH_WSREP */
+
if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
/* We cannot fit the name to the 512 bytes we have reserved */
@@ -223,7 +224,7 @@ trx_sys_update_mysql_binlog_offset(
#ifndef WITH_WSREP
sys_header = trx_sysf_get(mtr);
-#endif
+#endif /* !WITH_WSREP */
if (mach_read_from_4(sys_header + field
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
@@ -312,12 +313,49 @@ trx_sys_print_mysql_binlog_offset(void)
#ifdef WITH_WSREP
+#ifdef UNIV_DEBUG
+static long long trx_sys_cur_xid_seqno = -1;
+static unsigned char trx_sys_cur_xid_uuid[16];
+
+long long read_wsrep_xid_seqno(const XID* xid)
+{
+ long long seqno;
+ memcpy(&seqno, xid->data + 24, sizeof(long long));
+ return seqno;
+}
+
+void read_wsrep_xid_uuid(const XID* xid, unsigned char* buf)
+{
+ memcpy(buf, xid->data + 8, 16);
+}
+
+#endif /* UNIV_DEBUG */
+
void
trx_sys_update_wsrep_checkpoint(
- const XID* xid, /*!< in: transaction XID */
+ const XID* xid, /*!< in: transaction XID */
trx_sysf_t* sys_header, /*!< in: sys_header */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr) /*!< in: mtr */
{
+#ifdef UNIV_DEBUG
+ {
+ /* Check that seqno is monotonically increasing */
+ unsigned char xid_uuid[16];
+ long long xid_seqno = read_wsrep_xid_seqno(xid);
+ read_wsrep_xid_uuid(xid, xid_uuid);
+ if (!memcmp(xid_uuid, trx_sys_cur_xid_uuid, 8))
+ {
+ ut_ad(xid_seqno > trx_sys_cur_xid_seqno);
+ trx_sys_cur_xid_seqno = xid_seqno;
+ }
+ else
+ {
+ memcpy(trx_sys_cur_xid_uuid, xid_uuid, 16);
+ }
+ trx_sys_cur_xid_seqno = xid_seqno;
+ }
+#endif /* UNIV_DEBUG */
+
ut_ad(xid && mtr);
ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid((const void *)xid));
diff --git a/storage/xtradb/trx/trx0trx.cc b/storage/xtradb/trx/trx0trx.cc
index 0279b38446a..04423ea3662 100644
--- a/storage/xtradb/trx/trx0trx.cc
+++ b/storage/xtradb/trx/trx0trx.cc
@@ -1228,7 +1228,7 @@ trx_write_serialisation_history(
trx_sys_update_mysql_binlog_offset(
trx->mysql_log_file_name,
trx->mysql_log_offset,
- TRX_SYS_MYSQL_LOG_INFO,
+ TRX_SYS_MYSQL_LOG_INFO,
#ifdef WITH_WSREP
sys_header,
#endif /* WITH_WSREP */