数据库事务

数据库事务

一、事务的基本特性 (ACID)

ACID不仅是四个特性,更是一个有机整体 :一致性(Consistency)是最终目的 ,原子性、隔离性、持久性是实现这一目的的三个核心手段。

特性 核心含义 经典案例解析(A向B转账100元)
原子性 (Atomicity) 事务是最小工作单元,其包含的所有操作要么全部成功,要么全部失败回滚,不允许只执行一部分。 A账户-100和B账户+100这两个操作必须捆绑在一起。系统不会出现A的钱扣了,B的钱没到账的中间状态。
一致性 (Consistency) 事务的最终目的 。确保数据从一个正确的状态 转换到另一个正确的状态,满足所有预定义的业务规则和约束。 1. 数据状态一致: 转账后,总金额不变(A+B总额从600变为600)。 2. 业务约束一致: A账户余额不能为负(若A只有90元,则转账事务应失败);主键必须保持唯一等。
隔离性 (Isolation) 多个并发事务对同一数据进行操作时,事务之间是隔离的,不应相互干扰。这是防止并发操作导致数据不一致的关键。 当A向B转账的同时,如果C也向B转账,两个事务如果没有良好隔离,可能导致B的最终余额错误(如应是300,却得到200)。隔离级别定义了"干扰"的程度。
持久性 (Durability) 事务一旦提交,其对数据的修改就是永久性的,即使系统发生故障(如宕机),数据也不会丢失。 转账成功后,A=400,B=200的状态被持久化保存到存储介质。系统重启后,这个结果依然存在,不会回滚到转账前的状态。

核心逻辑链: 通过 原子性 确保操作完整,通过 隔离性 排除并发干扰,通过 持久性 固化结果,最终共同达成 一致性 这个根本目标。


二、事务的隔离级别

隔离级别解决的核心问题是:一个事务在操作数据时,如何看待其他并发事务对同一数据的修改?

隔离级别从低到高,数据安全性递增,但并发性能递减。

隔离级别 中文名 解决的问题 允许的并发问题 实现关键(以MySQL为例)
读未提交 (Read Uncommitted) 脏读 无 脏读、不可重复读、幻读 几乎不加锁,直接读最新数据(包括未提交的)。
读已提交 (Read Committed) 不可重复读 脏读 不可重复读、幻读 每次SELECT都生成新的 Read View ,只读取已提交的数据。Oracle默认级别。
可重复读 (Repeatable Read) 幻读(部分) 脏读、不可重复读 幻读(在MySQL的InnoDB中,通过间隙锁已基本解决) 事务开始时生成一个Read View ,在整个事务期间复用,保证每次读到的数据快照一致。MySQL默认级别。
串行化 (Serializable) - 脏读、不可重复读、幻读 无(但性能最低) 通过强制事务串行执行来实现最高隔离。

三、隔离级别引发的三大问题详解

通过"并发转账"或"重复查询"场景理解:

  1. 脏读 (Dirty Read)

    • 现象: 事务A读到了事务B尚未提交的修改。

    • 危害: 如果事务B最终回滚,事务A读到的就是根本不存在的"脏数据"。

    • 场景: 发生在读未提交级别。

  2. 不可重复读 (Non-repeatable Read)

    • 现象: 在同一个事务A内,两次读取同一条记录,得到的值不同。

    • 原因: 在两次读取之间,该记录被另一个已提交的事务B修改了。

    • 场景: 发生在读已提交级别,在可重复读级别中被解决。

  3. 幻读 (Phantom Read)

    • 现象: 在同一个事务A内,两次执行相同的条件查询 ,第二次查询结果集比第一次多出(或减少)了一些行(像出现了幻觉)。

    • 原因: 在两次查询之间,另一个已提交的事务B插入(或删除)了满足该查询条件的新数据。

    • 注意: 幻读关注的是结果集行数的变化 (新增/删除),而不可重复读关注的是同一行数据内容的变更。

    • 场景: 是可重复读隔离级别理论上存在的问题。但MySQL的InnoDB引擎通过MVCC + 间隙锁的机制,在很大程度上避免了幻读。


四、核心面试思路总结

  1. 不要死记硬背: 结合"转账"等业务场景理解ACID和隔离级别,理解其为什么存在 以及解决了什么问题。

  2. 理解默认级别:

    • MySQL (InnoDB): 默认可重复读,并利用MVCC和锁机制有效防止了幻读。

    • Oracle / SQL Server: 默认读已提交。

    • 能解释为什么不同数据库默认级别不同(权衡数据一致性与并发性能)。

  3. MVCC是理解关键: 读已提交和可重复读级别的不同行为,本质上是生成Read View(一致性视图)的时机不同。

    • 读已提交:每次SELECT都生成新Read View → 总能读到最新已提交数据 → 不可重复读。

    • 可重复读:事务开始时生成一个Read View并复用 → 整个事务看到同一个数据快照 → 可重复读。

  4. 理论与实践结合: 知道如果当前数据库的隔离级别不满足业务需求(如:在读已提交下需要避免不可重复读),应用层该如何做 (例如:使用SELECT ... FOR UPDATE加锁)。

  5. 区分概念: 清晰区分脏读、不可重复读、幻读 这三种现象,以及它们与丢失更新等问题的区别。

最终答案的层次: 从ACID的定义出发,阐述其内在联系,再过渡到为实现隔离性而设立的不同级别,用场景解释各级别的问题,并提及底层实现机制(如MVCC),展现出对事务全面、深入的理解。

相关推荐
IvorySQL7 小时前
PostgreSQL 日报|修复截断 zstd 备份检测(10 月 9 日)
数据库·postgresql
刘胡子大叔7 小时前
SQL 脚本的导入顺序
数据库·sql
代码什么用8 小时前
Spring对IoC的实现
数据库·spring
hz5678910 小时前
涉密视频会议设备配置指南:终端、音视频采集与配套设施选型
服务器·网络·数据库·安全·实时音视频·信息与通信·智能硬件
广州浮点FLOATLIC10 小时前
许可证服务器迁移后软件打不开:研发 IT 怎样定位连接问题
linux·服务器·数据库
程序员Sunday10 小时前
MySQL 为什么使用 B+ 树索引?把范围查询、回表和覆盖索引连起来
数据库·mysql
半杯咖啡半行码10 小时前
Qt开发实战:数据库、MV 模式、QProcess与串口通信全攻略
数据库·qt
Yyyyyy~10 小时前
[ Mysql ] 库的操作
mysql
小米里的大麦11 小时前
16 MySQL 事务
数据库·mysql
西柚小萌新11 小时前
【LLM&&AI应用开发 八股文】--4.3.Agent智能体(下)
java·开发语言·数据库