CMU15445 FALL2022 Project #4 - Concurrency Control

CMU15445 FALL2022 Project #4 - Concurrency Control

四种隔离级别

  • 未提交读(Read uncommitted)

    • 这种事务隔离级别下,select语句不加锁,事务中修改的数据,即使没有提交,对其他事务也都是可见的。
    • 此时,可能读取到不一致的数据,即“读脏 ”。这是并发最高,一致性最差的隔离级别。
  • 提交读(Read committed)

    • 一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。
    • 大多数数据库系统的默认隔离级别都是提交读(但Mysql不是)。
    • 提交读满足前面提到的隔离性的简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。可避免脏读,无法避免不可重复读发生。
    • 因为两次执行同样的查询,可能会得到不一样的结果,这个级别有时候也叫做不可重复读(nonrepeatable read)。
  • 可重复读(Repeatable read)

    • 该级别保证了在同一个事务中多次读取同样记录的结果是一致的,事务中未提交的数据对其他事务是不可见的,解决 脏读 、不可重复读 的问题,是MySql默认隔离级别,但会发生幻读。
  • 串行化(Serializable )

    • 可串行化是最高的隔离级别。它通过强制事务串行执行,避免了脏读、不可重复读、幻读的问题。

三种问题

  • 脏读:A事务正在修改数据但未提交,此时B事务去读取此条数据,B事务读取的是未提交的数据,A事务回滚。
  • 不可重复读:A事务中两次查询同一数据的内容不同,B事务间在A事务两次读取之间更改了此条数据。
  • 幻读:在同一事务中两次相同查询数据的条数不一致,例如第一次查询查到5条数据,第二次查到8条数据,这是因为在两次查询的间隙,另一个事务插入了3条数据。
Task #1 - Lock Manager

LockTable(Transaction, LockMode, TableOID)

  • 如果stateCOMMITEDABORTE,直接返回

  • 检查所请求的LockMode与隔离级别、state的兼容性,ABORTED并抛出异常

    • READ_UNCOMMITTED
      • LockMode只能是EXCLUSIVE或者INTENTION_EXCLUSIVEABORTED并抛出异常
      • 如果stateSHRINKING,且LockModeEXCLUSIV或者INTENTION_EXCLUSIVEABORTED并抛出异常
    • READ_COMMITTED
      • 如果stateSHRINKING,且LockModeSHARED或者INTENTION_SHAREDABORTED并抛出异常
    • REPEATABLE_READ
      • 如果stateSHRINKINGABORTED并抛出异常
  • table_lock_map_中找到oid对应的queue,如果没有则创建一个,注意先给queue上锁,再释放map锁

  • 循环判断queue中是否有id相同的,如果有

    • 如果LockMode相同,说明已经获得该锁,直接返回

    • 判断当前锁请求是否为一个锁升级upgrading请求,不是直接ABORTED并抛出异常

    • 判断IsUpgradeCompatible,是否能够upgrading,不能直接ABORTED并抛出异常

      • INTENTION_SHARED可以upgrading为SHAREDEXCLUSIVEINTENTION_EXCLUSIVESHARED_INTENTION_EXCLUSIVE
      • SHARED可以upgrading为EXCLUSIVESHARED_INTENTION_EXCLUSIVE
      • INTENTION_EXCLUSIVE可以upgrading为EXCLUSIVESHARED_INTENTION_EXCLUSIVE
      • SHARED_INTENTION_EXCLUSIVE可以upgrading为EXCLUSIVE
    • 移除已有的锁请求,在queue中删除找到的request,对应TableLockSet也删除对应得

    • 创建新的升级锁请求,并插入到queue第一个未被授权的锁请求前(FIFO),之后加锁等待授权

      • 遍历queue,对于已授予的锁请求判断是否兼容
        • SHARED 锁与INTENTION_EXCLUSIVESHARED_INTENTION_EXCLUSIVEEXCLUSIVE 锁不兼容
        • EXCLUSIVE 锁不与任何其他锁兼容
        • INTENTION_SHARED 锁与 EXCLUSIVE 锁不兼容
        • INTENTION_EXCLUSIVE 锁与SHAREDSHARED_INTENTION_EXCLUSIVEEXCLUSIVE 锁不兼容
        • SHARED_INTENTION_EXCLUSIVE 锁只与 INTENTION_SHARED 锁兼容
        • 如果遇到未授权的锁,且不是当前的锁返回false
      • 如果遇到state变为ABORTED,从queue删除,并唤醒等待的线程,返回
    • 确定可以授权后,TableLockSet中加入request,如果不是EXCLUSIVE则唤醒等待的线程,返回true

  • queue没有id相同请求,直接创建新请求,插入queue,然后相同判断授权后进行插入唤醒

UnlockTable(Transction, TableOID)

  • table_lock_map_中找到oid对应的queue,如果没有ABORTED并抛出异常
  • 检查在解锁表之前是否有行级锁被事务持有,如果有,则抛出异常,确保了在解锁表之前所有行级锁都已经被释放
  • 在锁请求队列中查找当前事务已经被授予的锁请求,然后移除该锁请求并通知所有等待的线程
  • 根据事务的隔离级别,更新事务的状态并返回解锁操作是否成功的标志
    • REPEATABLE_READ 下如果解锁的锁模式是 SHARED 或独占锁 EXCLUSIVE,转state为 SHRINKING
    • READ_COMMITTED 下如果解锁的锁模式是 EXCLUSIVE,转state为 SHRINKING
    • READ_UNCOMMITTED 下解锁的锁模式是 EXCLUSIVE,转state为 SHRINKING
    • SHRINKING 状态通常表示事务已经释放了一些资源,但尚未完成全部工作
  • TableLockSet中删除对应request

LockRow(Transaction, LockMode, TableOID, RID)

  • 开始如果判断 LockMode为意向锁直接ABORTED并抛出异常

  • 增加判断如果LockModeEXCLUSIVE

    • 如果表没有该表的EXCLUSIVEINTENTION_SHARED或者SHARED_INTENTION_EXCLUSIVE
    • 直接ABORTED并抛出异常
  • 后面大体与LockTable相同

UnlockRow(Transaction, TableOID, RID)

  • 与UnlockTable大体相同,不需要判断是否有行级锁被事务持有
Task #2 - Deadlock Detection

AddEdge(txn_id_t t1, txn_id_t t2)

  • 在txn_set_中插入t1、t2
  • waits_for_的t1中插入t2

RemoveEdge(txn_id_t t1, txn_id_t t2)

  • waits_for_的t1中删除t2

HasCycle(txn_id_t& txn_id)

  • 使用Dfs搜寻是否存在cycle,并且返回cycle中最大的txn_id

GetEdgeList()

  • 返回所有的边

RunCycleDetection()

  • 循环休眠监测,首先对表和行的lock map加锁

  • 循环遍历表级锁请求

    • 初始化一个 granted_set 集合,用于存储已经授予的事务 ID
    • 如果已授权,存入granted_set
    • 否则表示该事务正在等待
      • 记录其依赖关系(等待图的边),将锁请求的事务ID和锁请求的表ID存入map_txn_oid_,方便后续唤醒等待该表锁的其他事务
      • 将当前事务 ID 和所有已授予锁的事务 ID 添加到等待图中
  • 循环遍历行级锁请求

    • 初始化一个 granted_set 集合,用于存储已经授予的事务 ID
    • 如果已授权,存入granted_set
    • 否则表示该事务正在等待
      • 记录其依赖关系(等待图的边),将锁请求的事务ID和锁请求的行ID存入map_txn_oid_,方便后续唤醒等待该表锁的其他事务
      • 将当前事务 ID 和所有已授予锁的事务 ID 添加到等待图中
  • 循环调用 HasCycle 函数检测等待图中是否存在环路(死锁)

    • 如果检测到死锁,终止环路中的事务,将其状态设置为 ABORTED
    • 从等待图中移除被中止的事务节点
    • 通知等待该事务释放锁的其他事务
    • 清理等待图和相关数据结构
Task #3 - Concurrent Query Execution

seq_scan_executor

  • init时如果IsolationLevel不是READ_UNCOMMITTED,要获取表的INTENTION_SHARED
  • Next时如果IsolationLevel不是READ_UNCOMMITTED,要获取行的SHARED
  • 如果没有下一个iter且IsolationLevelREAD_COMMITTED,释放所有的行锁和表锁,返回

insert_executor

  • init时要获取表的INTENTION_EXCLUSIVE
  • Next时要获取行的EXCLUSIVE

delete_executor

  • init时要获取表的INTENTION_EXCLUSIVE
  • Next时要获取行的EXCLUSIVE
    最后放个线上测试图
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值