大数跨境
0
0

数据库的并发bug分析

数据库的并发bug分析 摩尔线程
2024-07-17
0
导读:前面的文章我简单介绍了关于mysql的并发访问控制,也就是锁,但是锁如果用的不好的话,很容易就会出现问题,今天

前面的文章我简单介绍了关于mysql的并发访问控制,也就是锁,但是锁如果用的不好的话,很容易就会出现问题,今天我们就来分析一些比较常见的bug。

我们首先看下面这一章图片, 下面这张图片一共有四个事务,其中前面两个事务做的事情主要是查询对应的数据,另外两个事务做的事情是修改对应的字段。

在mysql中其实是有一种锁在对表进行增删改查的时候会自动的被加上, 读锁之间是不互斥的,是可以存在多个线程进行访问的。

所以我们的session1和 session2 之间不是互斥的, 所以这两个之间是不互斥的,但是session3是互斥的, 因为这种互斥导致出现的问题就是session3被阻塞。

由于session3被阻塞等待,导致整个数据库完全不可以进行读写了。

那么我们如何去解决这个问题呢, 我们主要有两种方法,第一种方法是将前面这个比较长的事务给杀死,第二种方法是设置超时时间。

看完上面这个并发bug的分析,我们接下来分析一下关于行锁的一个bug,

在session1中我们存在一个事务,这个事务做的事情就是对一行进行一次更改, 然后存在session2这个事务,这个事务也是对一个行进行修改。

这个问题的本质就是持有锁的对象是谁, 要搞明白这个问题, 我们需要知道innodb的锁的规则, 在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。

当我们知道这个规则之后, 我们就知道了session2的更新语句其实是会被锁住的, 因为session1的锁并没有被释放。只有当session1提交之后才会继续更新。

分析完成这件事情之后,我们可以看一下一种出现死锁的情况: 死锁出现的原因主要是因为竞争资源而出现等待的情况。

我们看上面这个例子, 上面这个例子就是一个典型的死锁问题,这是因为session2的更新语句是在等待session1的锁被释放, 而session1的第二条更新语句也是等待session2的锁释放。

这样就导致出现相互等待的情况, 进入死锁的情况,出现这种死锁的时候, 一般存在两种解决方案

- 设置超时时间, 比如innodb_lock_time,但是这种时间我们可以稍微设。置的比较长一点, 因为设置短时的很有可能出现误伤。

- 另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑。

【声明】内容源于网络
0
0
摩尔线程
摩尔线程以全功能 GPU 为核心,致力于向全球提供计算加速的基础设施和一站式解决方案,为各行各业的数智化转型提供强大的AI计算支持。
内容 301
粉丝 0
摩尔线程 摩尔线程以全功能 GPU 为核心,致力于向全球提供计算加速的基础设施和一站式解决方案,为各行各业的数智化转型提供强大的AI计算支持。
总阅读115
粉丝0
内容301