美文网首页IT笔记与心得
mysql锁机制与事务

mysql锁机制与事务

作者: 会跳的八爪鱼 | 来源:发表于2021-02-22 12:22 被阅读0次

概念

事务是一系列操作所构成的执行单元,具有原子性,隔离性等的特点。
锁是为了防止多线程读写操作的并发问题而引入的解决方案。

  • 锁主要分为乐观锁和悲观锁,乐观锁认为不需要加锁,当多线程共同写操作时,引入version版本号机制。当读取的版本号与写入时的版本号不一致,则认为该数据已经被修改,写操作失败。悲观锁认为任何时候都需要加锁,所以多线程操作时,只有一个线程释放锁后,其他线程才能执行获取锁或者访问(需要区别读锁和写锁)。数据库的锁基本都是悲观锁。当然我们也可以使用乐观锁解决并发问题https://www.cnblogs.com/laoyeye/p/8097684.html
  1. 锁的分类
  • 读锁和写锁
    • 读锁也叫共享锁(s锁),当一个事务(或者线程)对某一个对象加读锁时,其他事务可以再加读锁,但是不能加写锁
      select ... lock in share mode;
    • 写锁也叫排他锁(x锁),当一个事务(或者线程)对某一个对象加写锁时,其他事务不能再加读锁或者写锁。
      select ... for update 或者update,delete等
      note:select不加任何锁,所以select查询任何时候都不会被阻塞。
  • 按照加锁的范围分为行锁和表锁
    行锁和表锁是指加锁的范围,读写锁是指加锁后其他事务能够加锁或者访问。
    • 表锁:锁住整张表,两个事务不能同时对一张表做更新操作,这样会降低并发性,但是不会出现死锁,也是大多数数据库引擎支持的类型。
    • 行锁是表中的一行或者多行加锁,这是Innodb的一个特征,行锁是根据索引加锁,所以如果查询没有使用索引,则会退化为表锁。
  • 如果使用了相同的索引值,即使是不同行也会冲突,造成不能加锁或访问。
  • 事务使用表中不同的索引时不会发生冲突。
  • 行锁的分类(记录锁,间隙锁,临间锁(记录锁+间隙锁))
    • 记录锁:锁住某几行记录
    • 间隙锁:为了解决可重复读中的幻读问题,所以只有可重复读和串行化中存在间隙锁。
  1. 事务
  • 事务的种类:读未提交,读已提交,可重复读,串行化
  • 读未提交,一个事务读取了另一个事务未提交的更新,会导致出现脏读。事务a进行更新时,事务b使用select(任何时候都可以读)查询到了修改的记录,但事务a并未提交,导致事务b读取到了脏数据。
  • 读已提交:读取一个事务已提交的更新,可以解决脏读。使用mvcc机制实现:

mvcc(多版本并发控制):数据库会生成ReadView(当前活跃的事务id)和版本链(版本链中的每个记录都会有一个事务id(trx_id)和指向上一次修改的指针roll_pointer),事务读取记录时,如果发现事务a的id小于要查询记录的版本链中中的事务id,说明这个版本记录中的事务已经提交了,可以使用;如果发现查询记录中版本链中的事务id在ReadView中,则说明该事务还未提交,则不能使用,然后查找roll_pointer指向的下一条记录,然后比较事务id是否在ReadView中。
note:读已提交和可重复读都使用了mvcc但是使用读已提交时,每次select都会生成新的ReadView,所以第二次select可以查到与第一次不同的数据。但是可重复读为了不解决一个食物中不可重复读的问题,不生成新的ReadView,这样一个事务中两次select的是同样的数据。


mvcc中记录的版本链示意图
  • 可重复读(innodb的默认隔离级别):可重复读解决了在同一个事务中多次读取数据不一致的情况。实现方式分为select实现和非select实现。
    • select实现(快照读):select不加锁,为了让select实现可重复读,RR将RC(读已提交的)的mvcc拿过来,但是同一事务中每次select都使用同一个ReadView所以,读取的是历史数据,所以此时select也被叫做快照读。
    • 非select实现(当前读):RR中除了select之外的都会更新ReadView,所以也叫当前读。但是会出现不可重复读和幻读的问题(详见下),所以非select方式(当前读)使用临间锁(记录锁+间隙锁)(详见下)实现。即通过锁不让其他事务在指定范围内更新数据。既保证了数据新鲜又能可重复读。
    • 不可重复读:在当前读时如果只使用记录锁,则再次查询时会出现新插入的记录。例如:数据表中有三条记录(id=1,2,3),事务a查询id小于10的记录,总共三条,但是锁住的只是id为123的记录,事务b插入新的记录不阻塞,则事务a再次查询时会出现四条记录。
    • 幻读:数据表中没有id为2的记录,事务a查询后insert一条id为2的记录,但是事务b也insert一条id为2的记录,这时由于查询时没有锁住id为2的行,所以事务a会插入失败,提示id冲突,即见鬼了。
    • 间隙锁:对索引之间的范围加锁,使得其他事务不能在该范围内更新
  • 当索引是主键索引和唯一索引时精确匹配时,只锁住该行(=或者in),当查询值不存在时会退化为间隙锁
  • 当索引是普通索引时,通过精确匹配会锁住满足检索条件的范围(=后者in)例如,索引是2,5,11,23,45,78,当查询in(5, 45)时会锁住[2, 5)和[5, 11),[23, 45)和[45, 78)当插入[11, 23)时不会阻塞。如果查询值为10,则锁住[5, 11)
  • 范围查找时会锁住指定范围,例如id>10 and id<30将锁住,如果10,30不是索引,索引值为4, 15, 17, 27, 35, 56将锁住[4, 35)
  • 串行化:会将所有的select语句加上共享锁lock in share mode,这将导致读写不能并发,效率低。

参照:MySQL的锁机制和加锁原理
mvcc机制
Innodb锁机制:Next-Key Lock 浅谈
面试中的老大难-mysql事务和锁,一次性讲清楚! - 掘金 (juejin.cn)

相关文章

  • mysql锁机制与事务

    概念 事务是一系列操作所构成的执行单元,具有原子性,隔离性等的特点。锁是为了防止多线程读写操作的并发问题而引入的解...

  • mysql事务与锁机制

    什么是事务? 官方点说,事务就是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作作序列构成。 通俗点...

  • MySQL - 解读MySQL事务与锁机制

    文章目录 生猛干货 事务及其特性 一致性原子性隔离性持久性 并发事务控制 单版本控制-锁多版本控制-MVCC 原子...

  • 高性能Mysql笔记

    一、Mysql架构与历史 1、架构图 2、锁 表锁 行级锁 3、事务 死锁 Mysql中的事务 1

  • mysql的事务与锁机制

    1.关系型数据库遵循ACID原则: 1.1 并发事务处理带来的问题 更新丢失(Lost Update) 脏读(Di...

  • MySQL相关(一)——— 事务和锁

    事务的隔离级别和锁机制 【1】InnoDB 事务隔离级别和锁 【2】脏读、不可重复读、幻读 mysql 相关 常用...

  • 收藏-MySQL

    # MySQL的并发控制与加锁分析# MySQL的四种事务隔离级别# mysql共享锁与排他锁

  • 事务、锁与MVCC

    目标与手段 MySQL的事务提供了四种隔离级别,这个是最终的目的,其余所有的锁机制、MVCC机制都是为此服务的。 ...

  • MYSQL锁和事务机制

    mysql基础: mysql的四个特性,原子性、一致性、隔离性、持久性。1.原子性(atomicity):一个事务...

  • MySQL事务&锁机制

    一、事务(transaction) 1、概念事物用于保护多个SQL语句的执行,只要有一个失败则全部失败,反之都成功...

网友评论

    本文标题:mysql锁机制与事务

    本文链接:https://www.haomeiwen.com/subject/ohyhfltx.html