例如:
交易1:select 'row 1' (s lock);
交易2:update 'row 1'(x lock);
交易1:update 'row 1'(x lock);
比事务2会死锁。
我不明白为什么innodb x锁必须等待先前的x锁(对于同一行,然后等待)释放?我认为事务2的x锁定实际上从未锁定过row1。并且事务1在行1上已经具有唯一的s锁。因此,我认为不必等待来自事务2的x锁定就可以进行事务1的更新操作。
[SELECT FOR UPDATE
获得X锁,而不是S锁。
您的示例中的事务2等待事务1。您可以通过以下方式查看它:
mysql> select * from sys.innodb_lock_waits\G
*************************** 1. row ***************************
wait_started: 2019-12-26 00:33:04
wait_age: 00:00:17
wait_age_secs: 17
locked_table: `test`.`mytable`
locked_table_schema: test
locked_table_name: mytable
locked_table_partition: NULL
locked_table_subpartition: NULL
locked_index: PRIMARY
locked_type: RECORD
waiting_trx_id: 5651
waiting_trx_started: 2019-12-26 00:33:04
waiting_trx_age: 00:00:17
waiting_trx_rows_locked: 1
waiting_trx_rows_modified: 0
waiting_pid: 9
waiting_query: update mytable set id = 2 where id = 1
waiting_lock_id: 4878281352:36:4:2:140455975282712
waiting_lock_mode: X,REC_NOT_GAP
blocking_trx_id: 5650
blocking_pid: 8
blocking_query: select * from sys.innodb_lock_waits
blocking_lock_id: 4878280464:36:4:2:140455975278104
blocking_lock_mode: X,REC_NOT_GAP
blocking_trx_started: 2019-12-26 00:32:49
blocking_trx_age: 00:00:32
blocking_trx_rows_locked: 1
blocking_trx_rows_modified: 0
sql_kill_blocking_query: KILL QUERY 8
sql_kill_blocking_connection: KILL 8
注意blocking_lock_mode
是X,而不是S。
事务1在您的示例中不等待,它只是更新了该行,因为它已被锁定。
事务2不会死锁。如果事务1不久不释放其锁,它最终将超时。这不是死锁,因为事务1没有等待事务2。