Mysql原理与调优-事务与MVCC

目录

1.事务

[1.1 什么是事务](#1.1 什么是事务)

[1.2 事务隔离级别](#1.2 事务隔离级别)

[1.2.1 事务并发执行可能出现的问题](#1.2.1 事务并发执行可能出现的问题)

[1.2.2 隔离级别](#1.2.2 隔离级别)

[1.2.3 如何查看和设置事务的隔离级别](#1.2.3 如何查看和设置事务的隔离级别)

[1.2.3 快照读和当前读](#1.2.3 快照读和当前读)

2.MVCC

[2.1 版本链机制](#2.1 版本链机制)

[2.2 Read View](#2.2 Read View)

[2.2.1 Read View读取事务的原则](#2.2.1 Read View读取事务的原则)

[2.4 Read Committed级别查询](#2.4 Read Committed级别查询)

[2.5 Repeatable Read级别查询](#2.5 Repeatable Read级别查询)

[2.6 MVCC是否能解决幻读问题](#2.6 MVCC是否能解决幻读问题)


1.事务

1.1 什么是事务

事务其实就是对Mysql的一系列操作,它要求满足4个性质,分别是A(原子性)、C(一致性)、I(隔离性)、D(持久性)。接下来我们来分别介绍一下这4个性质的含义。

  • 原子性

原子性,表示对于事务里面的操作是一个整体,要么同时成功,要么同时失败。比如A给B转账,A减少50,B加50,这一操作是一个整体。由redo log和undo log共同保证。

  • 持久性

持久性,表示的事务一旦提交,便会持久化到磁盘中。这一操作由redo log保证。

  • 隔离性

隔离性,表示不同的事务之间是不相互影响的。快照读和写操作的隔离性由MVCC保证,当前读和的写操作,写操作和写操作的隔离性由Mysql的锁机制保证。

  • 一致性

一致性,一致性分为数据一致性和约束一致性。我的立即其实就是符合客观事实,比如A给B转账,A减少50,B加50,但是总的金额是未改变的,这是否符合客观事实的。只有满足原子性、持久、隔离性才能保证一致性。

1.2 事务隔离级别

1.2.1 事务并发执行可能出现的问题

假设的现在有两个事务,事务A和事务B并发操作。

  • 脏写

脏写,事务A更改了事务B的还未提交的数据。

  • 脏读

脏读,事务A读取到事务B还未提交的数据。

  • 不可重复读

不可重复读,在同一个事务A里面,同时读取某行数据,前后值不一样。原因是,在此过程中,事务B对该行数据进行修改,并且提交。

  • 幻读

幻读,在同一个事务A里面,同时读取某个范围的数据,前后行数不一样。原因是,在此过程中,事务B插入了记录,并且提交。

1.2.2 隔离级别

Mysql的隔离级别,分为4个,读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED),可重复读(REPEATABLE READ)、串行化(SERIALIZABLE)。

注意:对于Mysql而言,RR级别,也可以解决,快照读的幻读问题。

1.2.3 如何查看和设置事务的隔离级别

sql 复制代码
 SHOW VARIABLES LIKE 'transaction_isolation'; //查看事务隔离级别
 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; //设置事务个几把
 SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;//设置当前会话的事务隔离级别

1.2.3 快照读和当前读

前面说过,事务的隔离性,主要是通过,MVCC和加锁来保证的。那什么时候是采用MVCC机制,设么时候采用加锁呢?就需要了解快照度和当前读的概念。

**当前读:**要求读取到的一定是当前数据库里面最新的内容,如果结合CAP理论来看,其实就是保证一致性。在Mysql里面,通过select * from table lock in share mode 或者 select * from table for update这两种查询为当前读。

**快照读:**读取的是读请求时的快照数据,在读操作者一过程中,其他事务可能对改数据进行修改,所以读取到的可能是老数据,如果结合CAP理论来看,其实就是保证可用性。在Mysql里面,通过普通的select就是快照读。

快照读在mysql中的对于隔离级别的处理,其实是相当于DML操作的。所以快照读和DML操作采用MVCC来保证隔离性。当前读和DML采用加锁来保证隔离性。

2.MVCC

2.1 版本链机制

前面讲Mysql行记录的时候,曾经说过,每条记录的会有三个隐藏列,分别是row_id,tx_id,roll_pointer。每次更新,都会在undo log里面放一条旧的数据,通过roll_pointer连接成一个版本链。其中tx_id是一个递增的。

2.2 Read View

MVCC主要是保证快照读和DML语句的隔离性。它每次读取主要读取到的其实是发送select命令时的快照。所以MVCC在每次读取的时候,会生成一个Read View,里面主要包含3个部分:

|----------------|--------------|
| 字段 | 说明 |
| m_ids | 所有活跃的事务id |
| min_trx_id | 活跃的事务最小id |
| max_trx_id | 活跃的事务最大id加1 |
| creator_trx_id | 创建的当前快照的事务id |

2.2.1 Read View读取事务的原则

假设当前需要被读取事务的tx_id为data_tx_id。

1.如果data_tx_id小于Read view的活跃事务最小id,表示修改这条记录的事务已经提交,可以读取。

2.如果data_tx_id等于Read view的creator_trx_id,表示这条数据是生成Read View的事务创建的,能够读取,所以在同一个事务里面,后面的select能够读取到该事务前面创建的数据。

3.如果data_tx_id大于等于活跃的事务最大id加1,表示在创建这个Read View的时候,该事务还未到达,所以不能提交。

4.如果data_tx_id在该Read View的m_ids里面,便表示生产该Read View的时候,修改data的事务还未提交,不能被访问。

综上,通过Read View机制,每个事务只能读取到当前事务修改的数据或者在当前select请求到达前并且事务已经提交的修改的数据。

2.4 Read Committed级别查询

原则:Read Committed每次查询都会生成一个Read View。因为,通过Read View每个事务只能读取到当前事务修改的数据或者在当前select请求到达前并且事务已经提交的修改的数据。所以的Read View一定读取到的是已经提交过后的事务,满足读已提交。

但是,因为在这个隔离级别下,每次读取会生成一个Read View,比如上面这个例子。

1.事务A在第一次select的时候,此时事务B还为提交,所以当前活跃事务id为[8,9],所以select到的内容为A。

2.在中间事务B更新数据为B并且提交。

3.事务A再次select,会为此生成一个新的Read View,里面m_ids为[8],表示只有A事务还在活跃,此时就能读取的内容为B。

可以看出,这种情况下,读取到的永远是已经提交的事务修改的数据,但是可能会出现不可重复读的问题。

2.5 Repeatable Read级别查询

原则:Read Committed只有在第一次查询的时候会生产一个Read View,后面都会共用这个Read View。所以在查询过程中,不管中途是否有其他事务修改数据并且修改,只要事务id比生产Read View的事务id大,便不能读取。

对于上面这个例子:

1.事务A在第一次select的时候,此时事务B还为提交,所以当前活跃事务id为[8,9],所以select到的内容为A。

2.在中间事务B更新数据为B并且提交。

3.事务A再次select,Read View不变,里面m_ids为[8,9],此时就能读取的内容为A。

可以看出,在这种情况下,只会共用一次Read View。所以在Repeatable Read级别下,只能读取事务id小于等于生成Read View的事务id的事务修改或者插入的数据。能够解决不可重复读问题。

2.6 MVCC是否能解决幻读问题

在Repeatable Read情况下,MVCC在多次查询,会共用一个Read View,所以在此情况下,MVCC只能读取到事务id等于生成Read View的事务id的事务修改或者插入的数据。由此可以看出,MVCC也能解决幻读问题,但是有种特殊情况。

可以看出,在事务A读取的过程中,事务B插入一条数据后提交,事务A刚好去更新了这条数据,会更改修改该条数据的事务id为事务A的id,所以事务A再次读取能够读取到该数据,会出现幻读问题。这种情况,可以通过后面的加锁来解决。

相关推荐
Python私教3 分钟前
Python国产新 ORM 框架 fastzdp_sqlmodel 快速入门教程
java·数据库·python
孟章豪5 分钟前
SQL Server全方位指南:从入门到高级详解
数据库
数分大拿的Statham6 分钟前
PostgreSQL中的regexp_split_to_table函数详解,拆分字段为多行
大数据·数据库·postgresql·数据分析·数据清洗
mqiqe6 分钟前
PostgreSQL主备环境配置
数据库·postgresql
mqiqe9 分钟前
PostgreSQL 容器安装
数据库·postgresql
计算机学姐24 分钟前
基于PHP的电脑线上销售系统
开发语言·vscode·后端·mysql·编辑器·php·phpstorm
小光学长39 分钟前
基于vue框架的宠物寻回小程序8g7el(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
数据库
一叶飘零_sweeeet40 分钟前
深入理解 MySQL MVCC:多版本并发控制的核心机制
数据库·mysql
中文很快乐1 小时前
springboot结合p6spy进行SQL监控
java·数据库·sql
小电玩1 小时前
谈谈你对Spring的理解
java·数据库·spring