DB锁

自己其实也算对db的机制有不少时间投入,从刚工作参与的项目,充斥各种复杂sql,随之要求大家对sql语句的简洁与性能持续关注。新的互联网单位,又变换成充斥各种No-sql,缓存是一等公民,曾经的思索都忘的七七八八了。唯一碰到的深度讨论只是为什么innodb的数据文件不能缩小的问题,总结点什么吧。

Innodb的卖身故事

用mysql的人恐怕都知道innodb数据引擎,innodb的初始母Innobase公司成立于95年的芬兰,目标是开发一个事务引擎,且初始并不是开源的,但创始人死活找不到人买这个产品,才促成了2000年与mysql的合作,并促成了2001mysql第一次发布支持innodb引擎的版本。

虽然mysql多次尝试与innodb 公司想达成收购交易,但还是oracle资金雄厚,笑到最后,好在oracle并未对innodb做什么不好的事情。oracle用的并不是innodb,虽然他们的思路相同(用日志系统来支持事务和并发)。innodb引擎和oracle数据库引擎对于事务的隔离级别支持并不同。

Oracle的隔离级别

oracle只支持“读已提交”和“串行化”(不在标准之列的只读模式咱就不提了),且它的串行化的实现,也不是真正的串行化,而是类似于基于日志系统的可重复读。

对于应用来说,其看到的实际效果又跟理论上定义的串行化一致,因为看不到幻读的出现。oracle这种要性能不要对上隔离(屏蔽同步复杂性)的做法,我个人觉得还是很不好的,这种假串行太高估应用层开发人员的思维能力了,他们经常已经被业务搞死了,还要应付一遍这些繁琐的更新竞争问题。

oracle的串行化,当两个事务同时更新一条数据时,如a先获得锁,b更新等待。a提交后,b将抛出一个不可串行化错误。这种错误没有客户能理解,最好的办法还是通过业务锁(令牌)机制来处理。看这篇文章[2]

关于oracle的隔离级别细节,说实在的我没有过一手项目经验,更多细节还可参见[3],虽然我觉得其从设计动机的角度解释说明的亦不全靠谱

Innodb的隔离级别

Innodb作为开源的引擎,试图尽量与标准保持一致。但是其可重复读级别,在一定程度上也避免了幻读(通过间隙锁,你的读语句是范围查询,gap lock才有意义),但显然并不是真正的串行化(串行化要求读写可串行化),其可重复读隔离级别最好的解释看这里[1]

Innodb 的锁的详细解读,可参看这里[4]

后记

14 年当时想讲清的东西就很多,故此文一直未完工,但转去写了一个PPT,于2015年07月完工PPT,把想讲的内容都涵盖了。PPT上传过百度文库,也许有人看过。

参考