summaryrefslogtreecommitdiff
path: root/storage/xtradb
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb')
-rw-r--r--storage/xtradb/handler/ha_innodb.cc129
-rw-r--r--storage/xtradb/handler/ha_innodb.h5
-rw-r--r--storage/xtradb/include/ha_prototypes.h2
-rw-r--r--storage/xtradb/lock/lock0lock.c90
4 files changed, 132 insertions, 94 deletions
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 9a40b9eef84..9737843a00b 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -137,9 +137,9 @@ extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_wsrep_rollback;
extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_wsrep_rollback;
extern MYSQL_PLUGIN_IMPORT wsrep_aborting_thd_t wsrep_aborting_thd;
-static inline wsrep_trx_handle_t*
-wsrep_trx_handle(THD* thd, const trx_t* trx) {
- return wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd),
+static inline wsrep_ws_handle_t*
+wsrep_ws_handle(THD* thd, const trx_t* trx) {
+ return wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd),
(wsrep_trx_id_t)trx->id);
}
@@ -147,7 +147,7 @@ extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key,
size_t cache_key_len,
const uchar* row_id,
size_t row_id_len,
- wsrep_key_part_t* key,
+ wsrep_buf_t* key,
size_t* key_len);
extern handlerton * wsrep_hton;
@@ -1187,6 +1187,8 @@ innobase_release_temporary_latches(
static int
wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
my_bool signal);
+static void
+wsrep_fake_trx_id(handlerton* hton, THD *thd);
static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid);
static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid);
#endif
@@ -2729,6 +2731,7 @@ innobase_init(
innobase_hton->wsrep_abort_transaction=wsrep_abort_transaction;
innobase_hton->wsrep_set_checkpoint=innobase_wsrep_set_checkpoint;
innobase_hton->wsrep_get_checkpoint=innobase_wsrep_get_checkpoint;
+ innobase_hton->wsrep_fake_trx_id=wsrep_fake_trx_id;
#endif /* WITH_WSREP */
innobase_hton->kill_query = innobase_kill_query;
@@ -8222,6 +8225,7 @@ wsrep_append_foreign_key(
ulint rcode = DB_SUCCESS;
char cache_key[513] = {'\0'};
int cache_key_len;
+ bool const copy = true;
if (!wsrep_on(trx->mysql_thd) ||
wsrep_thd_exec_mode(thd) != LOCAL_STATE)
@@ -8348,30 +8352,31 @@ wsrep_append_foreign_key(
foreign->foreign_table->name);
}
- wsrep_key_part_t wkey_part[3];
+ wsrep_buf_t wkey_part[3];
wsrep_key_t wkey = {wkey_part, 3};
if (!wsrep_prepare_key_for_innodb(
(const uchar*)cache_key,
cache_key_len + 1,
(const uchar*)key, len+1,
wkey_part,
- &wkey.key_parts_len)) {
- WSREP_WARN("key prepare failed for cascaded FK: %s",
- (wsrep_thd_query(thd)) ?
- wsrep_thd_query(thd) : "void");
+ &wkey.key_parts_num)) {
+ WSREP_WARN("key prepare failed for cascaded FK: %s",
+ (wsrep_thd_query(thd)) ?
+ wsrep_thd_query(thd) : "void");
return DB_ERROR;
}
rcode = (int)wsrep->append_key(
wsrep,
- wsrep_trx_handle(thd, trx),
+ wsrep_ws_handle(thd, trx),
&wkey,
- 1,
- shared);
+ 1,
+ shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE,
+ copy);
if (rcode) {
DBUG_PRINT("wsrep", ("row key failed: %lu", rcode));
- WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu",
- (wsrep_thd_query(thd)) ?
- wsrep_thd_query(thd) : "void", rcode);
+ WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu",
+ (wsrep_thd_query(thd)) ?
+ wsrep_thd_query(thd) : "void", rcode);
return DB_ERROR;
}
@@ -8392,6 +8397,7 @@ wsrep_append_key(
)
{
DBUG_ENTER("wsrep_append_key");
+ bool const copy = true;
#ifdef WSREP_DEBUG_PRINT
fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ",
(shared) ? "Shared" : "Exclusive",
@@ -8402,52 +8408,37 @@ wsrep_append_key(
}
fprintf(stderr, "\n");
#endif
- wsrep_key_part_t wkey_part[3];
+ wsrep_buf_t wkey_part[3];
wsrep_key_t wkey = {wkey_part, 3};
if (!wsrep_prepare_key_for_innodb(
(const uchar*)table_share->table_cache_key.str,
table_share->table_cache_key.length,
(const uchar*)key, key_len,
wkey_part,
- &wkey.key_parts_len)) {
- WSREP_WARN("key prepare failed for: %s",
- (wsrep_thd_query(thd)) ?
- wsrep_thd_query(thd) : "void");
+ &wkey.key_parts_num)) {
+ WSREP_WARN("key prepare failed for: %s",
+ (wsrep_thd_query(thd)) ?
+ wsrep_thd_query(thd) : "void");
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
}
int rcode = (int)wsrep->append_key(
wsrep,
- wsrep_trx_handle(thd, trx),
+ wsrep_ws_handle(thd, trx),
&wkey,
1,
- shared);
+ shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE,
+ copy);
if (rcode) {
DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
- WSREP_WARN("Appending row key failed: %s, %d",
- (wsrep_thd_query(thd)) ?
- wsrep_thd_query(thd) : "void", rcode);
+ WSREP_WARN("Appending row key failed: %s, %d",
+ (wsrep_thd_query(thd)) ?
+ wsrep_thd_query(thd) : "void", rcode);
DBUG_RETURN(rcode);
}
DBUG_RETURN(0);
}
-ibool
-wsrep_is_cascding_foreign_key_parent(
- dict_table_t* table, /*!< in: InnoDB table */
- dict_index_t* index /*!< in: InnoDB index */
-) {
- // return referenced_by_foreign_key();
- dict_foreign_t* fk = dict_table_get_referenced_constraint(table, index);
- if (fk &&
- (fk->type & DICT_FOREIGN_ON_UPDATE_CASCADE ||
- fk->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
- ) {
- return TRUE;
- }
- return FALSE;
-}
-
int
ha_innobase::wsrep_append_keys(
/*==================*/
@@ -8495,19 +8486,30 @@ ha_innobase::wsrep_append_keys(
ut_a(table->s->keys <= 256);
uint i;
for (i=0; i<table->s->keys; ++i) {
- uint len;
- char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
- char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
- char *key0 = &keyval0[1];
- char *key1 = &keyval1[1];
- KEY *key_info = table->key_info + i;
- ibool is_null;
+ uint len;
+ char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
+ char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
+ char* key0 = &keyval0[1];
+ char* key1 = &keyval1[1];
+ KEY* key_info = table->key_info + i;
+ ibool is_null;
+
+ dict_index_t* idx = innobase_get_index(i);
+ dict_table_t* tab = (idx) ? idx->table : NULL;
keyval0[0] = (char)i;
keyval1[0] = (char)i;
+ if (!tab) {
+ WSREP_WARN("MySQL-InnoDB key mismatch %s %s",
+ table->s->table_name.str,
+ key_info->name);
+ }
if (key_info->flags & HA_NOSAME ||
- referenced_by_foreign_key()) {
+ ((tab &&
+ dict_table_get_referenced_constraint(tab, idx)) ||
+ (!tab && referenced_by_foreign_key()))) {
+
if (key_info->flags & HA_NOSAME || shared)
key_appended = true;
@@ -13877,25 +13879,35 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno)
This function is used to kill one transaction in BF. */
int
wsrep_innobase_kill_one_trx(
+ void *bf_thd_ptr, /*!< in: BF thd */
trx_t *bf_trx, /*!< in: BF trx */
trx_t *victim_trx, /*!< in: victim trx */
ibool signal, /*!< in: signal to be used */
ibool have_kernel_mutex) /*!<in: do we own kernel mutex */
{
DBUG_ENTER("wsrep_innobase_kill_one_trx");
+ THD *bf_thd = (THD *)bf_thd_ptr;
THD *thd = (THD *) victim_trx->mysql_thd;
- THD *bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL;
int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0;
if (have_kernel_mutex) {
ut_ad(mutex_own(&kernel_mutex));
}
+ if (!bf_thd) bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL;
+
if (!thd) {
DBUG_PRINT("wsrep", ("no thd for conflicting lock"));
WSREP_WARN("no THD for trx: %llu", victim_trx->id);
DBUG_RETURN(1);
}
+ if (!bf_thd) {
+ DBUG_PRINT("wsrep", ("no BF thd for conflicting lock"));
+ WSREP_WARN("no BF THD for trx: %llu", (bf_trx) ? bf_trx->id : 0);
+ DBUG_RETURN(1);
+ }
+
+ WSREP_LOG_CONFLICT(bf_thd, thd, TRUE);
WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu",
signal, (long long)bf_seqno,
@@ -14098,8 +14110,8 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
if (victim_trx)
{
- int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx,
- signal, FALSE);
+ int rcode = wsrep_innobase_kill_one_trx(
+ bf_thd, bf_trx, victim_trx, signal, FALSE);
wsrep_srv_conc_cancel_wait(victim_trx);
DBUG_RETURN(rcode);
} else {
@@ -14134,6 +14146,19 @@ static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid)
return 0;
}
+static void
+wsrep_fake_trx_id(
+/*==================*/
+ handlerton *hton,
+ THD *thd) /*!< in: user thread handle */
+{
+ mutex_enter(&kernel_mutex);
+ trx_id_t trx_id = trx_sys_get_new_trx_id();
+ mutex_exit(&kernel_mutex);
+
+ (void *)wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id);
+}
+
#endif /* WITH_WSREP */
/* plugin options */
static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums,
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index b72bc13f945..798be6fb292 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -385,7 +385,10 @@ 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" wsrep_trx_handle_t* wsrep_thd_trx_handle(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(
diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index 373c4956ca5..7d98401a093 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -301,7 +301,7 @@ thd_flush_log_at_trx_commit(
void* thd);
#ifdef WITH_WSREP
-UNIV_INTERN int wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx,
+UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd, trx_t *bf_trx, trx_t *victim_trx,
ibool signal, ibool have_kernel_mutex);
int wsrep_thd_is_brute_force(void *thd_ptr);
int wsrep_trx_order_before(void *thd1, void *thd2);
diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c
index 36188b03cec..12694687180 100644
--- a/storage/xtradb/lock/lock0lock.c
+++ b/storage/xtradb/lock/lock0lock.c
@@ -42,6 +42,7 @@ Created 5/7/1996 Heikki Tuuri
#ifdef WITH_WSREP
extern my_bool wsrep_debug;
+extern my_bool wsrep_log_conflicts;
#endif
/* Restricts the length of search we will do in the waits-for
graph of transactions */
@@ -1533,7 +1534,34 @@ wsrep_kill_victim(trx_t *trx, lock_t *lock) {
/* cannot release lock, until our lock
is in the queue*/
} else if (lock->trx != trx) {
- wsrep_innobase_kill_one_trx(trx, lock->trx, TRUE, TRUE);
+ if (wsrep_log_conflicts) {
+ if (bf_this)
+ fputs("\n*** Priority TRANSACTION:\n",
+ stderr);
+ else
+ fputs("\n*** Victim TRANSACTION:\n",
+ stderr);
+ trx_print(stderr, trx, 3000);
+
+ if (bf_other)
+ fputs("\n*** Priority TRANSACTION:\n",
+ stderr);
+ else
+ fputs("\n*** Victim TRANSACTION:\n",
+ stderr);
+ trx_print(stderr, lock->trx, 3000);
+
+ fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
+ stderr);
+
+ if (lock_get_type(lock) == LOCK_REC) {
+ lock_rec_print(stderr, lock);
+ } else {
+ lock_table_print(stderr, lock);
+ }
+ }
+ wsrep_innobase_kill_one_trx(
+ trx->mysql_thd, trx, lock->trx, TRUE, TRUE);
}
}
}
@@ -1715,7 +1743,7 @@ lock_t*
lock_rec_create(
/*============*/
#ifdef WITH_WSREP
- lock_t* c_lock, /* conflicting lock */
+ lock_t* c_lock, /* conflicting lock */
#endif
ulint type_mode,/*!< in: lock mode and wait
flag, type is ignored and
@@ -1783,7 +1811,7 @@ lock_rec_create(
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
- lock_t *hash = c_lock->hash;
+ lock_t *hash = c_lock->hash;
lock_t *prev = NULL;
while (hash &&
@@ -1802,7 +1830,7 @@ lock_rec_create(
* delayed conflict resolution '...kill_one_trx' was not called,
* if victim was waiting for some other lock
*/
- if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) {
+ if (c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) {
c_lock->trx->was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug && c_lock->trx->wait_lock != c_lock) {
@@ -1824,8 +1852,8 @@ lock_rec_create(
}
if (wsrep_debug) fprintf(
- stderr,
- "WSREP: c_lock canceled %llu\n",
+ stderr,
+ "WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id);
/* have to bail out here to avoid lock_set_lock... */
@@ -1838,8 +1866,7 @@ lock_rec_create(
#else
HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
lock_rec_fold(space, page_no), lock);
-#endif
-
+#endif /* WITH_WSREP */
lock_sys->rec_num++;
if (lock_is_wait_not_by_other(type_mode)) {
lock_set_lock_and_trx_wait(lock, trx);
@@ -1860,7 +1887,7 @@ enum db_err
lock_rec_enqueue_waiting(
/*=====================*/
#ifdef WITH_WSREP
- lock_t* c_lock, /* conflicting lock */
+ lock_t* c_lock, /* conflicting lock */
#endif
ulint type_mode,/*!< in: lock mode this
transaction is requesting:
@@ -2211,7 +2238,7 @@ lock_rec_lock_slow(
{
trx_t* trx;
#ifdef WITH_WSREP
- lock_t *c_lock= 0;
+ lock_t* c_lock = NULL;
#endif
lock_t* lock;
@@ -2261,10 +2288,10 @@ lock_rec_lock_slow(
#ifdef WITH_WSREP
} else if ((c_lock = lock_rec_other_has_conflicting(
- mode, block, heap_no, trx))) {
+ mode, block, heap_no, trx))) {
#else
} else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) {
-#endif
+#endif /* WITH_WSREP */
/* If another transaction has a non-gap conflicting request in
the queue, as this transaction does not have a lock strong
@@ -2273,12 +2300,15 @@ lock_rec_lock_slow(
ut_ad(lock == NULL);
enqueue_waiting:
#ifdef WITH_WSREP
- return(lock_rec_enqueue_waiting(c_lock,mode, block, heap_no,
+ /* c_lock is NULL here if jump to enqueue_waiting happened
+ but it's ok because lock is not NULL in that case and c_lock
+ is not used. */
+ return(lock_rec_enqueue_waiting(c_lock, mode, block, heap_no,
lock, index, thr));
#else
return(lock_rec_enqueue_waiting(mode, block, heap_no,
lock, index, thr));
-#endif
+#endif /* WITH_WSREP */
} else if (!impl) {
/* Set the requested lock on the record */
@@ -3944,7 +3974,8 @@ lock_table_create(
if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug) {
- fprintf(stderr, "WSREP: table c_lock in wait: %llu new loc: %llu\n",
+ fprintf(stderr,
+ "WSREP: table c_lock in wait: %llu new loc: %llu\n",
(ulonglong) c_lock->trx->id, lock->trx->id);
}
@@ -4227,33 +4258,12 @@ lock_table_other_has_incompatible(
if ((lock->trx != trx)
&& (!lock_mode_compatible(lock_get_mode(lock), mode))
&& (wait || !(lock_get_wait(lock)))) {
-
#ifdef WITH_WSREP
- int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd);
- int 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)
- )
- ) {
- if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) {
- if (wsrep_debug) fprintf(stderr,
- "WSREP: BF victim waiting");
- return(lock);
- } else {
- if (bf_this && bf_other)
- wsrep_innobase_kill_one_trx(
- (trx_t *)trx, lock->trx, TRUE, TRUE);
- return(lock);
- }
- } else {
- return(lock);
- }
-#else
- return(lock);
+ if (wsrep_debug)
+ fprintf(stderr, "WSREP: table lock abort");
+ wsrep_kill_victim((trx_t *)trx, (lock_t *)lock);
#endif
+ return(lock);
}
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);