数据库进阶-事务

本文详细介绍了数据库事务的概念,包括事务的ACID特性、四种隔离级别(读未提交、读已提交、可重复读、序列化)及其引发的问题(脏读、不可重复读、幻读)。通过实例展示了不同隔离级别下的行为,并讨论了不同隔离级别下的锁情况。内容涵盖了事务处理过程中的关键知识点,对于理解数据库并发控制具有重要意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事务


事务(Transaction)是由一系列对系统中数据进⾏访问与更新的操作所组成的⼀个程序执行逻辑单元。

在这里插入图片描述

1 事务的语法

  • 开启事务
    • start transaction;
    • begin;
  • 提交事务(使得当前的修改确认)
    • commit;
  • 回滚事务(使得当前的修改被放弃)
    • rollback;

2 事务的ACID特性

  • 原⼦性(Atomicity)

    事务的原⼦性是指事务必须是⼀个原子的操作序列单元。事务中包含的各项操作在⼀次执⾏过程中,只允许出现两种状态之一。

    (1)全部执行成功

    (2)全部执行失败 事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。

    事务执⾏过程中出错, 会回滚到事务开始前的状态,所有的操作就像没有发⽣一样。也就是说事务是⼀个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

  • ⼀致性(Consistency)

    事务的一致性是指事务的执⾏不能破坏数据库数据的完整性和一致性,一个事务在执⾏之前和执行之后,数据库都必须处以⼀致性状态。

    比如:如果从A账户转账到B账户,不可能因为A账户扣了钱,⽽B账户没有加钱。

  • 隔离性(Isolation)

    事务的隔离性是指在并发环境中,并发的事务是互相隔离的。

    也就是说,不同的事务并发操作相同的数 据时,每个事务都有各自完整的数据空间。

    ⼀个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务是不能互相干扰的。

  • 持久性(Duration)

事务的持久性是指事务⼀旦提交后,数据库中的数据必须被永久的保存下来。即使服务器系统崩溃或服务器宕机等故障。只要数据库重新启动,那么一定能够将其恢复到事务成功结束后的状态

3 事务的并发问题

  • 脏读:
    读取到了没有提交的数据, 事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。

  • 不可重复读:
    同⼀条命令返回不同的结果集(主要在update中体现),事务 A 多次读取同一数据,事务 B 在事务A 多次读取的过程中,对数据做了更新并提交,导致事务A多次读取同一数据时,结果不一致。

  • 幻读:
    重复查询的过程中,数据就发⽣了量的变化(主要在insertdelete中体现)。

4 事务的隔离级别

事务隔离级别脏读不可重复读幻读
读未提交(READ_UNCOMMITTED)允许允许允许
读已提交(READ_COMMITTED)禁止允许允许
可重复读(REPEATABLE_READ)禁止禁止可能会
顺序读(SERIALIZABLE)禁止禁止禁止

4种事务隔离级别从上往下,级别越高,并发性越差,安全性就越来越高。 ⼀般数据默认级别是读已提交或可重复读

  • 查看当前会话中事务隔离级别
#mysql8之前的语法
#select @@tx_isolation; 

#mysql8之后用以下语法查看事务隔离级别
select @@transaction_isolation;

MySQL默认隔离级别为可重复读

  • 设置当前会话中的事务隔离级别
#每个会话需要单独设置隔离级别,默认为可重复读,会话结束,隔离级别失效

set session transaction isolation level read uncommitted;	#读未提交,注意read和uncommitted之间没有下划线
#set session transaction isolation level read committed		读已提交
#set session transaction isolation level repeatable read	可重复读
#set session transaction isolation level serializable		顺序读

4.1 读未提交

读未提交,该隔离级别允许脏读取,其隔离级别是最低的。换句话说,如果一个事务正在处理理某一数 据,并对其进⾏了更新,但同时尚未完成事务,因此还没有提交事务;而与此同时,允许另一个事务也能够访问该数据。

脏读示例
时间点事务A(存款)事务B(取款)
T1开始事务一一
T2一一开始事务
T3一一查询余额(1000元)
T4一一取出1000元(余额0元)
T5查询余额(0元)一一
T6一一撤销事务
T7存入500元(余额500元)一一
T8提交事务一一
  • 打开两个会话窗口,设置事务隔离级别为read uncommitted;

在这里插入图片描述

  • 创建测试表
create table money(
	userid int,
    usermoney int);
insert into money values(1,1000),(2,1000);
select * from money;
  • 两个会话都能查看这张表

在这里插入图片描述

  • 两个会话分别开启事务

开启事务可以通过start transaction;或begin;开启

  • B事务查询余额并取出1000元

在这里插入图片描述

  • A事务查询余额

在这里插入图片描述

  • B事务进行回滚

在这里插入图片描述

  • A事务存入500,并提交事务,再次查询,出现结果与目标不一致的情况。

在这里插入图片描述

4.2 读已提交

读已提交是不同的事务执行的时候只能获取到已经提交的数据。 这样就不会出现上面的脏读的情况了。 但是在同一个事务中执行同一个读取,结果不一致

  • 设置会话隔离级别为读已提交(首先看解决脏读问题)

在这里插入图片描述

  • 开启事务

在这里插入图片描述

  • 事务B查询余额并取出1000元

在这里插入图片描述

  • 事务A查询余额

在这里插入图片描述

  • 事务B回滚,事务A存入500,提交,并查询,查询到的结果和目标是一致的,所以解决了脏读的问题

在这里插入图片描述

不可重复读问题示例
时间点事务A(存款)事务B(取款)
T1开始事务一一
T2一一开始事务
T3一一查询余额(2000元)
T4查询余额(2000元)一一
T5一一取出1000元(余额1000元)
T6一一提交事务
T7查询余额(1000元)一一
T8提交事务一一
  • 开启事务
    在这里插入图片描述

  • 事务A,B分别查询余额

在这里插入图片描述

  • 事务B取出1000元,提交事务

在这里插入图片描述

  • 事务A查询余额,在同一个事务里,两次查询结果不一致,出现不可重复读问题

在这里插入图片描述

4.3 可重复读示例

可重复读就是保证在事务处理理过程中,多次读取同一个数据时,该数据的值和事务开始时刻是一致的。 因此该事务级别限制了不可重复读和脏读,但是有可能出现幻读的数据。

  • 设置两个会话的隔离级别为repeatable read(解决了不可重复读问题)

在这里插入图片描述

  • 两个会话分别开启事务

在这里插入图片描述

  • 事务A,B分别查询余额

在这里插入图片描述

  • 事务B取出1000元,提交事务

在这里插入图片描述

  • 事务A查询余额,余额还是1000元,解决了不可重复读问题

在这里插入图片描述

  • 事务A提交事务,再次查询,结果变为更改后的值

在这里插入图片描述

幻读产生情况

幻读就是指同样的事务操作,在前后两个时间段内执行对同一个数据项的读取,可能出现不一致的结果。 诡异的更新事件

时间点事务A(存款)事务B(取款)
T1开始事务一一
T2查询当前所有数据开始事务
T3一一插入一条数据
T4一一提交事务
T5进行范围修改一一
T6查询当前所有数据一一
T7提交事务一一
  • 两个会话分别开启事务
  • 事务A查询当前余额

在这里插入图片描述

  • B事务插入一条数据,并提交事务

在这里插入图片描述

  • A事务进行范围修改,并查询数据,在一个事务中本来只想修改两条数据,结果发现多了一条数据,这就是幻读

在这里插入图片描述

4.4 顺序读示例

顺序读是最严格的事务隔离级别。它要求所有的事务排队顺序执⾏行行,即事务只能一个接一个地处理,不能并发。

  • 设置隔离级别为serializable

在这里插入图片描述

  • 事务A开启事务,并查询数据

在这里插入图片描述

  • 事务B开启事务,并执行插入语句,可以看见事务B并未执行,而在排队等待中

在这里插入图片描述

  • 只有当A事务提交或回滚之后,B事务才会执行

在这里插入图片描述

5 不同隔离级别锁的情况

  • 读未提交(RU): 有行级的锁,没有间隙锁。它与RC的区别是能够查询到未提交的数据。
  • 读已提交(RC):有行级的锁,没有间隙锁,读不到没有提交的数据。
  • 可重复读(RR):有行级的锁,也有间隙锁,每次读取的数据都是一样的,并且没有幻读的情况。
  • 序列化(S):有行级锁,也有间隙锁,读表的时候,就已经上锁了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

What大潘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值