type
status
password
date
slug
summary
category
URL
tags
icon
事务性
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
例如张三向李四转账
张三向李四转账会经过3个环节。1. 查询张三的余额(余够不够1000元)2. 张三的余额减1000元 3. 李四的余额增加1000元。这三个环节只能同时成功或者同时失败,否则可能出现张三余额减1000元,李四账户余额增加1000元失败的情况。
MySql事务性操作
在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行
COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。MYSQL 事务处理主要有两种方法:
命令 | 描述 |
BEGIN 或 START TRANSACTION | 显式地开启一个事务 |
COMMIT 或 COMMIT WORK | COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的 |
ROLLBACK 或 ROLLBACK WORK | 回滚会结束用户的事务,并撤销正在进行的所有未提交的修改 |
SAVEPOINT identifier | 在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT |
RELEASE SAVEPOINT identifier | 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常 |
ROLLBACK TO identifier | 把事务回滚到标记点 |
SET TRANSACTION | 用来设置事务的隔离级别。
InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE |
事务四大特性
事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
- 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性:在事务开始之前和事务结束以后,数据库的数据完整性约束、业务规则始终保持一致。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- 持久性:事务一旦提交或回滚,它对数据的修改就是永久的,即使发生数据库崩溃、服务器断电、硬件故障等意外情况,数据也不会丢失。
举例说明
id | name | balance(余额) |
1 | 张三 | 500 |
2 | 李四 | 1000 |
原子性与一致性
特性 | 是否满足? | 具体表现 |
原子性 | ✅ 满足 | 事务内的 “扣钱 + 加钱” 两个操作全部执行,无拆分、无回滚,完全符合 “要么全做、要么全不做”; |
一致性 | ❌ 不满足 | 执行后:张三余额 =-100(违反 “余额不能为负” 的业务规则),虽然总余额 = 1500(符合),但单账户数据非法; |
持久性
- 事务执行阶段:修改数据时,先写入「内存缓冲区(Buffer Pool)」,同时记录「WAL 日志(如 InnoDB 的 redo log)」到「日志缓冲区(Log Buffer)」;
- 此时数据还在内存,没写硬盘,但日志已记录 “要修改什么”;
- 事务提交阶段(关键):
- 第一步:将「日志缓冲区」的 WAL 日志刷到「硬盘日志文件」(这一步是同步的,必须完成才算提交成功);
- 第二步:后台线程异步将「内存缓冲区」的脏数据(已修改但未写硬盘的数据)刷到「硬盘数据文件」(表空间文件);
- 故障恢复阶段:如果提交后、数据刷盘前发生断电,重启数据库时,会读取 WAL 日志,重新执行日志中的修改操作,确保数据最终落地。
并发事务问题
问题 | 描述 |
赃读 | 一个事务读到另外一个事务还没有提交的数据 |
不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读 |
幻读 | 一个事务按照条件查询数据时,没有对应的数据行,但是插入数据时,又发现这行数据已经存在,好像出现了幻影 |
事务隔离
隔离级别 | 性能 | 脏读 | 不可重复读 | 幻读 | 适用场景 |
读未提交 | 最高 | ❌ 可能 | ❌ 可能 | ❌ 可能 | 极少用(如临时统计、非核心数据) |
读已提交 | 高 | ✅ 防止 | ❌ 可能 | ❌ 可能 | 多数互联网场景(如电商列表、新闻详情) |
可重复读 | 中 | ✅ 防止 | ✅ 防止 | ❌ 可能* | 金融、电商订单(需保证同一事务内数据一致) |
可串行化 | 最低 | ✅ 防止 | ✅ 防止 | ✅ 防止 | 核心交易(如转账、支付) |
隔离原理
隔离级别 | 读操作锁策略 | 写操作锁策略 |
读已提交(RC) | 无锁(MVCC 快照) | 行级 X 锁(提交释) |
可重复读(RR) | 快照读无锁 / MVCC;当前读加 S 锁 | 行级 X 锁 + 间隙锁(提交释) |
串行读(Serializable) | 行级 S 锁(事务释) | 行级 X 锁(事务释) |
行级X锁
命令与操作
命令 | 描述 |
TRANSACTION_ISLATION | 查看事务隔离级别 |
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE} | 设置事务隔离级别 |