summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0sel.cc
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-05-29 08:54:33 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-05-29 08:54:33 +0300
commit35a9c90fff5e2b8ffc5acc7d7ed051f04c013213 (patch)
tree7b7647ad28bdac118f02238aa2b578af4ea4a2a8 /storage/innobase/row/row0sel.cc
parentd8da920264a0321e6d03b3cbe3c3b414f622aefa (diff)
downloadmariadb-git-35a9c90fff5e2b8ffc5acc7d7ed051f04c013213.tar.gz
MDEV-14589 InnoDB should not lock a delete-marked record
When the transaction isolation level is SERIALIZABLE, or when a locking read is performed in the REPEATABLE READ isolation level, InnoDB must lock delete-marked records in order to prevent another transaction from inserting something. However, at READ UNCOMMITTED or READ COMMITTED isolation level or when the parameter innodb_locks_unsafe_for_binlog is set, the repeatability of the reads does not matter, and there is no need to lock any records. row_search_for_mysql(): Skip locks on delete-marked committed records upfront, instead of invoking row_unlock_for_mysql() afterwards. The unlocking never worked for secondary index records.
Diffstat (limited to 'storage/innobase/row/row0sel.cc')
-rw-r--r--storage/innobase/row/row0sel.cc35
1 files changed, 21 insertions, 14 deletions
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 7af788973f2..06bf4cc30c0 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -4656,9 +4656,27 @@ wrong_offs:
ulint lock_type;
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
+ /* At READ COMMITTED or READ UNCOMMITTED
+ isolation levels, do not lock committed
+ delete-marked records. */
+ if (!rec_get_deleted_flag(rec, comp)) {
+ goto no_gap_lock;
+ }
+ if (trx_id_t trx_id = index == clust_index
+ ? row_get_rec_trx_id(rec, index, offsets)
+ : row_vers_impl_x_locked(rec, index, offsets)) {
+ if (trx_rw_is_active(trx_id, NULL)) {
+ /* The record belongs to an active
+ transaction. We must acquire a lock. */
+ goto no_gap_lock;
+ }
+ }
+ goto locks_ok_del_marked;
+ }
+
if (!set_also_gap_locks
- || srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED
|| (unique_search && !rec_get_deleted_flag(rec, comp))) {
goto no_gap_lock;
@@ -4849,20 +4867,9 @@ locks_ok:
page_rec_is_comp() cannot be used! */
if (rec_get_deleted_flag(rec, comp)) {
-
+locks_ok_del_marked:
/* The record is delete-marked: we can skip it */
- if ((srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
- && prebuilt->select_lock_type != LOCK_NONE
- && !did_semi_consistent_read) {
-
- /* No need to keep a lock on a delete-marked record
- if we do not want to use next-key locking. */
-
- row_unlock_for_mysql(prebuilt, TRUE);
- }
-
/* This is an optimization to skip setting the next key lock
on the record that follows this delete-marked record. This
optimization works because of the unique search criteria