SQL事务管理

news/2024/7/5 3:46:04

 事务管理是针对数据库的一组操作。由一条或多条SQL语句组成,这些语句在逻辑上具有强烈的相关性,如果其中一条语句无法执行,那么所有的语句都不会执行。

1 事务管理

原子性

指一个事务必须被视为一个不可分割的最小单元。只有事务中所有的数据操作都执行成功,才算整个事务都执行成功。

一致性

事务执行前后,数据库的状态(所有的约束条件、完整性规则和触发器)必须保持一致。

隔离性

每个事务的执行都应该与其他事务相互隔离,使得每个事务感觉不到其他事务的存在。

持久性

一旦事务提交,其所做的修改将会永久保存在数据库中。即使系统故障或重启后也不会丢失。

表 事务的四个特性

事务有以下的优点:

  1. 并发控制,事务可以管理并发访问数据库的能力。保证多个并发执行的事务不会相互干扰或产生不一致的结果。确保每个事务的操作在逻辑上相互隔离,避免了数据竞争和冲突。
  2. 错误恢复,如果事务执行过程发生错误,事务可以被回滚,撤销之前的操作,将数据库状态恢复到事务开始之前的状态。
  3. 高效性,通过将多个相关操作组合在一个事务中,可以减少与数据库的交互次数,提高效率。

1.1 事务基本用法

START TRANSACTION; -- 开启事务

SAVEPOINT label1; -- 保存回滚节点

ROLLBACK TO label1; -- 回滚到具体的节点

ROLLBACK; -- 回滚整个事务

COMMIT; -- 提交事务

START TRANSACTION;

INSERT teacher(id,name) VALUES(4,"刘老师");

SAVEPOINT label1;

INSERT teacher(id,name) VALUES(5,"张老师");

ROLLBACK TO label1;

COMMIT;  -- 最终,只有第一条信息会被插入id=4

1.2 事务并发引发的问题

1)脏读。一个事务处理过程中读取了另一个未提交的事务中的数据。

当数据库的事务隔离级别为读未提交(RU,READ-UNCOMMITTED)时,会出现这个问题。

-- 事务隔离级别为“读未提交”

START TRANSACTION;

UPDATE teacher SET `name`=CONCAT(`name`,"(未提交事务)") WHERE id = 4;

ROLLBACK -- 先不执行,先在其他事务查询这条数据,发现name="刘老师(未提交事务)",然后再执行回滚

将数据库隔离级别设置为其他的级别(比如读已提交),则不会有这个问题。

2)不可重复读。在一个事务中,多次读取同一个数据时,读取的数据不一致。(数据被更新了update)。

-- 隔离级别为“读已提交”

START TRANSACTION;

SELECT `name` FROM teacher WHERE id = 4;

SELECT SLEEP(30); -- 休眠30s,在这个时间在另一个事务中执行update操作,来跟新id=4的数据

SELECT `name` FROM teacher WHERE id = 4;

COMMIT;

将隔离级别设置为可重复读或可串行化则不会出现这个问题。

3)幻读。读取某一范围的数据时,在一个事务中多次读,结果不一致。(发生在插入或删除数据时。)

-- 隔离级别为 "读已提交",注意mysql 的“可重复读”不会出现这个问题。

START TRANSACTION;

SELECT * FROM teacher WHERE name = '刘老师';

SELECT SLEEP(20); -- 休眠20s,在这段时间在另一个事务执行insert操作,来插入新刘老师的数据

SELECT * FROM teacher WHERE name = '刘老师';

COMMIT;

mysql 将隔离级别设置为可重复读或可串行化则不会出现这个问题。

1.3 事务的隔离级别

读未提交 RU

READ UNCOMMITTED

可以读取到事务未提交的数据,隔离性差。

读已提交 RC

READ COMMITTED

读取事务已提交的数据,隔离性一般。

可重复读 RR

REPEATABLE READ

默认。在一个事务中多次读取同一个数据时,能够保证读取到的数据一致(即使其他事务修改了该数据)。

可串行化 SR

SERIALIZABLE

最高隔离级别。保证所有事务之间的执行顺序按照某个顺序执行,避免了所有并发问题。事务并发性最差。

表 事务的四种隔离级别

读未提交

读已提交

可重复读

可串行化

脏读

x

不可重复读

x

x

幻读

x

x

表 不同隔离级别下所解决的问题

注意:MySQL 隔离级别为可重复读解决了“幻读”的问题。

SHOW VARIABLES LIKE "transaction_isolation"; -- 查看数据库的隔离级别

SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- 设置全局隔离级别为“读未提交”。需要重新连接数据库才会生效。

1.4 当前读和快照读

当前读,读取最新提交的数据。(隔离级别为可串行化)。

快照读(一致性读),读取某一时间点的数据。(隔离级别为读提交或可重复读)。

在读提交隔离级别下,每次SELECT都会建立新的快照。

在可重复读隔离级别下,建立快照的时机为:

  1. 事务启动后,首次SELECT。
  2. 事务启动时选择了with consistent snapshot,则在启动时建立快照。
  3. 基于旧数据的修改操作(或insert及delete操作),会重新建立快照。
-- 隔离级别为 "可重复读"

START TRANSACTION;

SELECT * FROM teacher WHERE name LIKE '%刘老师%'; -- 建立快照

SELECT SLEEP(20); -- 休眠20s,在这段时间在另一个事务执行insert操作,来插入新刘老师的数据

INSERT INTO teacher(`name`) VALUES('刘老师'); -- 数据插入或删除会建立新的快照

UPDATE teacher SET `name` = '刘老师(旧数据修改)' WHERE id = 2; -- 旧数据修改,会建立新的快照

SELECT * FROM teacher WHERE name LIKE '%刘老师%';

COMMIT;

注意,上面查询的结果虽然不一致,这是因为在同一个事务中进行修改或插入操作。因此不是幻读。 而如果在休眠的20s中在其他事务中执行了插入操作,依旧不会影响查询结果。因为快照读是基于MVCC(多版本并发控制)实现的。


http://lihuaxi.xjx100.cn/news/1892312.html

相关文章

vba实现CAD块属性导出到excel中

vba实现CAD与excel交互功能可提高工作效率,此例可供参考。 vba6运行程序前需在vba ide中工具栏下引用选项中引用excel库方可运行,vba7可直接运行。 代码如下: Sub 导出CAD块属性到excel()Dim Excel As ObjectDim elem As ObjectDim excelSheet As Obj…

利用闭包与高阶函数实现缓存函数的创建

缓存函数是一种用于存储和重复利用计算结果的机制。其基本思想是,当一个函数被调用并计算出结果时,将该结果存储在某种数据结构中 (通常是一个缓存对象)以备将来使用。当相同的输入参数再次传递给函数时,不再执行实际的计算,而是直…

微服务学习:Gateway服务网关

一,Gateway服务网关的作用: 路由请求:Gateway服务网关可以根据请求的URL或其他标识符将请求路由到特定的微服务。 负载均衡:Gateway服务网关可以通过负载均衡算法分配请求到多个实例中,从而平衡各个微服务的负载压力。…

利用Pytorch预训练模型进行图像分类

Use Pre-trained models for Image Classification. # This post is rectified on the base of https://learnopencv.com/pytorch-for-beginners-image-classification-using-pre-trained-models/# And we have re-orginaized the code script.预训练模型(Pre-trained models)…

PHP的协程是什么?

PHP 的协程是一种轻量级的线程(或任务)实现,允许在一个进程中同时执行多个协程,但在任意时刻只有一个协程处于执行状态。协程可以看作是一种用户空间线程,由程序员显式地管理,而不是由操作系统内核进行调度…

KVO KVC

KVO & KVC KVC KVC(Key-value coding)键值编码,就是指iOS的开发中,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。这样就可以在运行时动态地访问和修改对象的属…

场景的组织及渲染(二)

3.11 分页细节层次节点 分页细节层次节点(osg::PagedLOD)继承自osg::LOD 节点,它也是一个细节层次节点,用于实现动态分页加载,根据视点来加载所需要的,分页细节层次节点中还可以包含LOD节点。它与osg::LOD节点的区别是…

如何在Ubuntu的Linux系统上搭建nacos集群

官方给出的集群部署架构图 集群部署说明 (nacos.io)3个或3个以上nacos节点才能构成集群当前示例中包含3个nacos节点,同时一个负载均衡器代理3个nacos,本示例中负载均衡器可使用的是nginx 准备并安装好正常运行的nginx,本示例略准备并安装好正…