严格从MySQL的角度来看
SHORT VERSION
MyISAM Storage Engine
<表锁写是先到先得的,读操作会减慢写操作的启动速度
InnoDB Storage Engine
<更新索引时,可能会发生行锁(非阻塞)事务死锁
LONG VERSION如果基础表使用
MyISAM Storage Engine, 无法使用行锁定。每个DML语句(INSERT、UPDATE和DELETE)都会导致一个完整的表锁。
如果50个DB连接尝试更新中的onw行mydb.mytable
1个表锁,1个更新,49个DB连接等待1个表锁,1个更新,48个DB连接等待1个表锁,1个更新,47个DB连接等待
1个表锁,1个更新,02个DB连接等待1个表锁,1个更新,01个DB连接等待明白了吗?您可以在一个表上看到瓶颈发生的位置。现在,想象一下一个流量巨大的WordPress网站。SELECTs get priority优于DML语句(例外情况是在MyISAM表上进行并发插入,前提是MyISAM表只进行了SELECT和INSERT,两者之间没有间隙)。在DML语句之间进行数百次甚至数十次选择,可以进一步减缓上述瓶颈。MyISAM在流量巨大的WordPress网站上的可取之处在于,死锁永远不会发生。
如果基础表使用InnoDB Storage Engine, 行锁(即使在同一行上)永远不会阻止读取,但在写入期间仍然可能出现死锁。具有AUTOCOMMIT=0
设置为/etc/my。cnf中,每个DML语句(INSERT、UPDATE和DELETE)将作为单行事务执行。发出单独的行锁。因此,50 DB连接可以在50个不同的行之后进行,并且不会发生任何悲剧。
死锁从哪里来?
由于InnoDB表的主键包含在Clustered Index (internally known as the gen_clust_index), 行数据与索引项紧密耦合。针对不属于主键的列创建的任何索引都使用两个基本项进行编目,1)列值,2)gen\\u clust\\u索引键。有时,在InnoDB中更新索引列可能会导致我开玩笑地称之为索引便秘。当对彼此相邻存储的索引项生成两个或多个锁时,就会发生这种情况。这在一个流量很大的网站上是可能的。
我曾经帮助一位开发人员了解为什么会在DBA StackExchange中发生这种情况。该开发人员随后进行了代码更改。以下是这些帖子:
YOUR QUESTION
无论存储引擎如何,其中一个更新都将丢失。只有列的最后一次更新才会设置最终值。CONCLUSION
这篇文章不支持任何一个存储引擎。这些只是关于写入表时可能发生和将发生什么的事实。