手写MySQL(七)VM模块篇-死锁检测与VM的实现

本文深入探讨了MySQL中两阶段锁协议(2PL)引发的死锁问题,详细阐述了死锁的成因,并通过代码示例展示了死锁检测的算法。在检测到死锁时,系统会撤销事务以解除死锁状态。此外,文章还介绍了如何在内存中维护等待图以辅助死锁检测,并分析了具体的检测流程。

代码地址:GitHub - zhangqingqing24630/MySQL-

此项目来源于何人听我楚狂声

目录

死锁

死锁的造成

死锁检测

测试代码

分析流程

VM其他实现方法

获取缓存

从图中删除事务

删除版本


本节将收尾 VM 层,以及mysql 如何检测 2PL 导致的死锁,还介绍了一些上一章节没有介绍到的方法。

死锁

死锁的造成

在mysql中,两阶段锁协议(2PL)通常包括扩张和收缩两个阶段。在扩张阶段,事务将获取锁,但不能释放任何锁。在收缩阶段,可以释放现有的锁,但不能获取新的锁,这种规定存在着死锁的风险。


例如:当T1’在扩张阶段,获取了Y的读锁,并读取了Y,此时想要去获取X的写锁,却发现T2’的读锁锁定了X,而T2’也想要获取Y的写锁。简而言之,T1’不得到X是不会释放Y的,T2’不得到Y也是不会释放X的,这便陷入了循环,便形成了死锁。

死锁检测

前面提到了 2PL 会阻塞事务,直至持有锁的线程释放锁。可以将这种等待关系抽象成有向边,例如 Tj 在等待 Ti,就可以表示为 Tj --> Ti。这样,无数有向边就可以形成一个图(不一定是连通图)。检测死锁也就简单了,只需要查看这个图中是否有环即可。

创建一个 LockTable 对象,在内存中维护这张图。维护结构如下:

public class LockTable {

    private Map<Long, List<Long>> x2u;  // 某个XID已经获得的资源的UID列表
    private Map<Long, Long> u2x;        // UID被某个XID持有
    private Map<Long, List<Long>> wait; // 正在等待UID的XID列表
    private Map<Long, Lock> waitLock;   // 正在等待资源的XID的锁
    private Map<Long, Long> waitU;      // XID正在等待的UID
    private Lock lock;

    ...
}

在每次出现等待的情况时,就尝试向图中增加一条边,并进行死锁检测。如果检测到死锁,就撤销这条边,不允许添加,并撤销该事务。

// 不需要等待则返回null,否则返回锁对象
// 会造成死锁则抛出异常
public Lock add(long xid, long uid) throws Exception {
        lock.lock();
        try {
            //某个xid已经获得的资源的UID列表,如果在这个列表里面,则不造成死锁,也不需要等待
            if(isInList(x2u, xid, uid)) {//x2u xid list<uid>
                return null;
            }
            //这里表示有了一个新的uid,则把uid加入到u2x和x2u里面,不死锁,不等待
            //u2x  uid被某个xid占有
            if(!u2x.containsKey(uid)) {//uid xid
                u2x.put(uid, xid);
                putIntoList(x2u, xid, uid);
                return null;
            }
            //以下就是需要等待的情况
            //多个事务等待一个uid的释放
            waitU.put(xid, uid);//把需要等待uid的xid添加到等待列表里面
            //System.out.println("waitU"+waitU);
            putIntoList(wait,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值