MySQL事务介绍

目录

一、事务定义

[二、核心特性 ACID](#二、核心特性 ACID)

[1. 原子性(Atomicity):要么全成,要么全败](#1. 原子性(Atomicity):要么全成,要么全败)

[2. 一致性(Consistency):数据始终合法](#2. 一致性(Consistency):数据始终合法)

[3. 隔离性(Isolation):并发执行不干扰](#3. 隔离性(Isolation):并发执行不干扰)

[4. 持久性(Durability):提交后永久生效](#4. 持久性(Durability):提交后永久生效)

三、事务的使用方法

1、核心语法

2、实用功能:保存点(Savepoint)

[3. 自动提交 vs 手动提交](#3. 自动提交 vs 手动提交)

[四、隔离级别:解决并发事务的 "冲突"](#四、隔离级别:解决并发事务的 “冲突”)

[1. 4 种隔离级别(从低到高)](#1. 4 种隔离级别(从低到高))

[2. 隔离级别相关问题](#2. 隔离级别相关问题)

[3. 隔离级别的查看与设置](#3. 隔离级别的查看与设置)

[五、隔离性的实现:锁与 MVCC](#五、隔离性的实现:锁与 MVCC)

[1. 锁机制:控制并发修改](#1. 锁机制:控制并发修改)

[2. MVCC:多版本并发控制(非锁定读)](#2. MVCC:多版本并发控制(非锁定读))

六、死锁

[1. 死锁产生的 4 个条件](#1. 死锁产生的 4 个条件)

[2. 避免死锁的方法](#2. 避免死锁的方法)


一、事务定义

事务是将一组 SQL 操作打包成的 "不可分割的执行单元",要么全部成功(提交) ,要么全部失败(回滚) ,绝不存在 "执行一半" 的中间状态。

最经典的例子就是转账:张三给李四转 100 元,核心是两条 SQL------ 张三余额 - 100、李四余额 + 100。事务能保证:要么两条 SQL 都执行成功,要么都不执行,不会出现 "张三钱少了但李四没收到" 的情况。

二、核心特性 ACID

ACID 是事务的四大核心特性,具体介绍如下。

1. 原子性(Atomicity):要么全成,要么全败

定义:事务中的所有操作是一个整体,不可拆分,失败则回滚到执行前状态。

实现原理:依赖 UndoLog(回滚日志) 。执行 SQL 前,会记录数据的原始状态到 UndoLog;若事务失败,通过 UndoLog 反向执行,恢复数据。

2. 一致性(Consistency):数据始终合法

定义:事务执行前后,数据库的完整性约束(如总额不变、字段格式合法)不会被破坏。

实现原理:一致性是 "结果",依赖原子性、隔离性、持久性共同保障。比如转账前后总额不变,就是一致性的体现。

3. 隔离性(Isolation):并发执行不干扰

定义:多个事务同时执行时,彼此不会相互影响,每个事务都能看到独立的数据视图。

实现原理:通过 锁机制MVCC(多版本并发控制) 实现,具体依赖隔离级别配置。

4. 持久性(Durability):提交后永久生效

定义:事务提交后,对数据的修改会永久存储,即使系统崩溃(断电、宕机)也不会丢失。

实现原理:依赖 RedoLog(重做日志) 。事务执行时,先将修改记录到 RedoLog;提交时,RedoLog 刷入磁盘;系统崩溃后,通过 RedoLog 恢复已提交的修改。

三、事务的使用方法

MySQL 中仅 InnoDB 存储引擎支持事务,核心语法和实操场景如下:

1、核心语法

sql 复制代码
-- 开启事务(二选一)
START TRANSACTION; 或 BEGIN;

-- 执行SQL操作(增删改)
UPDATE bank_account SET balance = balance - 100 WHERE name = '张三';
UPDATE bank_account SET balance = balance + 100 WHERE name = '李四';

-- 提交事务(成功则持久化)
COMMIT;

-- 回滚事务(失败则恢复)
ROLLBACK;

2、实用功能:保存点(Savepoint)

在事务执行的过程中设置保存点,回滚时指定保存点可以把数据恢复到保存点的状态:

sql 复制代码
START TRANSACTION;
UPDATE bank_account SET balance = balance - 100 WHERE name = '张三'; -- 张三余额900
SAVEPOINT sp1; -- 设置保存点
UPDATE bank_account SET balance = balance + 100 WHERE name = '李四'; -- 李四余额1100
SAVEPOINT sp2; -- 第二个保存点
UPDATE bank_account SET balance = balance - 100 WHERE name = '张三'; -- 张三余额800

ROLLBACK TO sp1; -- 回滚到保存点sp1,此时张三900、李四1000
COMMIT;

3. 自动提交 vs 手动提交

  • MySQL 默认 自动提交(autocommit=ON) :每条 SQL 单独构成一个事务,执行后自动提交。
  • 手动提交:设置**SET AUTOCOMMIT=0**(或 OFF),需手动执行 COMMIT/ROLLBACK。
  • 注意:只要用**START TRANSACTION**开启事务,无论 autocommit 是否开启,都必须手动 COMMIT 才会持久化;手动提交模式下,不用显示开启事务,执行修改操作后,提交或回滚事务时直接使用 commit 或 rollback;已提交的事务不能回滚。

四、隔离级别:解决并发事务的 "冲突"

当多个事务同时操作同一数据时,可能出现脏读、不可重复读、幻读等问题。隔离级别就是为了平衡 "并发性能" 和 "数据安全性" 的配置,MySQL 有 4 种隔离级别(InnoDB 引擎)。

1. 4 种隔离级别(从低到高)

按隔离水平高低排序如下:

2. 隔离级别相关问题

脏读:读到其他事务未提交的修改(如事务 A 改了数据但没提交,事务 B 读到了这个 "临时数据",之后 A 回滚,B 读的是 "脏数据")。

因为事务 A 是还没提交事务的,也就是它随时可能发生回滚操作,如果在上面这种情况事务 A 发生了回滚,那么 事务 B 刚才得到的数据就是过期的数据,这种现象就被称为脏读。

不可重复读:同一事务内,多次查询同一数据,结果不一致。

事务 A 先开始从数据库中读取数据,然后继续执行代码逻辑处理,在这过程中如果事务 B 更新了这条数据,并提交了事务,那么当事务 A 再次读取该数据时,就会发现前后两次读到的数据是不一致的,这种现象就被称为不可重复读。

幻读:同一事务内,多次查询同一范围数据,结果集行数不一致。

事务 A 先开始从数据库查询账户余额大于 100 万的记录,发现共有 5 条, 然后事务 B 也按相同的搜索条件也是查询出了 5 条记录,接下来,事务 A 插入了一条余额超过 100 万的账号,并提交了事务,此时数据库超过 100 万余额的账号个数就变为 6。 然后事务 B 再次查询账户余额大于 100 万的记录,此时查询到的记录数量有 6 条,发现和前一次读到的记录数量 不一样了,就感觉发生了幻觉一样,这种现象就被称为幻读

3. 隔离级别的查看与设置

sql 复制代码
-- 查看隔离级别(全局+会话)
SELECT @@GLOBAL.transaction_isolation; -- 全局
SELECT @@SESSION.transaction_isolation; -- 当前会话(默认REPEATABLE READ)

-- 设置隔离级别(全局/会话/仅下一个事务)
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- 仅下一个事务生效

五、隔离性的实现:锁与 MVCC

隔离级别的核心是 "隔离并发事务",而实现这一目标的两大技术是 锁机制MVCC

1. 锁机制:控制并发修改

InnoDB 的锁按粒度分为:

表级锁:锁定整个表,并发性能差(如 MyISAM 引擎默认)。

行级锁:锁定单条数据行或多行,并发性能好(InnoDB 默认,支持事务)。

按功能分为:

共享锁(S 锁):读锁,允许其他事务读取,但不允许写入(读不互斥)。

排他锁(X 锁):写锁,加锁后其他事务不能加任何锁(读写互斥、写写互斥)。

2. MVCC:多版本并发控制(非锁定读)

MVCC 是 InnoDB 实现 "读不加锁" 的关键,让读写并发不冲突:

**原理:**MVCC允许多个事务同时读取同一行数据,而不会彼此阻塞,每个事务看到的数据版本是该事务开始时的数据版本。这意味着,如果其他事务在此期间修改了数据,正在运行的事务仍然看到的是它开始时的数据状态,从而实现了非阻塞读操作。

  • 读操作时,生成 ReadView(数据快照),根据隔离级别选择可见的版本:
    • READ COMMITTED:每次查询生成新的 ReadView(导致不可重复读)。
    • REPEATABLE READ:事务内首次查询生成 ReadView,后续复用(解决不可重复读)。

六、死锁

由于每个事务都持有另⼀个事务所需的锁,导致事务⽆法继续进⾏的情况称为死锁。

1. 死锁产生的 4 个条件

  • 互斥访问:一个资源只能被一个事务占用。
  • 不可抢占:事务占有的锁不能被其他事务强制夺走。
  • 保持与请求:事务已持有一个锁,又请求其他事务的锁。
  • 循环等待:多个事务形成锁的循环依赖(如 A 等 B 的锁,B 等 A 的锁)。

以上四条是造成死锁的必要条件,必须同时满足,所以如果想要打破死锁,可以破坏以上四个条件之一,最常见的方式就是打破循环等待

2. 避免死锁的方法

  • 事务尽量短小,减少锁的持有时间。
  • 修改多表 / 多行时,按固定顺序操作(如先改 A 表再改 B 表,所有事务统一顺序)。
  • 避免长时间未提交的事务。
  • 合理设置隔离级别(如 READ COMMITTED 可减少死锁概率)。
相关推荐
m0_736919102 小时前
实战:用Python分析某电商销售数据
jvm·数据库·python
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.2 小时前
双主模式实现HTTP与MySQL高可用
网络协议·mysql·http
cheems95272 小时前
【MySQL】SQL调优:数据库性能优化(一)
数据库·sql·mysql
Rysxt_2 小时前
分布式数据库模式结构完整教程
数据库·分布式
远方16092 小时前
113-Oracle database26ai rpm安装和适配生产
大数据·数据库·sql·oracle·database
MMMMMMMMMMemory2 小时前
社区版oceanbase报警XA事务悬挂
数据库·oceanbase
OceanBase数据库官方博客2 小时前
APQO自适应参数化查询优化框架——OceanBase 校企联合研究成果
数据库·oceanbase·分布式数据库
Aloudata2 小时前
破解监管溯源难题:从表级血缘到算子级血缘的数据治理升级
数据库·数据挖掘·数据治理·元数据·数据血缘
OceanBase数据库官方博客2 小时前
中国联通软研院基于OceanBase引领运营商数智化转型新范式
数据库·oceanbase·分布式数据库