若session 1回滚,释放排它锁,session 2和session 3则可获得共享锁,此时两session死锁,均持有共享锁,欲获得排它锁。实际测试证实此现象。但疑惑的是,若session 1 commit,为何不会导致死锁,这原因尚不明了,期待高手解答。MySQL锁机制复杂,看似简单的SQL操作有时会引发死锁,初次遇到时会感到困惑...
mysqlinsertinto...select语句为什么会造成死锁?
在实际开发中,我遇到过MySQL死锁问题,深入研究了MySQL的锁机制以及产生死锁的场景。
具体分析,如发现不正确之处,请指正!
确实,数据表中若无记录,同时并发插入两条统一条记录(包含唯一键相同)可能导致死锁。
设想三个session并发插入同一条记录(假设t1为唯一键):
插入操作会加排它锁。假设session 1获取排它锁,session 2和session 3则会报主键重复错误,此时行加共享锁。若有多个session尝试插入同一行,且另一session已持有排它锁,session 2和session 3均会尝试获得共享锁。若session 1回滚,释放排它锁,session 2和session 3则可获得共享锁,此时两session死锁,均持有共享锁,欲获得排它锁。
实际测试证实此现象。但疑惑的是,若session 1 commit,为何不会导致死锁,这原因尚不明了,期待高手解答。
MySQL锁机制复杂,看似简单的SQL操作有时会引发死锁,初次遇到时会感到困惑。
我曾总结过MySQL锁机制及常见死锁场景,分享了一个ppt,详情参见:技术分享-MySQL InnoDB locks and deadlocks。
以下提供一些有价值的参考资料:
(1)MySQL官方文档,详细介绍了InnoDB锁机制: MySQL :: MySQL 5.5 Reference Manual :: 14.8.3 Locks Set by Different SQL Statements in InnoDB。
(2)阿里巴巴DBA专家何登成的博客,提供了深入解析:何登成的技术博客。
(3)《高性能MySQL》一书,对MySQL锁机制有详细讲解。2024-08-26