Lock Manager
lock
- 检查事务的隔离级别是否符合锁的要求
REPEATABLE_READ:
The transaction is required to take all locks.
All locks are allowed in the GROWING state
No locks are allowed in the SHRINKING state
READ_COMMITTED:
The transaction is required to take all locks.
All locks are allowed in the GROWING state
Only IS, S locks are allowed in the SHRINKING state
READ_UNCOMMITTED:
The transaction is required to take only IX, X locks.
X, IX locks are allowed in the GROWING state.
S, IS, SIX locks are never allowed
-
是否是重复的锁请求
-
是否为锁升级
-
将锁请求加入队列
-
尝试获取锁,看这个请求与已经分配资源(granted)的请求(如有其他线程在读被分配了读锁)是否互斥或者说兼容;如果满足的话,其次看优先级,满足 fifo;
- 判断兼容性。遍历请求队列,查看当前锁请求是否与所有的已经 granted 的请求兼容。需要注意的是,在我的实现中 granted 请求不一定都在队列头部,因此需要完全遍历整条队列。锁兼容矩阵可以在 Lecture slides 中查看。若全部兼容,则通过检查。否则直接返回 false。当前请求无法被满足。
- 判断优先级。锁请求会以严格的 FIFO 顺序依次满足。只有当前请求为请求队列中优先级最高的请求时,才允许授予锁。优先级可以这样判断:
如果队列中存在锁升级请求,若锁升级请求正为当前请求,则优先级最高。否则代表其他事务正在尝试锁升级,优先级高于当前请求。- 若队列中不存在锁升级请求,则遍历队列。如果,当前请求是第一个 waiting 状态的请求,则代表优先级最高。如果当前请求前面还存在其他 waiting 请求,则要判断当前请求是否前面的 waiting 请求兼容。若兼容,则仍可以视为优先级最高。若存在不兼容的请求,则优先级不为最高
这里有个问题,尝试获取锁的时候,确定了当前 request 不是升级锁的请求,且判断了之前的 waiting 的 request 都与当前的兼容,那么可以获取锁(具有相同的最高优先级),那么之前 waiting 的 request 呢?
这里这段话来自 shiyi
unlock
- 对于 table lock,释放时检查所有的 rowlock 是否已经释放
- 获取对应的 lock request queue
- 遍历请求队列,找到 unlock 对应的 granted 请求
当隔离级别为 REPEATABLE_READ 时,S/X 锁释放会使事务进入 Shrinking 状态。当为 READ_COMMITTED 时,只有 X 锁释放使事务进入 Shrinking 状态。当为 READ_UNCOMMITTED 时,X 锁释放使事务 Shrinking,S 锁不会出现。