Commit 1ec32057 authored by Vlad Lesin's avatar Vlad Lesin

Merge 10.3 into 10.4

parents 7b97020d 86c1bf11
...@@ -14,7 +14,6 @@ GCF-1081 : MDEV-18283 Galera test failure on galera.GCF-1081 ...@@ -14,7 +14,6 @@ GCF-1081 : MDEV-18283 Galera test failure on galera.GCF-1081
GCF-939 : MDEV-21520 galera.GCF-939 GCF-939 : MDEV-21520 galera.GCF-939
MW-328A : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 MW-328A : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002
MW-328B : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 MW-328B : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002
MW-328D : MDEV-27550 ER_LOCK_DEADLOCK is gone after MDEV-27025
MW-329 : MDEV-19962 Galera test failure on MW-329 MW-329 : MDEV-19962 Galera test failure on MW-329
galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event() galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event()
galera_bf_abort_group_commit : MDEV-18282 Galera test failure on galera.galera_bf_abort_group_commit galera_bf_abort_group_commit : MDEV-18282 Galera test failure on galera.galera_bf_abort_group_commit
......
CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t VALUES (3);
BEGIN;
connection default;
UPDATE t SET a = 2;
connect con1,localhost,root;
DELETE FROM t;
connection default;
UPDATE t SET a = 1;
COMMIT;
connection con1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
disconnect con1;
connection default;
# The above DELETE must delete all the rows in the table, so the
# following SELECT must show 0 rows.
SELECT count(*) FROM t;
count(*)
1
DROP TABLE t;
#
# MDEV-27025 insert-intention lock conflicts with waiting ORDINARY lock
#
CREATE TABLE t (a INT PRIMARY KEY, b INT NOT NULL UNIQUE) ENGINE=InnoDB;
connect prevent_purge,localhost,root,,;
start transaction with consistent snapshot;
connection default;
INSERT INTO t VALUES (20,20);
DELETE FROM t WHERE b = 20;
connect con_ins,localhost,root,,;
SET DEBUG_SYNC = 'row_ins_sec_index_entry_dup_locks_created SIGNAL ins_set_locks WAIT_FOR ins_cont';
INSERT INTO t VALUES(10, 20);
connect con_del,localhost,root,,;
SET DEBUG_SYNC = 'now WAIT_FOR ins_set_locks';
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL del_locked';
DELETE FROM t WHERE b = 20;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR del_locked';
SET DEBUG_SYNC = 'now SIGNAL ins_cont';
connection con_ins;
disconnect con_ins;
connection con_del;
disconnect con_del;
disconnect prevent_purge;
connection default;
SET DEBUG_SYNC = 'RESET';
DROP TABLE t;
--source include/have_innodb.inc
--source include/count_sessions.inc
CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t VALUES (3);
BEGIN;
connection default;
UPDATE t SET a = 2;
connect con1,localhost,root;
send DELETE FROM t;
connection default;
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Updating" and info = "DELETE FROM t";
--source include/wait_condition.inc
UPDATE t SET a = 1;
COMMIT;
connection con1;
error ER_LOCK_DEADLOCK;
reap;
disconnect con1;
connection default;
--echo # The above DELETE must delete all the rows in the table, so the
--echo # following SELECT must show 0 rows.
SELECT count(*) FROM t;
DROP TABLE t;
--source include/wait_until_count_sessions.inc
--source include/have_innodb.inc
--source include/count_sessions.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
--echo #
--echo # MDEV-27025 insert-intention lock conflicts with waiting ORDINARY lock
--echo #
# The test checks the ability to acquire exclusive record lock if the acquiring
# transaction already holds a shared lock on the record and another transaction
# is waiting for a lock.
CREATE TABLE t (a INT PRIMARY KEY, b INT NOT NULL UNIQUE) ENGINE=InnoDB;
--connect(prevent_purge,localhost,root,,)
start transaction with consistent snapshot;
--connection default
INSERT INTO t VALUES (20,20);
DELETE FROM t WHERE b = 20;
--connect(con_ins,localhost,root,,)
SET DEBUG_SYNC = 'row_ins_sec_index_entry_dup_locks_created SIGNAL ins_set_locks WAIT_FOR ins_cont';
send
INSERT INTO t VALUES(10, 20);
--connect(con_del,localhost,root,,)
SET DEBUG_SYNC = 'now WAIT_FOR ins_set_locks';
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL del_locked';
###############################################################################
# This DELETE creates waiting ORDINARY X-lock for heap_no 2 as the record is
# delete-marked, this lock conflicts with ORDINARY S-lock set by the the last
# INSERT. After the last INSERT creates insert-intention lock on
# heap_no 2, this lock will conflict with waiting ORDINARY X-lock of this
# DELETE, what causes DEADLOCK error for this DELETE.
###############################################################################
send
DELETE FROM t WHERE b = 20;
--connection default
SET DEBUG_SYNC = 'now WAIT_FOR del_locked';
SET DEBUG_SYNC = 'now SIGNAL ins_cont';
--connection con_ins
--reap
--disconnect con_ins
--connection con_del
# Without the fix, ER_LOCK_DEADLOCK would be reported here.
--reap
--disconnect con_del
--disconnect prevent_purge
--connection default
SET DEBUG_SYNC = 'RESET';
DROP TABLE t;
--source include/wait_until_count_sessions.inc
...@@ -283,6 +283,7 @@ connection default; ...@@ -283,6 +283,7 @@ connection default;
update t1 set b = 'foo'; update t1 set b = 'foo';
connection con1; connection con1;
update t1 set a = 'bar'; update t1 set a = 'bar';
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
disconnect con1; disconnect con1;
connection default; connection default;
drop table t1; drop table t1;
......
...@@ -186,9 +186,7 @@ send update t1 set b = 'foo'; ...@@ -186,9 +186,7 @@ send update t1 set b = 'foo';
connection con1; connection con1;
let $wait_condition= select count(*) from information_schema.innodb_lock_waits; let $wait_condition= select count(*) from information_schema.innodb_lock_waits;
source include/wait_condition.inc; source include/wait_condition.inc;
# There must no be DEADLOCK here as con1 transaction already holds locks, and error ER_LOCK_DEADLOCK;
# default's transaction lock is waiting, so the locks of the following "UPDATE"
# must not conflict with waiting lock.
update t1 set a = 'bar'; update t1 set a = 'bar';
disconnect con1; disconnect con1;
connection default; connection default;
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 2022, MariaDB Corporation. Copyright (c) 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -31,31 +31,7 @@ Created 5/20/1997 Heikki Tuuri ...@@ -31,31 +31,7 @@ Created 5/20/1997 Heikki Tuuri
#include "sync0rw.h" #include "sync0rw.h"
struct hash_table_t; struct hash_table_t;
struct hash_cell_t;
struct hash_cell_t
{
/** singly-linked, nullptr terminated list of hash buckets */
void *node;
/** Insert an element after another.
@tparam T type of the element
@param after the element after which to insert
@param insert the being-inserted element
@param next the next-element pointer in T */
template<typename T>
void insert_after(T &after, T &insert, T *T::*next)
{
#ifdef UNIV_DEBUG
for (const T *c= static_cast<const T*>(node); c; c= c->*next)
if (c == &after)
goto found;
ut_error;
found:
#endif
insert.*next= after.*next;
after.*next= &insert;
}
};
typedef void* hash_node_t; typedef void* hash_node_t;
...@@ -501,6 +477,10 @@ hash_unlock_x_all_but( ...@@ -501,6 +477,10 @@ hash_unlock_x_all_but(
hash_table_t* table, /*!< in: hash table */ hash_table_t* table, /*!< in: hash table */
rw_lock_t* keep_lock); /*!< in: lock to keep */ rw_lock_t* keep_lock); /*!< in: lock to keep */
struct hash_cell_t{
void* node; /*!< hash chain node, NULL if none */
};
/* The hash table structure */ /* The hash table structure */
struct hash_table_t { struct hash_table_t {
enum hash_table_sync_t type; /*<! type of hash_table. */ enum hash_table_sync_t type; /*<! type of hash_table. */
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, 2022, MariaDB Corporation. Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -888,29 +888,26 @@ class lock_sys_t ...@@ -888,29 +888,26 @@ class lock_sys_t
/*********************************************************************//** /*********************************************************************//**
Creates a new record lock and inserts it to the lock queue. Does NOT check Creates a new record lock and inserts it to the lock queue. Does NOT check
for deadlocks or lock compatibility! for deadlocks or lock compatibility!
@param[in] c_lock conflicting lock
@param[in] thr thread owning trx
@param[in] type_mode lock mode and wait flag, type is ignored and replaced by
LOCK_REC
@param[in] block buffer block containing the record
@param[in] heap_no heap number of the record
@param[in] index index of record
@param[in,out] trx transaction
@param[in] caller_owns_trx_mutex TRUE if caller owns trx mutex
@param[in] insert_before_waiting if true, inserts new B-tree record lock
just after the last non-waiting lock of the current transaction which is
located before the first waiting for the current transaction lock, otherwise
the lock is inserted at the end of the queue
@return created lock */ @return created lock */
UNIV_INLINE UNIV_INLINE
lock_t *lock_rec_create(lock_t *c_lock, lock_t*
lock_rec_create(
/*============*/
#ifdef WITH_WSREP #ifdef WITH_WSREP
que_thr_t *thr, lock_t* c_lock, /*!< conflicting lock */
que_thr_t* thr, /*!< thread owning trx */
#endif #endif
ulint type_mode, const buf_block_t *block, ulint type_mode,/*!< in: lock mode and wait
ulint heap_no, dict_index_t *index, trx_t *trx, flag, type is ignored and
bool caller_owns_trx_mutex, replaced by LOCK_REC */
bool insert_before_waiting= false); const buf_block_t* block, /*!< in: buffer block containing
the record */
ulint heap_no,/*!< in: heap number of the record */
dict_index_t* index, /*!< in: index of record */
trx_t* trx, /*!< in,out: transaction */
bool caller_owns_trx_mutex);
/*!< in: true if caller owns
trx mutex */
/*************************************************************//** /*************************************************************//**
Removes a record lock request, waiting or granted, from the queue. */ Removes a record lock request, waiting or granted, from the queue. */
...@@ -923,7 +920,6 @@ lock_rec_discard( ...@@ -923,7 +920,6 @@ lock_rec_discard(
/** Create a new record lock and inserts it to the lock queue, /** Create a new record lock and inserts it to the lock queue,
without checking for deadlocks or conflicts. without checking for deadlocks or conflicts.
@param[in] c_lock conflicting lock
@param[in] type_mode lock mode and wait flag; type will be replaced @param[in] type_mode lock mode and wait flag; type will be replaced
with LOCK_REC with LOCK_REC
@param[in] space tablespace id @param[in] space tablespace id
...@@ -933,15 +929,11 @@ without checking for deadlocks or conflicts. ...@@ -933,15 +929,11 @@ without checking for deadlocks or conflicts.
@param[in] index the index tree @param[in] index the index tree
@param[in,out] trx transaction @param[in,out] trx transaction
@param[in] holds_trx_mutex whether the caller holds trx->mutex @param[in] holds_trx_mutex whether the caller holds trx->mutex
@param[in] insert_before_waiting if true, inserts new B-tree record lock
just after the last non-waiting lock of the current transaction which is
located before the first waiting for the current transaction lock, otherwise
the lock is inserted at the end of the queue
@return created lock */ @return created lock */
lock_t* lock_t*
lock_rec_create_low( lock_rec_create_low(
lock_t* c_lock,
#ifdef WITH_WSREP #ifdef WITH_WSREP
lock_t* c_lock, /*!< conflicting lock */
que_thr_t* thr, /*!< thread owning trx */ que_thr_t* thr, /*!< thread owning trx */
#endif #endif
ulint type_mode, ulint type_mode,
...@@ -951,12 +943,9 @@ lock_rec_create_low( ...@@ -951,12 +943,9 @@ lock_rec_create_low(
ulint heap_no, ulint heap_no,
dict_index_t* index, dict_index_t* index,
trx_t* trx, trx_t* trx,
bool holds_trx_mutex, bool holds_trx_mutex);
bool insert_before_waiting = false);
/** Enqueue a waiting request for a lock which cannot be granted immediately. /** Enqueue a waiting request for a lock which cannot be granted immediately.
Check for deadlocks. Check for deadlocks.
@param[in] c_lock conflicting lock
@param[in] type_mode the requested lock mode (LOCK_S or LOCK_X) @param[in] type_mode the requested lock mode (LOCK_S or LOCK_X)
possibly ORed with LOCK_GAP or possibly ORed with LOCK_GAP or
LOCK_REC_NOT_GAP, ORed with LOCK_REC_NOT_GAP, ORed with
...@@ -975,7 +964,9 @@ Check for deadlocks. ...@@ -975,7 +964,9 @@ Check for deadlocks.
(or it happened to commit) */ (or it happened to commit) */
dberr_t dberr_t
lock_rec_enqueue_waiting( lock_rec_enqueue_waiting(
lock_t* c_lock, #ifdef WITH_WSREP
lock_t* c_lock, /*!< conflicting lock */
#endif
ulint type_mode, ulint type_mode,
const buf_block_t* block, const buf_block_t* block,
ulint heap_no, ulint heap_no,
......
...@@ -101,37 +101,34 @@ lock_hash_get( ...@@ -101,37 +101,34 @@ lock_hash_get(
/*********************************************************************//** /*********************************************************************//**
Creates a new record lock and inserts it to the lock queue. Does NOT check Creates a new record lock and inserts it to the lock queue. Does NOT check
for deadlocks or lock compatibility! for deadlocks or lock compatibility!
@param[in] c_lock conflicting lock
@param[in] thr thread owning trx
@param[in] type_mode lock mode and wait flag, type is ignored and replaced by
LOCK_REC
@param[in] block buffer block containing the record
@param[in] heap_no heap number of the record
@param[in] index index of record
@param[in,out] trx transaction
@param[in] caller_owns_trx_mutex TRUE if caller owns trx mutex
@param[in] insert_before_waiting if true, inserts new B-tree record lock
just after the last non-waiting lock of the current transaction which is
located before the first waiting for the current transaction lock, otherwise
the lock is inserted at the end of the queue
@return created lock */ @return created lock */
UNIV_INLINE UNIV_INLINE
lock_t *lock_rec_create(lock_t *c_lock, lock_t*
lock_rec_create(
/*============*/
#ifdef WITH_WSREP #ifdef WITH_WSREP
que_thr_t *thr, lock_t* c_lock, /*!< conflicting lock */
que_thr_t* thr, /*!< thread owning trx */
#endif #endif
ulint type_mode, const buf_block_t *block, ulint type_mode,/*!< in: lock mode and wait
ulint heap_no, dict_index_t *index, trx_t *trx, flag, type is ignored and
bool caller_owns_trx_mutex, replaced by LOCK_REC */
bool insert_before_waiting) const buf_block_t* block, /*!< in: buffer block containing
the record */
ulint heap_no,/*!< in: heap number of the record */
dict_index_t* index, /*!< in: index of record */
trx_t* trx, /*!< in,out: transaction */
bool caller_owns_trx_mutex)
/*!< in: TRUE if caller owns
trx mutex */
{ {
btr_assert_not_corrupted(block, index); btr_assert_not_corrupted(block, index);
return lock_rec_create_low(c_lock, return lock_rec_create_low(
#ifdef WITH_WSREP #ifdef WITH_WSREP
thr, c_lock, thr,
#endif #endif
type_mode, type_mode,
block->page.id.space(), block->page.id.page_no(), block->page.id.space(), block->page.id.page_no(),
block->frame, heap_no, index, trx, block->frame, heap_no,
caller_owns_trx_mutex, insert_before_waiting); index, trx, caller_owns_trx_mutex);
} }
/***************************************************************************** /*****************************************************************************
Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2018, 2022 MariaDB Corporation. Copyright (c) 2015, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -585,9 +585,6 @@ lock_rec_get_next_const( ...@@ -585,9 +585,6 @@ lock_rec_get_next_const(
/*********************************************************************//** /*********************************************************************//**
Gets the first explicit lock request on a record. Gets the first explicit lock request on a record.
@param[in] hash hash chain the lock on
@param[in] page_id page id
@param[in] heap_no heap number of the record
@return first lock, NULL if none exists */ @return first lock, NULL if none exists */
UNIV_INLINE UNIV_INLINE
lock_t* lock_t*
...@@ -663,26 +660,15 @@ lock_table_has( ...@@ -663,26 +660,15 @@ lock_table_has(
/** Set the wait status of a lock. /** Set the wait status of a lock.
@param[in,out] lock lock that will be waited for @param[in,out] lock lock that will be waited for
@param[in,out] trx transaction that will wait for the lock @param[in,out] trx transaction that will wait for the lock */
@param[in] c_lock conflicting lock */ inline void lock_set_lock_and_trx_wait(lock_t* lock, trx_t* trx)
inline void lock_set_lock_and_trx_wait(lock_t* lock, trx_t* trx,
const lock_t *c_lock)
{ {
ut_ad(lock); ut_ad(lock);
ut_ad(lock->trx == trx); ut_ad(lock->trx == trx);
ut_ad(trx->lock.wait_lock == NULL);
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(trx)); ut_ad(trx_mutex_own(trx));
if (trx->lock.wait_trx) {
ut_ad(!c_lock || trx->lock.wait_trx == c_lock->trx);
ut_ad(trx->lock.wait_lock);
ut_ad((*trx->lock.wait_lock).trx == trx);
} else {
ut_ad(c_lock);
trx->lock.wait_trx = c_lock->trx;
ut_ad(!trx->lock.wait_lock);
}
trx->lock.wait_lock = lock; trx->lock.wait_lock = lock;
lock->type_mode |= LOCK_WAIT; lock->type_mode |= LOCK_WAIT;
} }
...@@ -695,7 +681,6 @@ inline void lock_reset_lock_and_trx_wait(lock_t* lock) ...@@ -695,7 +681,6 @@ inline void lock_reset_lock_and_trx_wait(lock_t* lock)
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
ut_ad(lock->trx->lock.wait_lock == NULL ut_ad(lock->trx->lock.wait_lock == NULL
|| lock->trx->lock.wait_lock == lock); || lock->trx->lock.wait_lock == lock);
lock->trx->lock.wait_trx= NULL;
lock->trx->lock.wait_lock = NULL; lock->trx->lock.wait_lock = NULL;
lock->type_mode &= ~LOCK_WAIT; lock->type_mode &= ~LOCK_WAIT;
} }
......
...@@ -145,19 +145,22 @@ lock_rec_get_first_on_page_addr( ...@@ -145,19 +145,22 @@ lock_rec_get_first_on_page_addr(
return(NULL); return(NULL);
} }
/** Gets the first record lock on a page, where the page is identified by a /*********************************************************************//**
Gets the first record lock on a page, where the page is identified by a
pointer to it. pointer to it.
@param[in] lock_hash lock hash table
@param[in] space page's space id
@param[in] page_no page number
@param[in] hash page's hash value in records hash table
@return first lock, NULL if none exists */ @return first lock, NULL if none exists */
UNIV_INLINE UNIV_INLINE
lock_t *lock_rec_get_first_on_page(hash_table_t *lock_hash, ulint space, lock_t*
ulint page_no, ulint hash) lock_rec_get_first_on_page(
/*=======================*/
hash_table_t* lock_hash, /*!< in: lock hash table */
const buf_block_t* block) /*!< in: buffer block */
{ {
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
ulint space = block->page.id.space();
ulint page_no = block->page.id.page_no();
ulint hash = buf_block_get_lock_hash_val(block);
for (lock_t* lock = static_cast<lock_t*>( for (lock_t* lock = static_cast<lock_t*>(
HASH_GET_FIRST(lock_hash, hash)); HASH_GET_FIRST(lock_hash, hash));
...@@ -174,20 +177,6 @@ lock_t *lock_rec_get_first_on_page(hash_table_t *lock_hash, ulint space, ...@@ -174,20 +177,6 @@ lock_t *lock_rec_get_first_on_page(hash_table_t *lock_hash, ulint space,
return(NULL); return(NULL);
} }
/** Gets the first record lock on a page, where the page is identified by a
pointer to it.
@param[in] lock_hash lock hash table
@param[in] block buffer block
@return first lock, NULL if none exists */
UNIV_INLINE
lock_t *lock_rec_get_first_on_page(hash_table_t *lock_hash,
const buf_block_t *block)
{
return lock_rec_get_first_on_page(lock_hash, block->page.id.space(),
block->page.id.page_no(),
buf_block_get_lock_hash_val(block));
}
/*********************************************************************//** /*********************************************************************//**
Gets the next explicit lock request on a record. Gets the next explicit lock request on a record.
@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */ @return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */
...@@ -221,21 +210,21 @@ lock_rec_get_next_const( ...@@ -221,21 +210,21 @@ lock_rec_get_next_const(
return(lock_rec_get_next(heap_no, (lock_t*) lock)); return(lock_rec_get_next(heap_no, (lock_t*) lock));
} }
/** Gets the first explicit lock request on a record. /*********************************************************************//**
@param[in] hash hash chain the lock on Gets the first explicit lock request on a record.
@param[in] space record's space id
@param[in] page_no record's page number
@param[in] lock_hash_val page's hash value in records hash table
@param[in] heap_no heap number of the record
@return first lock, NULL if none exists */ @return first lock, NULL if none exists */
UNIV_INLINE UNIV_INLINE
lock_t *lock_rec_get_first(hash_table_t *hash, ulint space, ulint page_no, lock_t*
uint32_t lock_hash_val, ulint heap_no) lock_rec_get_first(
/*===============*/
hash_table_t* hash, /*!< in: hash chain the lock on */
const buf_block_t* block, /*!< in: block containing the record */
ulint heap_no)/*!< in: heap number of the record */
{ {
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
for (lock_t* lock = lock_rec_get_first_on_page(hash, space, page_no, for (lock_t* lock = lock_rec_get_first_on_page(hash, block); lock;
lock_hash_val); lock; lock = lock_rec_get_next_on_page(lock)) { lock = lock_rec_get_next_on_page(lock)) {
if (lock_rec_get_nth_bit(lock, heap_no)) { if (lock_rec_get_nth_bit(lock, heap_no)) {
return(lock); return(lock);
} }
...@@ -244,20 +233,6 @@ lock_t *lock_rec_get_first(hash_table_t *hash, ulint space, ulint page_no, ...@@ -244,20 +233,6 @@ lock_t *lock_rec_get_first(hash_table_t *hash, ulint space, ulint page_no,
return(NULL); return(NULL);
} }
/** Gets the first explicit lock request on a record.
@param[in] hash hash chain the lock on
@param[in] block block containing the record
@param[in] heap_no heap number of the record
@return first lock, NULL if none exists */
UNIV_INLINE
lock_t *lock_rec_get_first(hash_table_t *hash, const buf_block_t *block,
ulint heap_no)
{
return lock_rec_get_first(hash, block->page.id.space(),
block->page.id.page_no(),
buf_block_get_lock_hash_val(block), heap_no);
}
/*********************************************************************//** /*********************************************************************//**
Gets the nth bit of a record lock. Gets the nth bit of a record lock.
@return TRUE if bit set also if i == ULINT_UNDEFINED return FALSE*/ @return TRUE if bit set also if i == ULINT_UNDEFINED return FALSE*/
......
...@@ -425,9 +425,7 @@ struct trx_lock_t { ...@@ -425,9 +425,7 @@ struct trx_lock_t {
trx_que_t que_state; /*!< valid when trx->state trx_que_t que_state; /*!< valid when trx->state
== TRX_STATE_ACTIVE: TRX_QUE_RUNNING, == TRX_STATE_ACTIVE: TRX_QUE_RUNNING,
TRX_QUE_LOCK_WAIT, ... */ TRX_QUE_LOCK_WAIT, ... */
/** Transaction being waited for; protected by the same mutexes as
wait_lock */
trx_t* wait_trx;
lock_t* wait_lock; /*!< if trx execution state is lock_t* wait_lock; /*!< if trx execution state is
TRX_QUE_LOCK_WAIT, this points to TRX_QUE_LOCK_WAIT, this points to
the lock request, otherwise this is the lock request, otherwise this is
......
This diff is collapsed.
/***************************************************************************** /*****************************************************************************
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 2022 MariaDB Corporation. Copyright (c) 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -487,13 +487,9 @@ lock_prdt_add_to_queue( ...@@ -487,13 +487,9 @@ lock_prdt_add_to_queue(
} }
} }
/* Note: We will not pass any conflicting lock to lock_rec_create(), lock = lock_rec_create(
because we should be moving an existing waiting lock request. */
ut_ad(!(type_mode & LOCK_WAIT) || trx->lock.wait_trx);
lock = lock_rec_create(NULL,
#ifdef WITH_WSREP #ifdef WITH_WSREP
NULL, /* FIXME: replicate SPATIAL INDEX locks */ NULL, NULL, /* FIXME: replicate SPATIAL INDEX locks */
#endif #endif
type_mode, block, PRDT_HEAPNO, index, trx, type_mode, block, PRDT_HEAPNO, index, trx,
caller_owns_trx_mutex); caller_owns_trx_mutex);
...@@ -583,7 +579,9 @@ lock_prdt_insert_check_and_lock( ...@@ -583,7 +579,9 @@ lock_prdt_insert_check_and_lock(
trx_mutex_enter(trx); trx_mutex_enter(trx);
err = lock_rec_enqueue_waiting( err = lock_rec_enqueue_waiting(
#ifdef WITH_WSREP
NULL, /* FIXME: replicate SPATIAL INDEX locks */ NULL, /* FIXME: replicate SPATIAL INDEX locks */
#endif
LOCK_X | LOCK_PREDICATE | LOCK_INSERT_INTENTION, LOCK_X | LOCK_PREDICATE | LOCK_INSERT_INTENTION,
block, PRDT_HEAPNO, index, thr, prdt); block, PRDT_HEAPNO, index, thr, prdt);
...@@ -831,9 +829,9 @@ lock_prdt_lock( ...@@ -831,9 +829,9 @@ lock_prdt_lock(
lock_t* lock = lock_rec_get_first_on_page(hash, block); lock_t* lock = lock_rec_get_first_on_page(hash, block);
if (lock == NULL) { if (lock == NULL) {
lock = lock_rec_create(NULL, lock = lock_rec_create(
#ifdef WITH_WSREP #ifdef WITH_WSREP
NULL, /* FIXME: replicate SPATIAL INDEX locks */ NULL, NULL, /* FIXME: replicate SPATIAL INDEX locks */
#endif #endif
ulint(mode) | type_mode, block, PRDT_HEAPNO, ulint(mode) | type_mode, block, PRDT_HEAPNO,
index, trx, FALSE); index, trx, FALSE);
...@@ -863,8 +861,10 @@ lock_prdt_lock( ...@@ -863,8 +861,10 @@ lock_prdt_lock(
if (wait_for != NULL) { if (wait_for != NULL) {
err = lock_rec_enqueue_waiting( err = lock_rec_enqueue_waiting(
#ifdef WITH_WSREP
NULL, /* FIXME: replicate NULL, /* FIXME: replicate
SPATIAL INDEX locks */ SPATIAL INDEX locks */
#endif
ulint(mode) | type_mode, ulint(mode) | type_mode,
block, PRDT_HEAPNO, block, PRDT_HEAPNO,
index, thr, prdt); index, thr, prdt);
...@@ -948,9 +948,9 @@ lock_place_prdt_page_lock( ...@@ -948,9 +948,9 @@ lock_place_prdt_page_lock(
} }
if (lock == NULL) { if (lock == NULL) {
lock = lock_rec_create_low(NULL, lock = lock_rec_create_low(
#ifdef WITH_WSREP #ifdef WITH_WSREP
NULL, /* FIXME: replicate SPATIAL INDEX locks */ NULL, NULL, /* FIXME: replicate SPATIAL INDEX locks */
#endif #endif
mode, space, page_no, NULL, PRDT_HEAPNO, mode, space, page_no, NULL, PRDT_HEAPNO,
index, trx, FALSE); index, trx, FALSE);
......
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