【MySQL 12】事务管理 (带思维导图)

文章目录

  • 🌈 一、事务的基本概念
    • ⭐ 1. 事务是什么
    • ⭐ 2. 事务的特性
  • 🌈 二、事务的版本支持
  • 🌈 三、事务的提交方式
    • ⭐ 1. 查看事务的提交方式
    • ⭐ 2. 设置事务的提交方式
  • 🌈 四、事务的特性证明
    • ⭐ 1. 事务的常规操作
    • ⭐ 2. 证明事务的原子性
    • ⭐ 3. 证明事务的持久性
    • ⭐ 4. 手动开启的事务必须手动提交
    • ⭐ 5. 单条 sql 与事务的关系
  • 🌈 五、事务的隔离级别
    • ⭐ 1. 隔离级别的分类
    • ⭐ 2. 隔离级别的查看
    • ⭐ 3. 隔离级别的设置
    • ⭐ 4. 读未提交
    • ⭐ 5. 读已提交
    • ⭐ 6. 可重复读
    • ⭐ 7. 可串行化
    • ⭐ 8. 总结
  • 🌈 六、事务一致性解析
  • 🌈 七、多版本并发控制
    • ⭐ 1. 数据库并发场景
    • ⭐ 2. 并发控制的概念
    • ⭐ 3. 记录的隐藏字段
    • ⭐ 4. undo 日志
    • ⭐ 5. 快照的基本概念
    • ⭐ 6. 当前读和快照读
    • ⭐ 7. Read View 读视图
  • 🌈 八、RC 和 RR 的区别

在这里插入图片描述

🌈 一、事务的基本概念

⭐ 1. 事务是什么

  • 事务是一组操作 (一条 / 多条 sql 语句) 的集合,是一个不可分割的工作单位。这些语句在逻辑上存在相关性,共同完成一个任务,事务主要用于处理操作量大,复杂度高的数据。

    • 例:A 给 B 转账,需要将 A 的钱减少,B 的钱增多,这两条 sql 语句要同时执行才有意义,这两个操作要么只能成功或失败。
  • 数据是要被多个用户共享的,在同一时刻可能会有多个请求访问数据库,MySQL 内部是采用多线程的方式来实现对数据的存储并发工作的,为了解决并发问题,事务就由此而生。

⭐ 2. 事务的特性

  1. 原子性:一个事务中的所有有操作,在处理的时候,只有全部完成或全部不完成两种可能行,不会结束在中间某个环节,事务在执行过程中如果发生错误,会被回滚到事务开始前的状态。
  2. 隔离性:数据库允许多个并发事务同时对数据进行读写和修改,事务会将要访问的数据进行隔离,防止在并发执行时由于交叉执行而导致的数据不一致。
  3. 永久性:事务处理结束后,对数据的修改是永久的,即使系统故障也不会丢失。
  4. 一致性:在事务开始前和结束后,数据库的完整性没有被破坏,即从一种状态变成另一种状态,它的结果是可预期的,能完成预定工作。
    • 前面三种特性研究透彻了,一致性自然就出来了。

🌈 二、事务的版本支持

  • 在 MySQL 中,只有使用了 InnoDB 存储引擎的数据库或表才支持事务,而 MyISAM 则不支持。

查看数据库引擎

  • 在 MySQL 中,可使用下面的指令查看数据库的存储引擎。
show engines;		# 表格显示
show engines \G 	# 行显示

image-20240822100746475

参数说明

  • Engine:存储引擎的名称。
  • Support:服务器对存储引擎的支持级别,YES 表示支持,NO 则表示不支持,DEFAULT 表示数据库默认使用的存储引擎,DISABLES 表示支持引擎但将其禁用了。
  • Comment:对该存储引擎的描述。
  • Transactions:该存储引擎是否支持事务。
  • XA:表示存储引擎是否支持 XA 事务。
  • Savepoints:表示存储引擎是否支持设置存档点。

🌈 三、事务的提交方式

  • 事务的提交分为手动提交自动提交

⭐ 1. 查看事务的提交方式

  • 通过如下指令可以知道事务的自动提交是否被打开。
    • autocommit 的值为 ON 表示自动提交被打开,值为 OFF 则表示自动提交被关闭,需要手动提交。
show variables like 'autocommit';

image-20240822103919519

⭐ 2. 设置事务的提交方式

set autocommit = 1;	# 自动提交
set autocommit = 0;	# 手动提交
  1. 关闭自动提交,即设置成手动提交

image-20240822104446020

  1. 打开自动提交

image-20240822104517131

🌈 四、事务的特性证明

准备工作

  • 设置隔离级别:为了便于演示,现在将 MySQL 的隔离级别设置的低一点,设为读未提交
set global transaction isolation level READ UNCOMMITTED;
  • 重启终端:设置完隔离级别之后,当前会话的隔离级别并不会被改变,需要使用 quit 命令退出客户端之后,再重新启动。

  • 查看隔离级别:重启完毕之后,再继续查看 MySQL 的隔离级别。

select @@transaction_isolation;

image-20240822111910373

  • 创建测试表:创建一张名为 account 的银行用户表,表中包含用户的主键 id、姓名 name 和账户余额 blance 这三个字段。
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
) ENGINE = InnoDB DEFAULT CHARSET = UTF8;

image-20240822112446307

⭐ 1. 事务的常规操作

事务操作指令说明
begin; 或 start transaction;启动一个事务,该指令开始往后的所有 sql 都属于同一个事务,直到遇见 commit 为止
savepoint 保存点名称;在事务中创建指定名称的保存点
rollback to 保存点名称;将事务回滚到指定保存点
rollback;让事务回滚到最开始
commit;提交事务,事务在提交之后就无法回滚
  • 启动两个客户端,左边的客户端负责启动事务,右边的客户端负责查看银行用户表中的信息。

image-20240822115550469

  • 让左客户端中的事务向 account 表中插入一条记录,左客户端中的事务在使用 commit 提交之前,有客户端也能查看该事务向表中插入的数据。

image-20240822120057399

  • 对左客户端的事务设置一个名为 save1 的保存点,然后再继续插入一条新的记录。

image-20240822120313184

  • 让左客户端的事务使用 rollback to 指定保存点 回滚到 save1 保存点处,右客户端此时已经无法看到表的第二条记录了。

image-20240822120649639

  • 左客户端直接使用 rollback 让事务回滚到最开始,有客户端再查看表数据,可以发现表中的数据已经全部都没了。

image-20240822120859533

⭐ 2. 证明事务的原子性

  • 启动两个客户端,左边的客户端负责启动事务,右边的客户端负责查看银行用户表中的信息。

image-20240822172723295

  • 让左客户端中的事务向 account 表中插入一条记录,左客户端中的事务在使用 commit 提交之前,有客户端也能查看该事务向表中插入的数据。

image-20240822172917133

  • 让左客户端在未 commit 时崩溃,MySQL 会自动回滚,这样就能证明事务的原子性。

image-20240822173059091

⭐ 3. 证明事务的持久性

  • 开启事务,并让事务往 account 表中插入一条数据。

image-20240822173610678

  • 左客户端使用 commit 提交事务,然后退出客户端,再通过右客户端查看表中数据。
    • 表中的数据依然存在,说明事务只要提交了,就无法回滚,证实了事务的持久性。

image-20240822173931688

⭐ 4. 手动开启的事务必须手动提交

  • 只要输入 begin 或者 start transaction 手动开启了事务,便必须要通过 commit 提交,才会持久化,与是否设置 set autocommit 无关。

image-20240822175444009

  • 使用 begin 开启事务,并往表中插入记录。

image-20240822180030699

  • 在不 commit 的前提下将左客户端关闭, 会发现事务自动回滚了,说明并没有触发默认的自动提交。

image-20240822180202804

⭐ 5. 单条 sql 与事务的关系

  • 打开还是关闭 autocommit 自动提交影响的只是单条 sql 语句,在 InnoDB 中的每一条 sql 本质上都会被封装成一个事务。
  • 如果自动提交被打开,则单条 sql 语句执行后会自动被提交。如果自动提交被关闭,则 sql 语句在执行后需要手动进行提交。

1. 打开自动提交时,会自动提交单条 sql

  • 将自动提交 autocommit 设置为 on。

image-20240822183800667

  • 左客户端在不启动事务的情况下往表中插入数据。

image-20240822183922800

  • 不进行 commit 提交,直接将左客户端 quit 退出,此时再用过右客户端查看表中数据,发现并没有被回滚。

image-20240822184151681

2. 关闭自动提交时,不自动提交单条 sql

  • 将自动提交 autocommit 设置为 off。

image-20240822184505521

  • 在左客户端不开启事务,然后往表中插入一条数据。

image-20240822184623283

  • 不使用 commit,而是使用 quit 退出左客户端,再通过右客户端查看表中数据,此时发现刚刚插入的最新记录已经消失了。

image-20240822184825234

🌈 五、事务的隔离级别

  • MySQL服务可能会同时被多个客户端进程(线程)访问,访问的方式以事务的方式进行。
  • 一个事务可能由多条 SQL 语句构成,也就意味着任何一个事务,都有执行前、执行中、执行后三个阶段,而所谓的原子性就是让用户层要么看到执行前,要么看到执行后,执行中如果出现问题,可以随时进行回滚,所以单个事务对用户表现出来的特性就是原子性。
  • 但毕竟每个事务都有一个执行的过程,在多个事务各自执行自己的多条 SQL 时,仍然可能会出现互相影响的情况,比如多个事务同时访问同一张表,甚至是表中的同一条记录。
  • 数据库为了保证事务执行过程中尽量不受干扰,于是出现了隔离性的概念,而数据库为了允许事务在执行过程中受到不同程度的干扰,于是出现了隔离级别的概念。

⭐ 1. 隔离级别的分类

  • 读未提交 (Read Uncommitted ):事务的最低隔离级别,该隔离级别下,所有的事务都可以看到其他事务没有提交的执行结果,实际生产中不可能使用这种隔离级别,因为这种隔离级别相当于没有任何隔离性,会存在很多并发问题,如脏读、幻读、不可重复读等。
  • 读提交 (Read Committed):该隔离级别是大多数数据库的默认隔离级别,但它不是MySQL默认的隔离级别,它满足了隔离的简单定义,即一个事务只能看到其他已经提交的事务所做的改变,但这种隔离级别存在不可重复读和幻读的问题。
  • 可重复读 (Repeatable Read):MySQL 默认的隔离级别,该隔离级别确保同一个事务在执行过程中,多次读取操作数据时会看到同样的数据,即解决了不可重复读的问题,但这种隔离级别下仍然存在幻读的问题。
  • 串行化 (Serializable):事务的最高隔离级别,将所有到来的 CURD 操作按照先后顺序挨个执行,从而解决了幻读问题。它在每个读的数据行上面加上共享锁,但是可能会导致超时和锁竞争问题,这种隔离级别太极端,实际生成中基本不使用。

⭐ 2. 隔离级别的查看

  • 查看全局隔离级别
select @@global.transaction_isolation;

image-20240823101455515

  • 查看会话隔离级别:登录时会默认拷贝一份全局隔离级别给会话的隔离界别。
select @@session.transaction_isolation;
select @@transaction_isolation;

image-20240823101616057

⭐ 3. 隔离级别的设置

  • 设置全局隔离级别:会影响后续的所有客户端,必须将设置该隔离界别的会话重启才会生效。
set global transaction isolation level {read uncommitted / read committed / repeatable read / serializable};
  • 设置会话隔离级别:只会影响当前会话的隔离级别,不需要重启会话即可生效。
set session transaction isolation level {read uncommitted / read committed / repeatable read / serializable};

image-20240823103138595

⭐ 4. 读未提交

  • 先说结论:事务的最低隔离级别,效率高,但由于几乎没有加锁的原因,会产生很多并发问题,不建议使用。
  • 一个事务的操作即使还没有提交,其他事务也能看到其所做的操作的结果。
    • 该隔离级别下,会产生脏读的问题,即一个事务读取到另一个事务还没有提交(commit)的数据。

演示读未提交

  • 启动两个客户端,将隔离级别都设置为读未提交,并查看此时 account 表中的数据。

image-20240822200835990

  • 在左右两个客户端各自使用 begin 开启一个事务,然后让左客户端往表中插入数据但不提交,让右客户端读取表中的数据。
    • 可以发现,在未 commit 的情况下,其他客户端居然已经能够读取到数据了,这种情况被称之为脏读

image-20240822201411430

⭐ 5. 读已提交

  • 只有当一个事务将他的所有操作提交之后,其他事务才能够看到这个事务所做的操作。
  • 该隔离级别下会产生不可重复读的问题,即一个事务先后读取同一条记录,但两次读取的数据不同。

举个栗子

  • 启动两个客户端,并将各自的隔离级别都设置成读提交。

image-20240823093625869

  • 左右两个客户端各自开启一个事务,左客户端的事务在未提交前,右客户端无法查看左客户端所做的操作。

image-20240823094050112

  • 当左客户端使用 commit 将事务提交之后,右客户端才能看到其对数据的操作。

image-20240823094302318

⭐ 6. 可重复读

  • 即使事务 A 使用 commit 提交事务了,事务 B 也无法查看到 A 的操作,只有重启一个新的事务才能看到。
    • 在一个事务的执行过程中,多次相同的 select 语句查询到的结果相同。
  • 一般的数据库在该隔离级别下在 insert 记录时会产生的幻读的问题,但 MySQL 不会。
    • 幻读:一个事务按照条件查询数据时,没有对应的数据记录,但在插入数据时,又发现这条记录已经存在,就像出现了幻影。

举个栗子

  • 启动两个客户端,并将各自的隔离级别设置成可重复读。

image-20240823104606914

  • 两个客户端各自新启一个事务,让左客户端的事务负责插入数据,右客户端的数据负责查询数据。

image-20240823104829074

  • 左客户端将事务提交,右客户端继续查询,发现查询到的结果并没有变化。

image-20240823105252370

  • 右客户端将自己的事务 commit 提交之后,才能查询到左客户端对表插入的新数据。

image-20240823110105047

⭐ 7. 可串行化

  • 最高隔离级别,会将到来的所有事务按照到达的先后顺序挨个执行,极大的影响了效率,不推荐使用该隔离级别。

举个栗子

  • 启动两个客户端会话,并将各自的会话隔离级别设置成串行化 serializable。

image-20240823194636928

  • 让右客户端先启动事务,左客户端后启动,这样就让右事务比左事务先到达,如果这两个事务都进行读操作,则这两个事务可以并发执行,不会阻塞住。

image-20240823194842647

  • 在这两个事务都没有 commit 的情况下,如果哪个事务要对表执行插入操作,立马会被阻塞住。

image-20240823195120616

  • 只有当其他事务 (此处是右客户端的事务) 全部 commit 之后,插入操作被阻塞住的事务才会继续往下执行。

image-20240823195549923

⭐ 8. 总结

  • 事务的隔离级别越高,其安全性也就越高,数据库的并发性能也就越低。
  • 不可重复读的重点在于修改和删除,同样的条件已经读取过的数据,等下次再读可能就不一样了。
  • 幻读的重点在于新增,同样的条件,第一次和第二次读取的表的行数会不一样。
  • MySQL 的默认隔离级别是可重复读,一般情况下不建议修改。

隔离级别与其会产生的问题

  • 其中,√ 表示在对应隔离界别下会发生相应问题,× 则表示不会发生相应问题。
隔离级别脏读不可重复读幻读是否加锁读
读未提交
读已提交×
可重复读×××
可串行化×××

🌈 六、事务一致性解析

  • 在实现了原子性、隔离性、永久性后一致性自然就出来了。
  • 事务执行的结果,必须使数据库从一个一致性状态变成另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库就处于一致性状态。
  • 如果事务在执行过程中发生了错误,则会自动回滚到事务的最开始,即一致性需要原子性来保证
  • 事务处理结束后,对数据的修改必须是永久的,即便系统故障也不能丢失,即一致性需要持久性来保证
  • 多个事务同时访问同一份数据时,需要保证这多个事务在并发执行时,不会因为由于交叉执行而导致数据的不一致,即一致性需要隔离性来保证
  • 一致性还与用户的业务逻辑强相关,一般由 MySQL 提供技术支持,但如果用户本身的业务逻辑不行,最终也会破坏数据库的一致性。
  • 因此,想要实现一致性的效果,需要原子性、持久性、隔离性,以及上层用户编写出正确的业务逻辑。

🌈 七、多版本并发控制

  • MySQL 在同一时刻可能存在大量事务,如果不对这些事务加以控制,在执行时就可能会出现并发问题。

⭐ 1. 数据库并发场景

  1. 读 - 读:不存在任何问题,也不需要并发控制。
  2. 读 - 写:会产生线程安全问题,可能会存在事务的隔离性问题,即可能遇到脏读、幻读、不可重复读。
  3. 写 - 写:会产生线程安全问题,可能回存在更新丢失问题。

⭐ 2. 并发控制的概念

  • 多版本并发控制 MVCC 是一种用来解决读 - 写冲突无锁并发控制
    • 其主要依赖于记录的隐藏字段、undo 日志和 Read View 来实现。
  • MySQL 会为事务分配单项增长的事务 id,为每个修改保存一个版本,将版本与事务 id 关联起来,读操作只读该事务开始前的数据库快照。
    • 每个事务都要有自己的事务 ID,可以根据事务 ID 的大小,来决定事务到来的先后顺序。

1. MVCC 能为数据库解决的问题

  • 在并发读 - 写数据库时,能做到在读操作时不用把写操作给阻塞住,写操作也不会阻塞住读操作,提高了数据库的并发读写性能。
  • 解决了脏读、幻读、不可重复读等事务隔离问题,但是不能解决更新丢失的问题。

2. 如何管理事务 (事务的具体化)

  • MySQL 的服务端 (mysqld) 可能会面临处理多个事务的情况,事务也有自己的生命周期,mysqld 也要对多个事务进行管理,因此在 mysqld 中,事务一定是对应的一个或者一套结构体 / 类对象。
  • 事务也要有自己的结构体,事务 ID 对应的就是每个事务的结构体对象。当到达一个事务时,MySQL 会先 new 出一个事务的对象,再给该对象原子性的申请一个事务 ID,最后用事务 ID 初始化这个事务的结构体对象。
  • 将多个事务的结构体对象使用某种数据结构管理组织起来,组织好之后就成了对对应数据结构的增删查改。

⭐ 3. 记录的隐藏字段

  • 数据库表中的每条记录 (每行数据) 都会有 3 个隐藏的字段。
    • 数据库表中的每条记录还有一个删除 flag 隐藏字段,即记录被更新或删除并不代表真的删了,而是删除 flag 变了。
隐藏的字段名大小说明
DB_TRX_ID6 字节记录创建这条记录 / 最后一次修改该记录的事务 ID
DB_ROLL_PTR7 字节回滚指针,指向这条记录的上一个版本,即指向历史版本,这些数据一般在 undo log 中
DB_ROW_ID6 字节隐含的自增 ID (隐藏主键),如果数据库表没有设置主键,InnoDB 会自动以该字段生成一个聚簇索引

举个栗子

  • 创建一张名为 student 的学生表,表中包含姓名 name 和年龄 age 这两个字段。

image-20240824110910880

  • 当向表中插入一条记录后,该记录不仅包含 name 和 age 字段,还包含三个隐藏字段。

image-20240824111000267

⭐ 4. undo 日志

  • MySQL 将来是以服务进程的方式在内存中运行的。
  • 之前的索引、事务、隔离性、日志等机制都是在内存中完成的,即在 MySQL 内部的相关缓冲区中保存相关数据,完成各种判断操作。
  • 然后在合适的时候,将相关数据刷新到磁盘当中,undo lo 就是 MySQL 中的一段内存缓冲区,用来保存日志数据

MySQL 中的三大日志

  • 多版本并发控制 MVCC 的实现主要依赖这三个日志中的 undo log,记录的历史版本就存储在 undo log 对应的缓冲区中。
日志说明
redo log重做日志,用于在 MySQL 崩溃后进行数据恢复,保证数据的持久性
bin log逻辑日志,用于对主从数据备份时进行数据同步,保证数据的一致性
undo log回滚日志,用于对已经执行的操作进行回滚操作,保证事务的原子性

⭐ 5. 快照的基本概念

  • undo log 中有一个基于链表记录的历史版本链,undo log 中的每一个历史版本就是一个个的快照

1. 模拟多版本并发控制 MVCC 的场景

  • 当前有一个事务 ID 为 10 的事务,对 student 表中的记录进行修改,将 name (张三) 改成 name(李四)。
    • 由于要进行的是写操作,因此需要先给该条记录加行级锁。
    • 修改前,先将该条记录拷贝到 undo log 中,此时的 undo log 中会多出一行副本数据。
    • 再将原始记录中的张三的名字改成李四,并将该记录的 DB_TRX_ID 改为 10,让回滚指针 DB_ROLL_PTR 指向 undo log 中副本数据的地址,从而指向上一个历史版本。
    • 当将 10 号事务提交后,释放锁,此时最新的记录就是学生姓名为李四的记录了。

image-20240824111541179

  • 当前又有一个事务 ID 为 11 的事务,对 student 表中的记录进行修改,将 age(28) 修改成 age(38)。
    • 事务 11 也要进行修改,因此需要先给最新的这条记录加上行级锁。
    • 修改前,先将该行记录拷贝到 undo log 中,此时的 undo log 又多了一行副本数据。对新的副本采用头插的方式才插入到 undo log 中。
    • 将原始记录的 age 改为 38,并将该记录的 DB_TRX_ID 改为 11,让回滚指针 DB_ROLL_PTR 执行刚拷贝到 undo log 中的新副本不数据的地址,从而执行该记录的上一历史版本。
    • 将 11 号事务提交,然后释放行级锁,此时最新的记录就是 age 为 38 的那条。

image-20240824112329534

2. 何时清除 undo log 中的历史版本链

  • undo log 只是一段缓冲区,记录的是事务在运行期间对数据的历史修改。
  • 当事务 commit 提交后,undo log 曾经的历史版本就会被释放。

⭐ 6. 当前读和快照读

  • 当前读:访问当前最新的记录被称之为当前读,增删改操作必须得是当前读。
  • 快照读:访问版本链中的历史记录被称之为快照读,事务在 select 时当前读和快照都有可能进行。

如何实现读写的多版本并发控制

  • 在执行写操作时,使用的是当前读,访问的是最新的数据版本。
  • 在执行读操作时,使用的是快照读,访问的是历史的数据版本。

⭐ 7. Read View 读视图

  • 可用 Read View 保证不同的事务,能够看到不同的内容,即隔离级别的实现。

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

    • 当一个事务被开启时,都会被分配一个 ID,这个 ID 是递增的,索引越新的事务,ID 值越大。
  • Read View 在 MySQL 的源码中它就是一个类,本质是用来做可见性判断的,当事务对某个记录执行快照读时,会对改记录创建与一个 Read View 读视图,根据这个读视图来判断当前事务能够看到该记录的是哪个版本的数据。

Read View 类的源码

class ReadView 
{// 省略......
private:// 高水位事务 ID: 大于等于这个 ID 的事务均不可见trx_id_t m_low_limit_id;// 低水位事务 ID: 小于这个 ID 的事务均可见trx_id_t m_up_limit_id;// 创建该 Read View 的事务的 IDtrx_id_t m_creator_trx_id;// 创建视图时的活跃事务 ID 列表ids_t m_ids;// 配合 purge,标识该视图不需要小于 m_low_limit_no 的 UNDO LOG,// 如果其他视图也不需要,则可以删除小于 m_low_limit_no 的 UNDO LOGtrx_id_t m_low_limit_no;// 标记视图是否被关闭bool m_closed;// 省略......
};

Read View 类中部分成员的说明

m_ids		 	 	// 一张用来维护 Read View 生成时刻系统正活跃的事务 ID 的列表
up_limit_id		 	// 用以记录 m_ids 列表中事务 ID 最小的 ID
low_limit_id	 	// 存储目前已经出现过的对最大事务 ID 值 + 1 后的值
m_creator_trx_id	// 创建该 Read View 的事务的 ID
  • 由于事务 ID 是递增的,因此根据 Read View 中的 m_up_limit_id 和 m_low_limit_id,可将事务 ID 分成三个部分:
  1. 事务 ID < m_up_limit_id 的事务:一定是生成读视图时已经提交的事务。
  2. 事务 ID >= m_low_limit_id 的事务:一定时生成读视图时还没开启的事务。
  3. m_up_limit_id < 事务 ID < m_low_limit_id 的事务: 在生成读视图时可能处于活跃 / 已提交状态的事务,此时需要判断事务 ID 是否存在于 m_ids 中来判断该事务是否已经提交。

image-20240824180517058

🌈 八、RC 和 RR 的区别

1. 演示当前读和快照都在 RR 个隔离界别下的区别

  • 启动两个会话客户端,并将各自的会话隔离级别都设置成可重复读 (RR)。

image-20240824184952637

  • 让两个客户端各自 begin 一个事务,在左事务操作前,先让右事务查看一下表中的 account 表中的数据。

image-20240824185145896

  • 让左客户端事务对表中的信息进行修改并提交,右客户端的事务是看不到修改后的数据的。

image-20240824190100683

  • 让右客户端的事务使用如下指令以加锁共享的方式执行当前读,能看到被修改后的数据。
select * from account lock in share mode;

image-20240824190138987

  • 但如果修改一下 SQL 的执行顺序,在两个客户端各自开启事务后,先让左客户端的事务对表中的信息进行修改并提交,再让右客户端中的事务进行查看,此时右客户端中的事务就能直接看到修改后的数据。

image-20240824190529468

  • 在右客户端执行当前读,能够发现刚才读到的数据确实已经是最新的了。

image-20240824190643364

  • 这两种情况唯一区别在于,右事务在左事务修改数据之前是否进行过快照读
  • 当前面没有进行读取的情况下,就不存在历史版本,只能进行当前读。
  • 在可重复读的隔离级别下,只要保证事务对数据的第一次读取和最后一次读取能够读取到同样的数据即可。

2. RC 和 RR 的本质区别

  • Read View 形成的时机不同,会影响事务的可见性。
  • 在 RR 隔离级别下,事务第一次进行快照读时会创建一个 Read View,将当前系统中活跃的事务记录下来,此后再进行快照读时就会直接使用这个 Read View 进行可见性判断,因此当前事务看不到第一次快照读之后其他事务所作的修改。
  • 而在 RC 隔离级别下,事务每次进行快照读时都会创建一个 Read View,然后根据这个 Read View 进行可见性判断,因此每次快照读时都能读取到被提交了的最新的数据。
  • RR 级别下快照读只会创建一次 Read View,所以 RR 级别是可重复读的,而RC 级别下每次快照读都会创建新的 Read View,所以 RC 级别是不可重复读的。
    前读,能够发现刚才读到的数据确实已经是最新的了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/412478.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

进程间的通信

建立两个.c 建立子父进程&#xff0c;父进程发送消息到队列&#xff0c;子进程读取队列&#xff0c;另一个同样。 #include <myhead.h> struct msga {long mtype;char mtext[1024]; }; #define len sizeof(struct msga)-sizeof(long) int main(int argc, const char *arg…

烂大街的测试左移和右移

01 测试左移与右移的定义 通俗的讲&#xff1a;左移是往开发阶段移&#xff0c;右移是往发布之后移。 正常测试&#xff1a;提测后的测试工作——到——发布验证完成阶段。 测试左移&#xff1a;提测之前的测试。 如&#xff1a;代码单元测试&#xff0c;代码质量检测&#x…

python-读取word中的内容

doc Document(rD:\xxxx\xxxx\xxx.docx) #读取word中所有内容 for p in doc.paragraphs print(p,p.text) #读取指定段落中的所有run(文字块) for run in doc.paragraphs[1].runs: print(run,run.text) #读取word中所有表格内容 for 表格 in doc.tables: print(表格) for 行 in …

产品经理有没有必要考pmp证书?

可以给一个总结&#xff1a;想提升自己的可以考&#xff0c;单纯奔着考证去的&#xff0c;没必要考&#xff01; 如果产品经理的相关证件&#xff0c;比如 npdp 之类的&#xff0c;都已经拿到手了&#xff0c;并且觉得自己现阶段工作比较满意&#xff0c;想提升自己更上一层楼…

《安全回收电脑,从销毁硬盘数据开始》文件硬盘数据销毁

在这个信息高速发展的时代&#xff0c;电脑已经成为我们生活和工作中不可或缺的工具。然而&#xff0c;当我们决定更换电脑或者对旧电脑进行回收时&#xff0c;你是否考虑过硬盘中存储的数据安全问题呢&#xff1f; 电脑硬盘中可能存储着大量的个人信息、工作文件、照片、视频等…

解决vue中this.$set()不更新页面问题

问题汇总&#xff1a;解决vue中this.$set()不更新页面问题 this.$set()方法有一种情况&#xff0c;就是当你要设置的key已经存在于这个对象或数组中的时候&#xff0c;它只会更改data并不会为该key添加响应检测&#xff0c;所以解决这个问题的办法就是在设置值之前先把这个属性…

k8s项目的发布(金丝雀发布)

目录 三种发布方式 1.蓝绿发布 2.金丝雀发布&#xff08;灰度发布&#xff09; 实验&#xff1a;k8s实现金丝雀发布 3.滚动发布&#xff08;默认形式&#xff09; 因为应用升级以及新旧业务切换&#xff0c;所以在这个过程当中如何保证对外的服务正常是一个非常重要的问题…

InternVL 多模态模型部署微调实践

写在前面&#xff08;什么是InternVL&#xff09; InternVL 是一种用于多模态任务的深度学习模型&#xff0c;旨在处理和理解多种类型的数据输入&#xff0c;如图像和文本。它结合了视觉和语言模型&#xff0c;能够执行复杂的跨模态任务&#xff0c;比如图文匹配、图像描述生成…

macos 10.15 catalina xcode 下载和安装

在macos 10.15 catalina系统中, 由于系统已经不再支持,所以我们无法通过应用商店来安装xcode, 需要手动下载指定版本的 xcode 版本才能安装, catalina 支持的最新xcode版本为 Xcode v12.4 (12D4e) , 其他的新版本是无法安装在Catalina系统中的. Xcode_12.4.xip下载地址 注意,下…

前端开发学习Docker记录02容器操作

docker images先查看有哪些镜像 运行nginx docker run nginx使用docker ps 可以看到有哪些镜像在运行 docker stats查看运行状态 命令总结

linux 云主机下载压缩包安装配置 maven 实录(华为云 EulerOS)

本想通过 yum install maven 直接安装的, 方便省事, 但报错说没找到, 于是只能手动安装了, 把整个过程记录了一下, 包括下载, 解压, 配置及验证的全过程, 并对用到的命令及参数作了详细说明, 需要的同学可以参考. maven 官网找到下载链接 首先要去到 maven 的官网, https://m…

国产网卡品牌崛起,做好网络信息安全的“守门人”

在信息技术日新月异的时代背景下&#xff0c;信息安全不仅关乎个人隐私保护&#xff0c;更是国家安全与经济发展的基石。LR-LINK联瑞凭借其前瞻性的视野和深厚的研发实力&#xff0c;成功自主研发出全国产化的FPGA&#xff08;现场可编程门阵列&#xff09;网闸隔离卡方案&…

AI编码公司Magic获得近5亿美元巨额投资

Magic&#xff0c;一家专注于生成式人工智能AI编码的初创公司&#xff0c;最近在AI领域取得了显著的成就。该公司通过创建模型来生成代码并自动执行软件开发任务&#xff0c;成功吸引了包括前谷歌CEO埃里克施密特在内的一系列知名投资者的关注&#xff0c;并完成了一轮3.2亿美元…

Linux 下查找运行中的 Java 进程及 .jar 文件位置

在 Linux 环境中&#xff0c;有时我们需要查找正在运行的 Java 进程以及它们对应的 .jar 文件位置。本文将介绍如何使用命令行工具来实现这一目标。 前言 在 Linux 系统中&#xff0c;我们经常需要监控正在运行的应用程序&#xff0c;特别是在出现问题时&#xff0c;了解应用程…

Hook 框架 Frida

文章目录 Hook 框架 FridaHook框架介绍下载和安装Frida 的使用手机端启动frida服务端电脑端配置简单使用python的hook方式js的hook方式 Hook 框架 Frida Hook框架介绍 Hook 框架是一种技术&#xff0c;用于在运行时拦截和修改应用程序的行为。 通过 Hook&#xff0c;你可以劫…

鸿蒙界面开发(八):Grid网格布局Badge角标组件

Badge角标组件 在目标组件的外层包裹一层Badge角标组件 支持位置&#xff1a;右上&#xff0c;左&#xff0c;右 也可以使用绝对定位实现更灵活的角标位置。 Badge({count:1,//角标数值&#xff0c;角标数值为0时不展示position:BadgePosition.RightTop,//角标位置&#xff0…

换毛季猫咪化身掉毛怪,宠物浮毛如何清理?推荐用宠物空气净化器

我家现在有三只毛孩子&#xff0c;养宠的幸福是三倍&#xff0c;除毛的烦恼也是三倍。尤其还有两只是银渐层&#xff0c;掉毛量实在是太夸张了&#xff0c;衣服、地板、水杯家里到处都是。我也每天早晚都给它们梳毛&#xff0c;卫生也定期清理&#xff0c;可还是浮毛满天飞。 …

kafka集群

cd /opt/software 把kafka压缩包拉进来 并解压到/usr下 tar -xzvf /opt/software/kafka_2.12-2.7.0.tgz -C /usr/ 改名 mv /usr/kafka_2.12-2.7.0/ /usr/kafka 配置环境变量 vim /etc/profile大写G定位到最后一行 在 o 在下一行添加kefka环境变量export JAVA_HOME/usr…

店招起名“大润發”,侵犯“大润发”商标权赔偿8000元!

近日某干果店招为“大润發水果干果批发”的店铺&#xff0c;因侵犯“大润发”注册商标专用权&#xff0c;赔偿原告所属主体共计人民币8000元&#xff0c;有些人起店招名称喜欢傍大牌&#xff0c;这样很容易侵犯商标权。 有些聪明的人会想&#xff0c;大牌商标是繁体&#xff0c…

ssrf实现

一、SSRF &#xff08;Server-side Request Forge, 服务端请求伪造&#xff09; 1、概念&#xff1a; 它是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下&#xff0c;SSRF攻击的目标是从外网无法访问的内部系统。正是因为它是由服务端发起的&#xff0c;所…