Insert delete的情况如何保证concurrency
- 尝试上锁时,会默认这个锁锁住了所有的内容
- 但是这个当我们往这些内容里添加了新的东西后,我们可能就会读到一些不对的数据。
- 比如说一页中有7条数据,t1尝试读取其中的最大的数据,那么t1会首先尝试锁住这7条数据所在的位置,但是T2可以往里面insert东西,这个insert不受t1的这个锁的影响,这时t1的读取的操作就可能会读到不对的数据。
解决方案1:index locking
T1 锁住保存index的页面,如果没有index的page,则必须lock所有tuple并且lock住整张表。
Predicate locking
锁住所有满足一定条件的数据:age > 2*salary
一种简单的tree-locking 算法
搜索(Search)操作:
过程:搜索操作从树的根节点开始,然后逐层向下遍历。
对每一个子节点获取共享锁(S锁),然后解除对父节点的锁定。
这样做的目的是为了确保在搜索路径上,只有当前正在访问的节点是锁定的,而路径上的其他节点是解锁状态,以便其他事务可以并发地访问这些节点。
目的:通过只锁定正在访问的节点,并解锁不再需要的节点,提高并发性,同时保证搜索过程的一致性。
- 插入/删除(Insert/Delete)操作:
过程:插入或删除操作也从树的根节点开始,逐层向下遍历,并在需要时获取排他锁(X锁)。
当锁定了子节点之后,需要检查该节点是否是“安全的”。
如果该节点是安全的,意味着它的结构变化(如插入或删除)不会传播到更高的层级,那么可以解除对祖先节点的锁定。
目的:通过只在需要时锁定特定节点,并在可能的情况下尽早释放锁,来减少锁的持有时间,从而提高系统的并发性。
- 安全节点(Safe Node):
定义:安全节点是指在对其进行插入或删除操作时,结构变化不会向上传播到该节点的祖先节点。
插入时:节点未满,意味着可以安全地插入数据而不会引发节点分裂或其他结构调整。
删除时:节点不为空且数据量超过一半,意味着可以安全地删除数据而不会引发节点合并或其他结构调整。
作用:确定节点是否安全可以帮助决定是否需要继续保持对祖先节点的锁定,从而优化锁的管理,减少锁冲突和死锁的可能性。
一种更好的tree-locking 算法
- search 不变,
- insert/delete需要变化,假设只变叶节点,只对路径上的节点设置共享锁,只对子节点设置排他锁
- 由于大多数情况都不需要改变非叶节点,所以大多数情况木有问题
- 在有问题的时候,重启事务,使用上一个算法
不使用lock的办法 Kung-Robinson Model
- 如果冲突很少发生,为了获得concurrency,我们可以不使用锁,而是通过在transaction的操作 commit之前寻找conflict的方式来获得。
锁的缺点:
- 锁管理有较大的开销。
- 死锁检测/解决。
- 对于频繁使用的对象,可能会出现锁竞争。
Kung-Robinson Model
Kung-Robinson Model分为三个阶段
- 读 READ: Xacts read from the database, but make changes to private copies of objects.
- 验证 VALIDATE: Check for conflicts.
- 写 WRITE: Make local copies of changes public.
那么validate这一步就至关重要了
- 我们为每一个事务维护一个 readset和modifyset,分别记录其在什么时间对什么东西进行了修改,在对一个relation进行写入时,都需要查看操作这个relation的其他xact的这两个set。
三个test
- 这种情况,tj不会读到dirty的数据
- 这种情况,tj会读到dirty的数据,但是不会覆盖ti写入的数据