likes
comments
collection
share

MySQL并发知识(面试高频)

作者站长头像
站长
· 阅读数 2

mysql并发事务解决

不同隔离级别下,mysql解决并发事务的方式不同。主要由锁机制和MVCC(多版本并发控制)机制来解决并发事务问题。

1. mysql中的锁有哪些?

  1. 表级锁

    • 场景:表级锁适用于需要对整个表进行操作的情况,例如在执行DDL语句(如ALTER TABLE)时需要锁定整个表
    • 隔离级别中的使用:表级锁通常在所有隔离级别下都会使用,因为它们可以在需要时锁定整个表,从而防止并发修改。
  2. 行级锁

    • 共享锁(Shared Lock)解决了并发事务 读-读 读-写 问题

      • 场景:共享锁允许多个事务同时读取同一行数据,适用于读取操作。例如,当一个事务读取数据时,可以使用共享锁防止其他事务对数据进行写操作
      • 隔离级别中的使用:共享锁在“读已提交”(Read Committed)及以上的隔离级别使用,以防止其他事务对数据进行不一致的修改。
    • 排他锁(Exclusive Lock)解决了并发事务 写-写 问题

      • 场景:排他锁用于对数据进行写操作,确保在同一时间只有一个事务可以对数据进行修改
      • 隔离级别中的使用:排他锁在所有隔离级别下都会使用,因为它们确保数据在被修改时不会被其他事务修改
  3. 间隙锁(Gap Lock)

    • 场景:间隙锁用于防止并发事务在范围查询中插入新数据,确保数据一致性。
    • 隔离级别中的使用间隙锁主要在“可重复读”(Repeatable Read)隔离级别下使用,以防止其他事务在查询范围内插入新数据,导致幻读问题。
  4. Next-Key Lock

    • 场景:Next-Key Lock可以看作是间隙锁的一个增强版本,结合了行锁和间隙锁的特性,用于防止并发事务在范围查询中插入新数据或修改已有数据,同时也防止幻读问题。
    • 隔离级别中的使用Next-Key Lock也是在“可重复读”(Repeatable Read)隔离级别下使用,与间隙锁一起,用于防止幻读问题的发生

在MySQL中,根据隔离级别的不同,使用的锁也会有所不同,以确保在不同的并发情况下保证数据的一致性和隔离性。

2. MVCC原理

MVCC概念

MySQL中的InnoDB存储引擎利用MVCC(多版本并发控制)来优化并发性能,并确保事务间的隔离性。解决了并发事务 写-读 问题。MVCC允许不同的事务在同一时刻看到数据库的不同版本状态,以此来减少锁定需求,尤其对于读密集型应用而言,可以显著提升并发读取性能。

MVCC核心组件

  1. 隐藏字段

    • 每一行记录除了我们通常定义的列之外,还包含一些隐藏的系统字段:

      • DB_TRX_ID(事务ID): 记录最后一次修改该行记录的事务ID
      • DB_ROLL_PTR(回滚指针): 指向对应的undo日志记录,用于获取该行的前一个版本。
      • DB_ROW_ID(行ID): 在某些情况下作为聚簇索引的补充,用于非唯一二级索引定位记录。
  2. Undo Log (回滚日志)

    • 当事务对数据进行修改时,InnoDB会产生 undo log 记录原来的值,形成版本链。
    • 每次更新操作都会生成一个新的版本,并将旧版本链接到undo log中。
    • Undo日志不仅用于事务回滚,也用于MVCC提供历史版本数据给读事务。
  3. Read View (一致性读视图)

    • 在开启事务时,InnoDB会创建一个Read View用来确定事务执行过程中哪些版本的数据对它是可见的。

    • Read View包含了以下关键信息:

      • m_ids: 当前系统中活跃事务的最小和最大事务ID。
      • active_trx_list: 活跃事务列表,这些事务可能修改了数据但还未提交。
      • 创建Read View时系统全局事务ID计数器的值。

MVCC的工作原理

MVCCC是“维持一个数据的多个版本,使读写操作没有冲突”的一个抽象概念。 这个概念需要具体功能去实现,这个具体实现就是快照读

  • 快照读:在可重复读(Repeatable Read)隔离级别下,普通的SELECT语句不会加锁而是采用一致性读(快照读),根据当前事务的Read View来读取创建视图时刻之前已经提交的数据版本。

    • 根据以下规则判断某行记录对于当前事务是否可见:

      • 如果DB_TRX_ID小于Read View的最低事务ID(min trx id),表示该行在Read View创建前就已经提交,因此是可见的。
      • 如果DB_TRX_ID大于或等于Read View的最低事务ID,但不在活跃事务列表中,同样视为已提交且可见。
      • 若DB_TRX_ID大于或等于Read View的最低事务ID且在活跃事务列表中,说明是未提交事务更改的数据,不可见。InnoDB会查询undo log中的历史版本数据,直到找到最接近的已提交数据版本,将其提供给当前事务使用。
      • 若DB_TRX_ID等于当前事务的事务ID,表示是当前事务自己修改的数据,也是可见的。
  • 事务结束时的清理

    • 当事务提交时,其修改过的记录的旧版本可以在适当的时机被purge线程清除,以回收存储空间。
    • 已经不再被任何事务使用的旧版本数据会被从undo日志中移除。

通过上述机制,MVCC能够在很大程度上降低事务之间的互斥,提高并发性能,同时保证事务的ACID特性(原子性、一致性、隔离性和持久性)。在实际应用中,尤其是在高并发的OLTP系统中,MVCC是保证数据库高性能并发处理的重要手段

MVCC机制生效条件

MVCC机制只在读已提交和可重复读隔离级别下才会生效。

  • 读已提交(READ COMMITTED) : 在这个隔离级别下,每次SELECT语句执行时,都会获取最新的已提交数据,这意味着每次查询都可能看到不同的数据版本,因为每次查询都会获取一个最新的快照。然而,与Repeatable Read相比,这里的“快照”并不是事务开始时固定的视图,而是每次查询时动态获取的
  • 可重复读(REPEATABLE READ) : 这是MySQL InnoDB存储引擎的默认事务隔离级别。在这个级别下,同一个事务内的普通SELECT语句确实不会加锁,而是始终读取事务启动时存在的已提交数据版本,也就是说,同一个事务内多次执行相同的SELECT语句结果总是相同的,不会受到其他事务提交的影响

总结来说,所谓的MVCC指的就是在使用READ COMMITTDREPEATABLE READ这两种隔离级别的事务在执行普通的SEELCT操作时访问记录的版本链的过程,这样子可以使不同事务的读-写写-读操作并发执行,从而提升系统性能

转载自:https://juejin.cn/post/7351687181382500362
评论
请登录