MySQL事务并发问题及隔离级别介绍

目录

    • 前言
    • 事务特性
        • 原子性(Atomicity)
        • 一致性(Consistency)
        • 隔离性(Isolation)
        • 持久性(Durability)
    • 事务并发的三大问题
        • 脏读
        • 不可重复读
        • 幻读
    • 事务隔离级别
        • Read Uncommitted (RU 未提交读)
        • Read Committed (RC 已提交读)
        • Repeatable Read (RR 可重复读)
        • Serializable (串行化)
    • MVCC
        • DATA_TRX_ID
        • DATA_ROLL_PTR
        • DB_ROW_ID

前言

本文主要介绍MySQL innodb存储引擎的事务并发问题及事务级别

事务特性

事务需要满足4大特性,即所谓的ACID

原子性(Atomicity)

原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚

一致性(Consistency)

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。注意:事务的一致性一般是由业务来控制的

隔离性(Isolation)

隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

持久性(Durability)

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

事务并发的三大问题

脏读

一个事务读取到了其他事务还未提交的数据,造成读不一致。这是我们绝对不能容忍的,即事务还没提交,即有可能被回滚,但是数据可以被其他事务读取到
MySQL事务并发问题及隔离级别介绍_第1张图片

不可重复读

一个事务读取到了其他事务已提交的数据造成读读不一致(其他数据修改或者删除导致读不一致)
MySQL事务并发问题及隔离级别介绍_第2张图片

幻读

一个事务读取到了其他事务插入的数据造成读不一致(其他数据插入导致读不一致)
MySQL事务并发问题及隔离级别介绍_第3张图片
基于事务并发存在的三大问题,那么我们的数据库必须要帮我们解决这些问题,所以就出现了标准,即希望数据库厂商可以实现该标准

事务隔离级别

SQL92 ANSI/ISO标准,在该标准定义了四大隔离级别应该解决的问题,并且希望数据库厂商可以实现该标准
http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

Read Uncommitted (RU 未提交读)

最低级别,未解决任何并发问题

Read Committed (RC 已提交读)

解决脏读问题

Repeatable Read (RR 可重复读)

解决脏读问题、解决不可重复读问题

Serializable (串行化)

解决脏读问题、解决不可重复读问题、解决幻读问题

那么MySQL中是否有实现这些标准呢,可以看下图

MySQL事务并发问题及隔离级别介绍_第4张图片
我们可以看到MySQL在InnoDB的存储引擎下,在可重复读(RR)级别就已经帮我们解决了并发读不一致的三大问题了

所以MySQL目前默认的事务隔离级别就是Repeatable Read,我们可以执行SELECT @@tx_isolation来进行查询

MVCC

以上事务隔离级别是为了解决事务读一致性的问题的,那么MySQL是如何解决这些问题的呢,主要是采用的MVCC的思想来解决

MVCC (Multiversion Concurrency Control) 中文全程叫多版本并发控制,是现代数据库(包括 MySQL、Oracle、PostgreSQL 等)引擎实现中常用的处理读写冲突的手段,目的在于提高数据库高并发场景下的吞吐性能。

InnoDB 中 MVCC 的实现方式为:每一行记录都有两个隐藏列:DATA_TRX_ID、DATA_ROLL_PTR(如果没有主键,则还会多一个隐藏的主键列)。

DATA_TRX_ID

记录最近更新这条行记录的事务 ID,大小为 6 个字节

DATA_ROLL_PTR

表示指向该行回滚段(rollback segment)的指针,大小为 7 个字节,InnoDB 便是通过这个指针找到之前版本的数据。该行记录上所有旧版本,在 undo 中都通过链表的形式组织。

DB_ROW_ID

行标识(隐藏单调自增 ID),大小为 6 字节,如果表没有主键,InnoDB 会自动生成一个隐藏主键,因此会出现这个列。另外,每条记录的头信息(record header)里都有一个专门的 bit(deleted_flag)来表示当前记录是否已经被删除。

MVCC即是根据DATA_TRX_ID和DATA_ROLL_PTR根据规则来实现的,这里不做详细介绍。

你可能感兴趣的:(数据库,mysql,事务隔离级别,事务并发问题,mvcc)