成熟的数据库设计中,需要一个模块对资源的并发控制进行管理。意向锁就是实现资源并发控制管理的经典方式。在讨论它的概念与设计前,我们先举几个MongoDB的经典场景。
- mongoDB 默认是行级并发,我们希望多行并发读写互不影响,但是我们又希望对在dropCollection时,不能有任何对表的读写在操作,这个“不希望”也是双向的,即在对表并发读写时,我们也不希望dropCollection在操作。
在执行dbStats命令时,希望和dropDB/insert命令互斥,但是又不影响对表的并发读。
由于写每个db的每张表,都须要往oplog中写记录,因此oplog是全局的,我们希望在truncate oplog这个全局操作在进行时,任何db对oplog的写操作都被阻塞。
第一个例子中,我们似乎用传统的rwlock就可以解决,在对表进行并发读写前,加rlock,在对表进行dropCollection前,加wlock。 暂不论rwlock的r状态和并发写的行为不一致,至少这样是行得通的。 可是遇到了第二个例子,我们发现rwlock的rw两个状态无法表达我们的锁需求了,到了第三个例子,只要能隐约觉得,这个锁,还得有层级结构。
而意向锁协议,是一种对树形(层级)资源进行并发控制的协议。它由"操作约定"和"冲突矩阵"两部分组成,且看下文。
02
MongoDB中的意向锁的定义
MongoDb使用了简化版的意向锁协议,抛却了SIX状态,保留了 IS/IX/S/X四种锁状态。其冲突矩阵为:
其使用方式为:
-
对一个节点加IX/X锁时,必须先(递归)获取其父节点的IX锁。
-
对一个节点加IS/S锁时,必须先(递归)获取其父节点的IS锁。
举个例子:MongoDB中的资源层级结构如下: