From 833c75da1c94584d095efa659e0546e2b031926c Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Wed, 6 Mar 2013 11:49:57 +0530 Subject: [PATCH] Bug #16133801 UNEXPLAINABLE INNODB UNIQUE INDEX LOCKS ON DELETE + INSERT WITH SAME VALUES Problem: When a transaction is in READ COMMITTED isolation level, gap locks are still taken in the secondary index, when row is inserted. This happens when the secondary index is scanned for duplicate. The function row_ins_scan_sec_index_for_duplicate() always calls the function row_ins_set_shared_rec_lock() with LOCK_ORDINARY irrespective of the transaction isolation level. Solution: The function row_ins_scan_sec_index_for_duplicate() calls the function row_ins_set_shared_rec_lock() with LOCK_ORDINARY or LOCK_REC_NOT_GAP based on the transaction isolation level. rb://2035 approved by Krunal and Marko --- storage/innobase/row/row0ins.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 21afa9eff0d..8312ef38311 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. 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 @@ -1698,6 +1698,7 @@ row_ins_scan_sec_index_for_duplicate( do { const rec_t* rec = btr_pcur_get_rec(&pcur); const buf_block_t* block = btr_pcur_get_block(&pcur); + ulint lock_type; if (page_rec_is_infimum(rec)) { @@ -1707,6 +1708,16 @@ row_ins_scan_sec_index_for_duplicate( offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + /* If the transaction isolation level is no stronger than + READ COMMITTED, then avoid gap locks. */ + if (!page_rec_is_supremum(rec) + && thr_get_trx(thr)->isolation_level + <= TRX_ISO_READ_COMMITTED) { + lock_type = LOCK_REC_NOT_GAP; + } else { + lock_type = LOCK_ORDINARY; + } + if (allow_duplicates) { /* If the SQL-query will update or replace @@ -1715,13 +1726,11 @@ row_ins_scan_sec_index_for_duplicate( INSERT ON DUPLICATE KEY UPDATE). */ err = row_ins_set_exclusive_rec_lock( - LOCK_ORDINARY, block, - rec, index, offsets, thr); + lock_type, block, rec, index, offsets, thr); } else { err = row_ins_set_shared_rec_lock( - LOCK_ORDINARY, block, - rec, index, offsets, thr); + lock_type, block, rec, index, offsets, thr); } switch (err) {