博客
关于我
MySQL事务详解结合MVCC机制的理解
阅读量:790 次
发布时间:2023-02-11

本文共 2292 字,大约阅读时间需要 7 分钟。

MySQL事务的隔离级别

SQL标准定义了四个隔离级别:

  • READ-UNCOMMITTED(读取未提交):最低的事务隔离级别,允许读取尚未提交的数据变更,可能导致脏读,幻读,不可重复读。
  • READ-COMMITTED(读取已提交):可以阻止脏读,但不可重复度,幻读仍然可能发生。
  • REPEATABLE-READ(可重复读):同一事务中,多次一样的查询结果相同,除非数据是被本身事务修改,可以阻止脏读和不可重复读,幻读仍然可能发生。
  • SERIALIZABLE:保证事务的行为像对一系列并发操作进行串行执行,完全避免幻读、脏读等现象。

脏读 ——读未提交(read-uncommitted)

脏读,也叫读未提交。它允许在一个事务中,一个连接修改数据后,另一个连接在同一事务中读取修改后的数据,即使这个修改尚未提交。这通常会导致数据不一致的问题,例如第一个连接可能读到第二个连接修改的未提交数据,而第二个连接后来回滚了。

避免脏读 —— 读已提交(read committed)

在读已提交的隔离级别下,任何读操作都只能读到已经提交的事务数据。因此,如果一个连接修改数据后没有提交,另一个连接在读取时不会看到该修改,直到修改被提交。而如果是可重复读或串行化的隔离级别,则需要额外的机制来确保读到的数据一致性。

不可重复读(reapeatable-read)

不可重复读的定义是,在一个事务范围内,两个或多个相同的查询却返回了不同的结果。这种现象通常是由于事务的并发读写导致的。例如,在可重复读隔离级别下,一个事务可能修改数据,而另一个事务在读取时看到修改后的数据,但由于事务的提交和回滚机制,结果可能不一致。

可重复读

可重复读的核心思想是,在一个事务中,多次读取相同的数据,结果应该是一致的,除非数据是由当前事务本身修改过的。在可重复读隔离级别下,数据库会记录当前事务的版本信息,以避免读到未提交的数据,从而保证数据一致性。

幻读

幻读(phantom read)是指在一个事务中,两次执行相同的查询,结果却不同。这种现象主要发生在支持多版本并发控制(MVCC)的数据库系统中。当一个事务读取数据时,可能会读到由其他事务修改的未提交版本,而这些修改在读取时尚未被提交,从而导致结果不一致。

怎么解决幻读? (serializable)

解决幻读的方式有以下几种:

  • 将事务的隔离级别调整为 SERIALIZABLE:在串行化隔离级别下,数据库会对每个事务的操作加锁,确保事务的操作顺序不被打乱,从而避免幻读现象。
  • 在可重复读的事务级别下,给事务操作的这张表添加表锁:通过加锁机制,防止其他事务在同一时间读取或修改数据,从而避免结果不一致。
  • 在可重复读的事务级别下,给事务操作的这行表添加Next-key Lock(Record Lock+Gap Lock):这种机制通过在数据行和间隙处加锁,确保读者和修改者之间不会出现竞争,从而避免幻读现象。
  • 深入理解MVCC机制

    在MySQL事务中,要么全部执行,要么全部回滚。事务的核心是基于两个文件 redo logundo log

    redo log

    redo log 是数据库的一部分,记录物理数据变化的日志。它保证了数据的持久性,因为每次修改操作都会写入到redo log中。redo log 一部分存在内存中,一部分存在磁盘文件中,和主流的日志框架一样,日志优先存入内存,再异步持久化到磁盘。

    undo log

    undo log 是回滚日志,记录数据的逻辑变化。它有两个主要作用:提供回滚操作和多个行版本控制(MVCC:Muti-Version-Concurrency-Control)。当一个事务回滚时,系统会利用undo log来恢复数据到修改前的状态。

    多行版本控制(MVCC)

    MVCC通过版本链的机制实现行版本控制。在每个数据行中,除了存储实际数据之外,还存储了一个逻辑链表。这个链表包含了数据行的所有版本信息,包括修改的事务ID和上一个版本的指针。每次修改操作都会生成一个新的版本,并将旧版本信息记录到undo log中。

    版本链的组成

    版本链的每个节点包含以下信息:

    • trx_id:表示最新修改该行数据的事务ID。每个事务ID是唯一的,且按顺序递增。
    • roll_pointer:指向上一个版本的地址,可以通过它找到该记录修改前的信息。

    读Review

    MVCC仅在读已提交和可重复读两个隔离级别下工作。在这两种隔离级别下,数据库在执行普通的SELECT操作时,会生成一个ReadReview。ReadReview的作用是检查当前事务的版本信息,以确定哪些版本的数据是可见的。

    ReadReview的核心思想是通过检查trx_ids列表,存储当前活跃的读写事务ID,来判断哪些版本的数据是当前事务可以读取的。这样可以确保在多个事务并发读写的情况下,数据库能够正确地读取最新的数据版本。

    快照读与当前读的区别

    1. 快照读(普通读):普通读是指没有加锁的读操作。它利用MVCC机制,结合ReadReview,来确保读到的数据是最新的。普通读不会对记录加锁,因此可以支持多个并发读操作。

    2. 当前读:当前读需要加锁,确保在读取数据时,其他事务无法修改相同的数据行。当前读会读取到最新的数据版本,并在读取时加锁,防止其他事务的修改操作干扰。

    例如,在执行以下SQL语句时,会触发当前读:

    SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODEUPDATE,DELETE,INSERT

    转载地址:http://yabfk.baihongyu.com/

    你可能感兴趣的文章
    MongoDB出现Error parsing command line: unrecognised option ‘--fork‘ 的解决方法
    查看>>
    MongoDB学习笔记(8)--索引及优化索引
    查看>>
    ms sql server 2008 sp2更新异常
    查看>>
    MS UC 2013-0-Prepare Tool
    查看>>
    msbuild发布web应用程序
    查看>>
    MSCRM调用外部JS文件
    查看>>
    MSEdgeDriver (Chromium) 不适用于版本 >= 79.0.313 (Canary)
    查看>>
    msf
    查看>>
    MSSQL数据库查询优化(一)
    查看>>
    MSSQL日期格式转换函数(使用CONVERT)
    查看>>
    MSTP多生成树协议(第二课)
    查看>>
    MSTP是什么?有哪些专有名词?
    查看>>
    Mstsc 远程桌面链接 And 网络映射
    查看>>
    Myeclipse常用快捷键
    查看>>
    MyEclipse用(JDBC)连接SQL出现的问题~
    查看>>
    myeclipse的新建severlet不见解决方法
    查看>>
    MyEclipse设置当前行背景颜色、选中单词前景色、背景色
    查看>>
    MyEclipse配置SVN
    查看>>
    MTCNN 人脸检测
    查看>>
    MyEcplise中SpringBoot怎样定制启动banner?
    查看>>