以前从未意识到这个问题,我一直以为 MySQL 在多线程数据同步问题上不需要使用者过多的考虑,内部有那么多机制能保证多线程下数据一致问题。最近在深挖 MySQL 的锁知识的时候,发现了这一段,官网描述:
https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html1 个表,存在唯一索引(主键索引也算唯一索引)。先让 1 个 session 去插入唯一索引所在列,然后 hold 在那里即不回滚,也不提交。此时另外启动两个 session,也插入同样的列值;这两个 session 为了检测唯一索引是否已经存在,会去申请共享锁,但由于此时第一个 session 持有互斥锁,会让后两个 session 申请共享锁的行为阻塞。2 和 3 的 session 就会等在那里;此时 1 的 session 回滚,释放掉互斥锁,2 和 3 的 session 会同时获得共享锁;他们要进一步获得互斥锁才能进行插入,但是,因为互斥锁和共享锁是冲突的,会形成,2 为了得到互斥锁必须等待 3 释放共享锁和 3 为了得到互斥锁也必须等待 2 释放共享锁的死锁现象,直到死锁超时回滚
我随便搜了一下发现这种死锁其实非常常见,网上有不少,在高一点的并发下 insert 就会出现死锁的情况。从原理上说,不需要 3 个 session,理论上,只要两个线程只要同时拿到共享锁就一定会发生死锁,
然而 mysql 官方并不认为这是个 bug。而我查到的解决办法居然是:在程序层上并发写变队列写(单线程写)。我总觉得这有点不合乎道理,有没有人聊聊其它家的数据库有解决方案吗,MySQL 的解决方法真的只有并发写变队列写这一条路了?
PS:如果关系数据库在写入上有这样的限制,我可不可以认为关系数据库实际是偏向“写少读多”场景的?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
https://www.v2ex.com/t/505341
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.