首页 > 数据库技术 > 详细

「DB」读取问题、隔离级别和锁

时间:2020-03-12 23:46:01      阅读:157      评论:0      收藏:0      [点我收藏+]

https://mp.weixin.qq.com/s/201mUftRWEFcxx9W_zsD2w

感谢欣哥!←最会讲故事的程序员!

? 数据库可能出现的问题

更新丢失

概念

  • 两个不同事务同时获得相同数据,然后在各自事务中修改数据,那么先提交的事务更新会被后提交事务的更新覆盖掉,导致「更新丢失」

解决办法

  • 引入「排他锁(Exclusive Lock)」,简称「X锁」。
  • 「X锁」不能与其它锁并存,而且只有一个事务能拿到某一数据行的「X锁」,其余事务不能再获取该数据行的所有锁。

漫画图解

技术分享图片

脏读

概念

  • 事务A读取了事务B未提交的数据,由于事务B回滚,导致了事务A数据的不一致,结果事务A出现了「脏读」

解决办法

  • 引入「共享锁(Share Lock)」,简称「S锁」。
  • 共享锁和排他锁不同,主要用于读取数据。
  • 如果一个数据加了X锁,就不能再加「S锁」;加了「S锁」,不能加X锁。
  • 「S锁」用完立刻释放。

漫画图解

技术分享图片

不可重复读

概念

  • 一个事务再自己没有更新数据库的情况下,同一个查询操作执行两次或多次得到的数值不同,因为别的事务更新了该数据,并且提交了事务。

解决办法

  • S锁保持锁定,直到事务提交。

漫画图解

技术分享图片

幻读

概念

  • 事务A读的时候读出了N条记录,事务B在事务A执行的过程中增加了一条,事务A再读的时候变成了N+1条,这种情况就叫做「幻读」

解决办法

  • 数据库事务隔离级别的终极大招:「Serializable(串行化)」

漫画图解

技术分享图片

?? 隔离级别

技术分享图片

Read Uncommited-读未提交

  • 写数据时加上X锁,直到事务结束。
  • 读的时候不加锁。
  • 虽然能够避免丢失数据,但是会读到没有提交或者回滚的数据(脏读)。
  • 这是数据库最低的隔离级别。

Read Commited-读已提交

  • 写数据的时候加上X锁,直到事务结束。
  • 读的适合加上S锁,读完数据立刻释放。
  • 可以避免「丢失数据」和「脏读」,但是会出现「不可重复读」的问题。
  • 这是数据库的第二级事务隔离级别。

Repeatable Read-可重复读

  • 写数据的时候加上X锁,直到事务结束。
  • 读的适合加上S锁,也是直到事务结束。
  • 可以避免「丢失数据」、「脏读」以及「不可重复读」的三个问题。
  • 这是数据库的常用(默认)事务隔离级别,简称RR。

Serializable-串行化

  • 事务one by one的执行,不能并发执行。
  • 最严格的事务隔离级别。

?? MySQL的几种锁

感谢 https://zhuanlan.zhihu.com/p/48127815 ??

共享锁

相关概念

  • 多个事务的查询语句可以共用一把共享锁;
  • 如果只有一个事务拿到了「共享锁」,则该事务可以对数据进行 UPDATE DETELE 等操作;
  • 如果有多个事务拿到了「共享锁」,则所有事务都不能对数据进行 UPDATE DETELE 等操作。

使用场景

  • 确保某个事务查到最新的数据;
  • 这个事务不需要对数据进行修改、删除等操作;
  • 也不允许其它事务对数据进行修改、删除等操作;
  • 其它事务也能确保查到最新的数据。

排他锁

相关概念

  • 只有一个事务能获取该数据的「排他锁」
  • 一旦有一个事务获取了该数据的「排他锁」之后,其余事务对于该数据的操作将会被阻塞,直至锁释放。

使用场景

  • 确保某个事务查到最新的数据;
  • 并且只有该事务能对数据进行修改、删除等操作。

共享/排它锁对于性能的影响

  • 因为排它锁只允许一个事务获取,所以如果是业务繁忙的情况下,一旦有某个业务不能及时的释放锁,则会导致其它事务的锁等待、锁等待超时、死锁等问题;
  • 虽然共享锁可以给多个事务共享,但一旦有多个事务同时拥有共享锁,则所有事务都不能对数据进行 UPDATE DETELE 等操作,也会导致其它事务的锁等待、锁等待超时、死锁等问题;
  • 都会影响数据库的并发能力。

自增锁

  1. 先执行查询1,查出了 id 为 1,2,3 的3条数据;
  2. 事务1新增了一条语句(数据的id = 4),此时未提交;
  3. 事务2新增了一条语句(数据的id = 5),并已经提交;
  4. 执行了查询2,此时查出了 id 为 1,2,3,5 的4条数据;
  5. 事务1提交;
  6. 执行了查询3,此时查出了 id 为 1,2,3,4,5 的5条数据;

从这里就有一个问题,为什么第二个查询,查询不到 id = 4 的数据呢?在解决这个问题之前,我们首先要了解,为什么主键要使用自增?

为什么主键通常是自增的?

  • 因为B+树索引的关键字都是有序的
  • 所以我们在主键上设置自增属性,可以保证每次插入都是插入到最后面,可以有效的减少索引页的分裂和数据的移动。

简单理解就是,事务提交了才会解除自增锁。我还不太懂。。

记录锁、间隙锁、临键锁

https://zhuanlan.zhihu.com/p/48269420

「DB」读取问题、隔离级别和锁

原文:https://www.cnblogs.com/antonzhao/p/12483559.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!