第13章 事务基础知识【3.事务篇】【MySQL高级】5

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 第13章 事务基础知识【3.事务篇】【MySQL高级】5

演示4:幻读


会话A&B

mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)
mysql> 

会话B

mysql> select count(*) from account where id = 3;
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)
mysql> 

会话A

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into account(id,name,balance) values(3,'王五',100);
Query OK, 1 row affected (0.00 sec)
mysql> select * from account;
+----+--------+---------+
| id | name   | balance |
+----+--------+---------+
|  1 | 张三   |      40 |
|  2 | 李四   |       0 |
|  3 | 王五   |     100 |
+----+--------+---------+
3 rows in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

会话B

mysql> select count(*) from account where id = 3;
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

证明出现幻读

#证明出现幻读
mysql> insert into account(id,name,balance) values(3,'王五',1000);
ERROR 1062 (23000): Duplicate entry '3' for key 'account.PRIMARY'
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

这里要灵活的理解读取的意思。第一次select是读取,第二次的insert其实也属于隐式的读取,只不过是在mysql的机制中读取的,插入数据也是要先读取一下有没有主键冲突才能决定是否执行插入


幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些: select某记录是否存在,不存在,准备插入此记录,但执行insert时发现此记录已存在,无法插入,此时就发生了幻读。


在RR隔离级别下,step1、step2是会正常执行的,step3则会报错主键冲突,对于事务1的业务来说是执行失败的,这里事务1就是发生了幻读,因为事务1在step1中读取的数据状态并不能支撑后续的业务操作,事务1:“见鬼了,我刚才读到的结果应该可以支持我这样操作才对啊,为什么现在不可以"。事务1不敢相信的又执行了step4,发现和setp1读取的结果是一样的(RR下的 MVCC机制)。此时,幻读无疑已经发生,事务1无论读取多少次,都查不到id=3的记录,但它的确无法插入这条他通过读取来认定不存在的记录(此数据已被事务2插入),对于事务1来说,它幻读了。


其实RR(Mysql默认隔离级别)也是可以避免幻读的,通过对select操作手动加行X锁(独占锁) (SELECT … FOR UPDATE这也正是SERIALIZABLE 隔离级别下会隐式为你做的事情),同时,即便当前记录不存在,比如id = 3是不存在的,当前事务也会获得一把记录锁(因为InnoDB的行锁锁定的是索引,故记录实体存在与否没关系,存在就加行X锁,不存在就加间隙锁),其他事务则无法插入此索引的记录,故杜绝了幻读。


在SERIALIZABLE隔离级别下,step1执行时是会隐式的添加行(X)锁/gap(X)锁的,从而step2会被阻塞,step3 会正常执行,待事务1提交后,事务2才能继续执行(主键冲突执行失败),对于事务1来说业务是正确的,成功的阻塞扼杀了扰乱业务的事务2,对于事务1来说他前期读取的结果是可以支撑其后续业务的。


所以MySQL的幻读并非什么读取两次返回结果集不同,而是事务在插入事先检测不存在的记录时,惊奇的发现这些数据已经存在了,之前的检测读获取到的数据如同鬼影一般

补充:SERIALIZABLE

会话A&B

mysql> set session transaction_isolation = 'SERIALIZABLE';
Query OK, 0 rows affected (0.00 sec)
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| SERIALIZABLE            |
+-------------------------+
1 row in set (0.00 sec)

会话B

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select count(*) from account where id = 4;
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

会话A

mysql> insert into account(id,name,balance) values(4,'马六',100);
###卡住

会话B

mysql> insert into account(id,name,balance) values(4,'马六',1000);
Query OK, 1 row affected (0.00 sec)
mysql> select * from account;
+----+--------+---------+
| id | name   | balance |
+----+--------+---------+
|  1 | 张三   |      40 |
|  2 | 李四   |       0 |
|  3 | 王五   |     100 |
|  4 | 马六   |    1000 |
+----+--------+---------+
4 rows in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

会话A

###不卡了
ERROR 1062 (23000): Duplicate entry '4' for key 'account.PRIMARY'
mysql> select * from account;
+----+--------+---------+
| id | name   | balance |
+----+--------+---------+
|  1 | 张三   |      40 |
|  2 | 李四   |       0 |
|  3 | 王五   |     100 |
|  4 | 马六   |    1000 |
+----+--------+---------+
4 rows in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

4. 事务的常见分类

从事务理论的角度来看,可以把事务分为以下几种类型:
扁平事务(Flat Transactions)

带有保存点的扁平事务(Flat Transactions with Savepoints)

链事务(Chained Transactions)

嵌套事务(Nested Transactions)

分布式事务(Distributed Transactions)

下面简单介绍这几种类型:

1)扁平事务是事务类型中最简单的一种,但是在实际生产环境中,这可能是使用最频繁的事务,在扁平事务中,所有操作都处于同一层次,其由BEGIN WORK开始,由COMMIT WORK或ROLLBACK WORK结束,其间的操作是原子的,要么都执行,要么都回滚,因此,扁平事务是应用程序成为原子操作的基本组成模块。扁平事务虽然简单,但是在实际环境中使用最为频繁,也正因为其简单,使用频繁,故每个数据库系统都实现了对扁平事务的支持。扁平事务的主要限制是不能提交或者回滚事务的某一部分,或分几个步骤提交。


扁平事务一般有三种不同的结果:①事务成功完成。在平常应用中约占所有事务的96%。②应用程序要求停止事务。比如应用程序在捕获到异常时会回滚事务,约占事务的3%。③外界因素强制终止事务。如连接超时或连接断开,约占所有事务的1%。


2)带有保存点的扁平事务除了支持扁平事务支持的操作外,还允许在事务执行过程中回滚到同一事务中较早的一个状态。这是因为某些事务可能在执行过程中出现的错误并不会导致所有的操作都无效,放弃整个事务不合乎要求,开销太大。


保存点(Savepoint)用来通知事务系统应该记住事务当前的状态,以便当之后发生错误时,事务能回到保存点当时的状态。对于扁平的事务来说,隐式的设置了一个保存点,然而在整个事务中,只有这一个保存点,因此,回滚只能会滚到事务开始时的状态。


3)链事务是指一个事务由多个子事务链式组成,它可以被视为保存点模式的一个变种。带有保存点的扁平事务,当发生系统崩溃时,所有的保存点都将消失,这意味着当进行恢复时,事务需要从开始处重新执行,而不能从最近的一个保存点继续执行。链事务的思想是:在提交一个事务时,释放不需要的数据对象,将必要的处理上下文隐式地传给下一个要开始的事务,前一个子事务的提交操作和下一个子事务的开始操作合并成一个原子操作,这意味着下一个事务将看到上一个事务的结果,就好像在一个事务中进行一样。这样,在提交子事务时就可以释放不需要的数据对象,而不必等到整个事务完成后才释放。其工作方式如下:



链事务与带有保存点的扁平事务的不同之处体现在:


①带有保存点的扁平事务能回滚到任意正确的保存点,而链事务中的回滚仅限于当前事务,即只能恢复到最近的

一个保存点。


②对于锁的处理,两者也不相同,链事务在执行COMMIT后即释放了当前所持有的锁,而带有保存点的扁平事务

不影响迄今为止所持有的锁。


4)嵌套事务是个层次结构框架,由一个顶层事务(Top-Level Transaction)控制着各个层次的事务,顶层事务之下嵌套的事务被称为子事务(Subtransaction),其控制着每一个局部的变换,子事务本身也可以是嵌套事务。因此,嵌套事务的层次结构可以看成是一棵树。


5)分布式事务通常是在一个分布式环境下运行的扁平事务,因此,需要根据数据所在位置访问网络中不同节点的数据库资源。例如,一个银行用户从招商银行的账户向工商银行的账户转账1000元,这里需要用到分布式事务,因为不能仅调用某一家银行的数据库就完成任务。

最后


2022/8/11 13:35


p161~p168


Markdown 27412 字数 1463 行数

HTML 24361 字数 843 段落


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5天前
|
SQL 存储 缓存
【MySQL】事务
【MySQL】事务
14 0
|
5天前
|
SQL 存储 关系型数据库
MySQL索引及事务
MySQL索引及事务
24 2
|
5天前
|
存储 关系型数据库 MySQL
MySQL事务简述
MySQL事务简述
6 0
|
5天前
|
存储 算法 关系型数据库
MySQL事务与锁,看这一篇就够了!
MySQL事务与锁,看这一篇就够了!
|
5天前
|
Java 关系型数据库 MySQL
MySQL 索引事务
MySQL 索引事务
14 0
|
3天前
|
关系型数据库 MySQL API
实时计算 Flink版产品使用合集之可以通过mysql-cdc动态监听MySQL数据库的数据变动吗
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
57 0
|
5天前
|
关系型数据库 MySQL 数据库
docker MySQL删除数据库时的错误(errno: 39)
docker MySQL删除数据库时的错误(errno: 39)
49 0
|
5天前
|
Java 关系型数据库 MySQL
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口(下)
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口
34 0
|
5天前
|
Java 关系型数据库 MySQL
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口(上)
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口
35 0
|
5天前
|
前端开发 关系型数据库 MySQL
【MySQL × SpringBoot 突发奇想】全面实现流程 · 数据库导出Excel表格文件的接口
【MySQL × SpringBoot 突发奇想】全面实现流程 · 数据库导出Excel表格文件的接口
34 0