当前位置: 首页> 教育> 锐评 > 十堰市疫情防控指挥部最新公告_酷站欣赏_seo搜索引擎_保定seo外包服务商

十堰市疫情防控指挥部最新公告_酷站欣赏_seo搜索引擎_保定seo外包服务商

时间:2025/7/11 18:08:56来源:https://blog.csdn.net/weixin_66672501/article/details/142955912 浏览次数:0次
十堰市疫情防控指挥部最新公告_酷站欣赏_seo搜索引擎_保定seo外包服务商

目录

  • 前言
  • 1. 什么是事务
    • 1.1 四个特性
  • 2. 为什么要有事务
    • 2.1 支持事务的存储引擎
  • 3. 事务的提交
  • 4. 事务的常见操作方式
    • 4.1 准备工作
    • 4.2 基本操作
  • 5. 事务的隔离级别
    • 5.1 如何理解隔离性
    • 5.2 隔离级别
    • 5.3 查看与设置隔离级别
    • 5.4 再谈一致性
  • 6. 隔离性是怎么做到的
    • 6.1 MVCC
    • 6.2 read view
    • 6.3 RR-RC的区别

前言

mysql是一个网络服务,这意味着在同一时刻可能有多个用户在并发访问或者操作这个数据库中的某些数据,如果不对这些操作进行控制的话有可能会造成并发访问导致数据不一致的问题,进而导致错误发生,因此针对这种并发访问的情况,数据库要通过事务等制来保证操作的正确性

1. 什么是事务

事务说白了它是一由一条或者多条有关联的sql语句组成,这些sql语句共同完成了一个实际的功能或者业务逻辑,因此事务是站在用户层上来看待sql语句的一个方式,它将多个sql操作封装为一个不可分割的整体,从而确保这些操作要么全部成功,要么在遇到错误时全部回滚到事务开始前的状态,就好像错误重来没产生过一样

操作数据库的基本单位就是事务

正如上面所说,一个MySQL 数据库,可不止一个事务在运行,同一时刻,甚至有大量的请求被包装成事务,在向MySQL 服务器发起事务处理请求。而每条事务至少一条SQL ,最多很多SQL ,这样如果大家都访问同样的表数据,在不加保护的情况,就绝对会出现问题。甚至,因为事务由多条SQL 构成,那么,也会存在执行到一半出错或者不想再执行的情况,那么已经执行的怎么办呢?

1.1 四个特性

具体来说一个完整的事务并不是一个简单的sql语句集合,只有满足如下四个性质,才可保证操作的正确性:

原子性(Atomicity):
原子性是指事务在执行过程中,要么全部成功,要么在遇到错误时回滚到事务开始前的状态,确保数据不会处于中间状态

一致性(Consistency):
一致性是指数据库从一个一致性状态转换到另一个一致性状态,这个状态是可以预期的,也就是说事务执行前后,只要数据库遵守所有的完整性约束(如主键约束、外键约束、唯一性约束等),状态就是可预期的,也就是一致的

隔离性(Isolation):
隔离性是指事务之间的操作是互不干扰的。即使多个事务并发执行,每个事务都像在单独的环境中运行一样,不会受到其他事务的影响。不同的隔离级别(如未提交读、提交读、可重复读和序列化)提供了不同程度的事务隔离

持久性(Durability):
持久性是指一旦事务提交,它对数据库的改变就是永久性的,即使系统崩溃也不会丢失。这通常通过将数据写入持久存储(如磁盘)来实现

上面四个属性,可以简称为ACID

2. 为什么要有事务

说浅显一点是多用户并发访问数据库会导致数据一致等问题,进而影响数据完整性,这种说法是站在底层开发者视角

实际上事务应该从是上层使用者的角度来理解,它的存在就是为了方便让用户去操作数据库,在编码方面也可以简化编程模型,不需要让用户再去考虑各种各样的潜在错误和并发问题,这些是事务要管的事情,所以这才是对为什么要有事务的正确理解

可以想一下当使用事务时,要么提交,要么回滚,不会再去考虑网络异常了,服务器宕机了,同时更改一个数据怎么办对吧?因此事务本质上是为了应用层服务的,而且事务不是伴随着数据库系统天生就有的,而是在使用的过程中发现需要有这么个东西后才被设计出来

2.1 支持事务的存储引擎

查看存储引擎是否支持事务:

mysql> show engines \G;
*************************** 1. row ***************************Engine: ARCHIVESupport: YESComment: Archive storage engine
Transactions: NOXA: NOSavepoints: NO
*************************** 2. row ***************************Engine: BLACKHOLESupport: YESComment: /dev/null storage engine (anything you write to it disappears)
Transactions: NOXA: NOSavepoints: NO
*************************** 3. row ***************************Engine: MRG_MYISAMSupport: YESComment: Collection of identical MyISAM tables
Transactions: NOXA: NOSavepoints: NO
*************************** 4. row ***************************Engine: FEDERATEDSupport: NOComment: Federated MySQL storage engine
Transactions: NULLXA: NULLSavepoints: NULL
*************************** 5. row ***************************Engine: MyISAMSupport: YESComment: MyISAM storage engine
Transactions: NOXA: NOSavepoints: NO
*************************** 6. row ***************************Engine: PERFORMANCE_SCHEMASupport: YESComment: Performance Schema
Transactions: NOXA: NOSavepoints: NO
*************************** 7. row ***************************Engine: InnoDBSupport: DEFAULTComment: Supports transactions, row-level locking, and foreign keys
Transactions: YESXA: YESSavepoints: YES
*************************** 8. row ***************************Engine: MEMORYSupport: YESComment: Hash based, stored in memory, useful for temporary tables
Transactions: NOXA: NOSavepoints: NO
*************************** 9. row ***************************Engine: CSVSupport: YESComment: CSV storage engine
Transactions: NOXA: NOSavepoints: NO
9 rows in set (0.00 sec)

目前只有默认的InnoDB引擎支持事务

3. 事务的提交

提交方式分为两种:

  1. 自动提交
  2. 手动提交

查看提交方式:

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.02 sec)

on表示当前是自动提交,可以修改为手动:

mysql> set autocommit=0; #SET AUTOCOMMIT=0 禁止自动提交
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set (0.00 sec)mysql> set autocommit=0; #SET AUTOCOMMIT=1 开启自动提交

4. 事务的常见操作方式

4.1 准备工作

为了更好的验证多个客户端并发访问时所带来的影响,需要先把mysql的事务隔离级别调整到最低,这样方便观察现象:

# 将默认隔离级别设置为读未提交
mysql> set global transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.01 sec)
# 重启客户端才能生效、
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-UNCOMMITTED        |
+-------------------------+
1 row in set (0.00 sec)

创建测试表:

create table if not exists account(id int primary key,name varchar(50) not null default '',blance decimal(10,2) not null default 0.0
);

4.2 基本操作

事务的启动、回滚和提交:

-- 开始一个事务begin也可以,推荐begin
mysql> start transaction; 
Query OK, 0 rows affected (0.00 sec)-- 创建一个保存点save1
mysql> savepoint save1; 
Query OK, 0 rows affected (0.00 sec)-- 插入一条记录
mysql> insert into account values (1, '张三', 100); 
Query OK, 1 row affected (0.05 sec)-- 创建一个保存点save2
mysql> savepoint save2; 
Query OK, 0 rows affected (0.01 sec)-- 在插入一条记录
mysql> insert into account values (2, '李四', 10000); 
Query OK, 1 row affected (0.00 sec)-- 两条记录都在了
mysql> select * from account; 
+----+--------+----------+
| id | name | blance |
+----+--------+----------+
| 1 | 张三 | 100.00 |
| 2 | 李四 | 10000.00 |
+----+--------+----------+
2 rows in set (0.00 sec)-- 回滚到保存点save2
mysql> rollback to save2; 
Query OK, 0 rows affected (0.03 sec)-- 一条记录没有了
mysql> select * from account; 
+----+--------+--------+
| id | name | blance |
+----+--------+--------+
| 1 | 张三 | 100.00 |
+----+--------+--------+
1 row in set (0.00 sec)-- 直接rollback,回滚在最开始
mysql> rollback; 
Query OK, 0 rows affected (0.00 sec)-- 所有刚刚的记录没有了
mysql> select * from account; 
Empty set (0.00 sec)

需要注意的是,一旦commit提交了事务之后,数据会进行持久化保存到数据库中,这时就没办法再进行回滚了

上面的测试的是正常情况,当客户端在事务运行期间退出或者崩溃,mysql也会自动进行回滚

rollback是直接回滚到最开始,即使打了保存点

begin操作会自动更改提交方式,不会受MySQL是否自动提交影响,也就是begin只能commit提交,与系统中是否自动提交没关系

一些结论:

  • 只要输入begin或者start transaction,事务便必须要通过commit提交,才会持久化,与是否设置set autocommit无关
  • 事务可以手动回滚,同时,当操作异常,MySQL会自动回滚
  • 对于InnoDB每一条SQL语句都默认封装成事务然后自动提交,除非将自动提交关闭,这时需要手动commit

事务操作注意事项:

  • 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务还没有提交)
  • 如果一个事务被提交了(commit),则不可以回退(rollback)
  • 可以选择回退到哪个保存点

从上面的例子,能看到事务本身的原子性(回滚),持久性(commit)
那么隔离性?一致性

5. 事务的隔离级别

5.1 如何理解隔离性

首先要明确的是,mysql是一个网络服务器程序,这意味着同时可能会有很多客户端发送请求过来让其进行处理,请求的基本单位是事务,所以肯定会存在大量的事务等待服务器进行处理,这时可能会存在一个事务还在执行过程中,其它事务也在开始了执行,这个时候就大概率会导致并发问题,进而导致数据不一致,因此为了保证事务的执行过程中尽量不会受到其它事务的干扰就有了隔离性的概念

隔离机制只是尽量保证事务的运行不受其它事务的干扰,但实际上根据可以根据干扰程度来给隔离进行分级

5.2 隔离级别

读未提交【Read Uncommitted】: 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的),这是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻读,不可重复读等,上面为了做实验方便,用的就是这个隔离性

读提交【Read Committed】 :该隔离级别是大多数数据库的默认的隔离级别。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别避免了脏读,但会引起不可重复读,即一个事务执行时,如果多次 select, 可能得到不同的结果

可重复读【Repeatable Read】: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题

串行化【Serializable】: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,也就是串行执行,从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,但是可能会导致超时和锁竞争(这种隔离级别太极端,实际生产基本不使用,性能太低了)

并发问题解释:
脏读(Dirty Read):一个事务可以读取另一个事务未提交的数据,这个现象就是脏读,如果另一个事务回滚了,那么当前事务读取的数据就是无效的

不可重复读(Non-repeatable Read):一个事务在读取数据后,另一个事务可以修改这些数据,导致第一个事务再次读取时无法读取到相同的数据,进而可能会影响上层对数据的决策

这其实有问题的,因为事务的执行要求是原子的,所以在一个事务中多次select的结果应该相同

幻读(Phantom Read):在一个事务中select某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现插入失败,此时就发生了幻读,原因在于另一个事务已经插入了这个数据(需要类似主键冲突数据),即使表中实际存在,但第一个事务依旧查询不到,另一个事务可以查询的到

幻读是专门伴随insert这个操作所诞生的问题

隔离级别如何实现:隔离,基本都是通过锁实现的,不同的隔离级别,锁的使用是不同的。常见有,表锁,行锁,读锁,写锁,间隙锁(GAP),Next-Key锁(GAP+行锁)等

上面的隔离级别主要针对的读写并发,也就是一个事务在curd另一个事务在读,如果是读读并发就不存在并发问题了,而如果是写写则必须是串行化执行了,保证数据一致性

5.3 查看与设置隔离级别

查看:

-- 查看全局隔离级别
mysql> SELECT @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| READ-UNCOMMITTED               |
+--------------------------------+
1 row in set (0.00 sec)-- 查看会话(当前)全局隔级别
mysql> SELECT @@session.transaction_isolation;
+---------------------------------+
| @@session.transaction_isolation |
+---------------------------------+
| READ-UNCOMMITTED                |
+---------------------------------+
1 row in set (0.00 sec)-- 默认同上
mysql> SELECT @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-UNCOMMITTED        |
+-------------------------+
1 row in set (0.00 sec)

会话隔离级别默认会根据全局隔离级别进行初始化,如果修改会话隔离级别只会影响当前登陆的会话,如果修改全局隔离级别则会影响每次会话的隔离级别

如果修改了会话的默认隔离级别,需要systemctl restart mysqld恢复

设置:

--设置
-- 设置当前会话 or 全局隔离级别语法
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}--设置当前会话隔离性,另起一个会话,看不多,只影响当前会话
mysql> set session transaction isolation level serializable; -- 串行化
Query OK, 0 rows affected (0.00 sec)mysql> SELECT @@global.transaction_isolation; --全局隔离性还是RR
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set, 1 warning (0.00 sec)mysql> SELECT @@session.transaction_isolation; --会话隔离性成为串行化
+------------------------+
| @@session.tx_isolation |
+------------------------+
| SERIALIZABLE |
+------------------------+
1 row in set, 1 warning (0.00 sec)mysql> SELECT @@transaction_isolation; --同上
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE |
+----------------+
1 row in set, 1 warning (0.00 sec)--设置全局隔离性,另起一个会话,会被影响
mysql> set global transaction isolation level READ UNCOMMITTED;
Query OK, 0 rows affected (0.00 sec)mysql> SELECT @@global.transaction_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-UNCOMMITTED |
+-----------------------+
1 row in set, 1 warning (0.00 sec)mysql> SELECT @@session.transaction_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED |
+------------------------+
1 row in set, 1 warning (0.00 sec)mysql> SELECT @@transaction_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set, 1 warning (0.00 sec)
-- 注意,如果没有现象,关闭mysql客户端,重新连接

5.4 再谈一致性

只要事务执行的结果正确,就会让数据库从一个一致性状态,变到另一个一致性状态

如果系统运行发生崩溃导致某个事务尚未完全完成,而未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态,所有了就有了回滚机制来保证一致性,因此一致性是通过原子性来保证,这是从底层角度理解,其它三个特性也是为了保证一致性来进行的

实际上一致性其实更应该从用户的角度来理解,如果用户非要做一些不合法(业务逻辑层面上的不合法,不是使用层面)的事情那MySQL能怎么办呢,它只负责给用户提供技术支持,如果用户非要做坏事,那它无法完全保证一致,因此一致性也是要靠用户维护

6. 隔离性是怎么做到的

第一个和最后一个隔离性比较好理解,R-U就相当于没有隔离性,修改就能看到,串行化就是串行执行,不存在并发问题了,而对于另外两个隔离性R-C和R-R具体是怎么做到的呢,数据不是只有一份吗,为什么修改了看不到?

这里就得分清楚有哪些并发场景,针对不同场景应该选择哪种隔离性,具体其实就三种并发情况:

  1. 读-读并发:不存在任何并发问题,因此不需要并发控制
  2. 写-写并发:有线程安全问题,但实际上这种场景不多,所以不做重点介绍
  3. 读-写并发:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读,这种并发场景是最常见的,也是后续介绍的重点

6.1 MVCC

解决读写并发所使用到的一个关键技术是MVCC,就是多版本并发控制,它允许在不锁定资源的情况下进行读和写操作,从而提高数据库的并发性能

在学习它之前需要先了解几个相关概念:

  1. 事务ID:虽然事务可以并发执行,但终究是有先后顺序的,也就是谁先到来谁后到来,MVCC会对依次到来的事务分配一个单向增长的事务ID,因此就可以通过ID来判断事务到来的顺序;另外要知道的是,mysql程序内部一定会存在多个事务,所以就得对多个事务进行管理,把事务这个抽象体通过结构体或者类进行描述,然后再通过这些类定义出一个个事务对象,最后用合适的数据结构把这些对象管理起来,因此事务ID肯定是保存在事务对象中的,肯定也包含了保存多条sql语句的字段等等
  2. 三个隐藏列字段:一个表除了会创建用户指定的属性列之外,还包含如下就几个隐藏列:
    DB_TRX_ID,含义是最近修改(或插入)的事务ID,六个字节,作用是用来记录创建这条记录/最后一次修改该记录的事务ID;
    DB_ROLL_PTR,一个回滚指针,七个字节,作用是指向上一个记录的版本,相当于在修改时拷贝一个新记录,让用户去修改这个新记录,然后让这个新记录中回滚指针指向之前的旧记录,方便在出错时回滚,旧数据保存在undo log中
    DB_ROW_ID,一个隐藏的自增ID(隐藏的默认主键),六个字节,如果数据表没有主键, InnoDB会自动以这个列产生一个聚簇索引,如果有主键,则按照用户主键构建索引;
    flag,它用于标记记录是否被删除。这个字段并不是一个单独的列,而是记录头信息中的一个bit位,用来表示当前记录是否已经被删除。当一个事务删除一条记录时,实际上并不是从磁盘上删除它,而是通过设置这个标记位为1来表明记录已被删除,这样,在后续的读中,这些被标记为删除的记录就不会被读操作看到,从而保证了事务的隔离性
  3. undo日志,这里理解成mysql中的一段内存缓冲区,用来保存日志数据的就行
  4. Read View,后面介绍

模拟MVCC:
已更新为例,假设目前有一条记录,这时新来了一个事务,需要对这条记录进行更新,修改之前先加行锁,保证修改的原子性,然后拷贝一个当前记录的副本到undo log那块内存空间中,假设保存这个副本数据的内存地址为0x11,接着就可以修改了,修改后隐藏列的事务ID和回滚指针要发生变化,事务ID会更新成当前的新事务ID,然后回滚指针原本是空,这时要更新成0x11,也就是副本数据的内存地址,这意味着当前版本的上一个版本就是回滚指针所指向的那个版本,最后提交事务解锁

所保存的一个个副本实际可以看做成一张张快照

当有其它事务到来要对其进行修改时,做法是和刚才一样的,所以这条记录中的回滚指针实际保存的是一条链表,一条保存历史修改记录的链表,因此回滚本质是通过当前版本的回滚指针找到上一个旧版本,然后把数据替换成旧版本,不过实际上只有更新操作是覆盖数据,而插入删除操作是有些区别的,插入操作其实是没有历史版本的,但也要保存到undo log中方便回滚,删除有历史版本,但也是类似的道理,它们保存的是相反的操作语句,比如插入,那么回滚就应该是删除,反之亦然,因此它们回滚不是覆盖数据,而是重新执行一遍所保存的相反的sql语句,以上就是MVCC的基本工作原理了

可以理解成update和delete可以形成版本链,insert暂时不考虑

一旦事务提交之后,就不能回滚了,所以undo log中当前记录的历史版本就不需要保存了,可以释放,这是一般情况,实际上undo log的释放是由InnoDB的Purge操作来管理的,这个过程是异步进行的。Purge操作会在以下条件下发生:

  • 当没有活跃的事务需要访问undo log中的信息时
  • 当undo log占用的空间过多,需要被回收以避免消耗过多的存储空间时

Purge操作会检查系统中所有活跃事务的事务ID,确保没有事务需要访问某个特定的undo log记录。如果一个undo
log记录不再被任何活跃事务需要,那么它就可以被安全地释放

通过上面的理解,update和delete操作修改的一定是最新的那个版本数据,历史版本数据是没资格修改的,也不应该修改,那select呢,它读取的是当前版本还是历史版本的数据呢,如果读历史版本应该是哪个历史版本呢?

把读取当前版本的记录的方式叫做当前读(增删改都叫这个),否则叫做快照读

根据读写可以并发这个现象再根据上面理解,可以推断出读和写一定是不同的版本,读是读的历史版本而写写的是最新版本,由于不是操作的同一块空间所以就不需要加锁,因此读和写可以并发执行

如果要读最新版本的话那也需要加锁了,也就是串行化了,select * from xxx lock in share mode,读取最新版本

隔离性最本质的做法其实就是对多个版本进行隔离,而隔离级别则是体现在事务具体能看到这么多版本中的哪些版本,能否看到最新版本,这些是完完全全由隔离级别决定的,因此隔离性和隔离级别以及回滚其实就是由MVCC多版本控制技术来实现的

为什么要有隔离级别呢?
要明确的是不管多个事务如何并发执行,总是有先有后顺序的,为了保证事务的“有先有后”,是不是应该让不同的事务看到它该看到的内容,也就是先来的事务应该只能看到它来到之前的情况,对于它之后发生的情况,它不应该知道,或者应该知道多少,这就是所谓的隔离级别要解决的问题

所以为什么根据隔离级别的不同会看到不同的结果呢?

6.2 read view

Read View就是事务进行快照读操作的时候产生的读视图(Read View),在该事务执行快照读的那一刻,会生成数据库系统当前的一个快照,这个快照用来记录并维护系统当前活跃事务的ID

Read View 在MySQL 源码中就是一个类,本质是用来进行可见性判断的即当某个事务执行快照读的时候,对该记录创建一个Read View 读视图,把它比作条件,用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log 里面的某个版本的数据

一个 Read View 通常包含以下内容:

creator_trx_id:创建这个 Read View 的事务ID
m_ids:表示在生成 Read View 时当前系统中活跃的读写事务的事务ID列表
min_trx_id:活跃的事务中最小的事务ID
max_trx_id:表示生成 Read View 时系统中应该分配给下一个事务的ID值,即目前已出现过的事务ID的最大值加一

作用:Read View 用于确定事务在快照读时能够看到哪个版本的数据记录。它通过与行记录的隐藏字段 DB_TRX_ID 进行比较来判断记录的可见性

生成时机:

在 READ COMMITTED 隔离级别下,每次进行普通 SELECT 操作前都会生成一个新的 Read View

在 REPEATABLE READ 隔离级别下,只在第一次进行普通 SELECT 操作前生成一个 Read View,之后的查询操作都复用这个 Read View

可见性判断规则:

如果记录的 trx_id 等于 creator_trx_id,说明当前事务在访问它自己修改过的记录,该版本可以被访问

如果记录的 trx_id 小于 min_trx_id,表示这个版本的记录是在创建 Read View 前已经提交的事务生成的,所以该版本的记录对当前事务可见

如果记录的 trx_id 大于或等于 max_trx_id,表示这个版本的记录是在创建 Read View 后才启动的事务生成的,所以该版本的记录对当前事务不可见

如果记录的 trx_id 在 m_ids 列表中,说明在创建 Read View 时,这个事务还在活跃,还没有提交,所以该版本的记录对当前事务不可见

如果记录的 trx_id 不在 m_ids 列表中,且大于 min_trx_id 且小于 max_trx_id,则说明这个事务在创建 Read View 之前已经提交了,所以该版本的记录对当前事务可见

应用场景:Read View 主要用于处理 READ COMMITTED 和 REPEATABLE READ 隔离级别下的快照读操作,确保事务能够读取到正确的数据版本,同时避免脏读、不可重复读和幻读等问题
在这里插入图片描述
read view是一个事务可见性的类,不是有事务就有视图,而是当这个事务首次进行快照读的时候,mysql形成一个read view,如果一直不读,那就不会有read view

事务中快照读的结果是非常依赖该事务首次出现快照读的地方,也就是首次select的时候,它会影响该事务后续快照读的结果,delete同样如此

6.3 RR-RC的区别

正是Read View生成时机的不同,从而造成RC,RR级别下快照读的结果的不同

在RR级别下的某个事务的对某条记录的第一次快照读会创建一个快照及Read View, 将当前系统活跃的其他事务记录起来

此后在调用快照读的时候,还是使用的是同一个Read View,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用的都是同一个Read View,所以对之后的修改不可见;

即RR级别下,快照读生成Read View时,Read View会记录此时所有其他活动事务的快照,这些事务的修改对于当前事务都是不可见的。而早于Read View创建的事务所做的修改均是可见

而在RC级别下的,事务中,每次快照读都会新生成一个快照和Read View, 这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因

总之在RC隔离级别下,是每个快照读都会生成并获取最新的Read View;而在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View

正是RC每次快照读,都会形成Read View,所以,RC才会有不可重复读问题

关键字:十堰市疫情防控指挥部最新公告_酷站欣赏_seo搜索引擎_保定seo外包服务商

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: