Description:
i found mysql will report deadlock when i 'select for update' even ‘update’ with same record in concurrency thread, with the error status of innodb:
=====================================
2018-03-23 15:22:19 0x7f0824272700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 16 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 249 srv_active, 0 srv_shutdown, 1559184 srv_idle
srv_master_thread log flush and writes: 1558877
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 460
OS WAIT ARRAY INFO: signal count 376
RW-shared spins 0, rounds 441, OS waits 193
RW-excl spins 0, rounds 1371, OS waits 25
RW-sx spins 1, rounds 28, OS waits 0
Spin rounds per wait: 441.00 RW-shared, 1371.00 RW-excl, 28.00 RW-sx
------------------------
LATEST DETECTED DEADLOCK
------------------------
2018-03-23 15:21:54 0x7f08241df700
*** (1) TRANSACTION:
TRANSACTION 349110, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 143, OS thread handle 139672943212288, query id 460994 10.5.17.15 loanuser statistics
select
ID, NAME
from t_deadlock
where ID = 'T1-9' for update
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 118 page no 3 n bits 80 index PRIMARY of table "test"."t_deadlock" trx id 349110 lock_mode X locks rec but not gap waiting
Record lock, heap no 11 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 54312d39; asc T1-9;;
1: len 6; hex 0000000553b4; asc S ;;
2: len 7; hex 3a0000021701fb; asc : ;;
3: len 1; hex 47; asc G;;
*** (2) TRANSACTION:
TRANSACTION 349111, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 141, OS thread handle 139672942409472, query id 460996 10.5.17.15 loanuser statistics
select
ID, NAME
from t_deadlock
where ID = 'T1-9' for update
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 118 page no 3 n bits 80 index PRIMARY of table "test"."t_deadlock" trx id 349111 lock mode S locks rec but not gap
Record lock, heap no 11 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 54312d39; asc T1-9;;
1: len 6; hex 0000000553b4; asc S ;;
2: len 7; hex 3a0000021701fb; asc : ;;
3: len 1; hex 47; asc G;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 118 page no 3 n bits 80 index PRIMARY of table "loan"."t_deadlock" trx id 349111 lock_mode X locks rec but not gap waiting
Record lock, heap no 11 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 54312d39; asc T1-9;;
1: len 6; hex 0000000553b4; asc S ;;
2: len 7; hex 3a0000021701fb; asc : ;;
3: len 1; hex 47; asc G;;
*** WE ROLL BACK TRANSACTION (2)
------------
TRANSACTIONS
------------
Trx id counter 349120
Purge done for trx's n:o < 349120 undo n:o < 0 state: running but idle
History list length 46
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421148215175928, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421148215175008, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
1693 OS file reads, 2440 OS file writes, 1097 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.81 writes/s, 0.62 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 1 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 2 buffer(s)
Hash table size 34673, node heap has 3 buffer(s)
Hash table size 34673, node heap has 2 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
0.19 hash searches/s, 0.56 non-hash searches/s
---
LOG
---
Log sequence number 186437447
Log flushed up to 186437447
Pages flushed up to 186437447
Last checkpoint at 186437438
0 pending log flushes, 0 pending chkp writes
858 log i/o's done, 0.38 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 1833906
Buffer pool size 8191
Free buffers 6459
Database pages 1724
Old database pages 639
Modified db pages 0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 1613, created 111, written 1469
0.00 reads/s, 0.00 creates/s, 0.37 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1724, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
0 read views open inside InnoDB
Process ID=990, Main thread ID=139672864941824, state: sleeping
Number of rows inserted 44210, updated 197, deleted 0, read 958895
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
How to repeat:
use multi-thread 'select for update' and update a record with same key(primary or unique key)
Suggested fix:
i don't understand why use S locker first when 'select for update' or 'update', maybe for other connection to read share, but i think the X locker need to lock at the point S locker locking, or the X locker could insert the locker order in first when the connection hold the S lock?