事务与并发控制
在你使用数据库处理多条数据操作时,可能会希望“要么都成功,要么都失败”,不能只执行了一半。你也可能会遇到多个用户同时读写数据库的情况,如果处理不当,就可能造成数据错误、冲突或丢失。
为了解决这些问题,数据库引入了两个核心机制:事务(Transaction) 和 并发控制(Concurrency Control)。
这一节,你将学习:
- 什么是事务,事务的四大特性(ACID)
- 什么是并发访问,会带来哪些问题
- 常见的并发控制机制(锁、隔离级别等)
什么是事务?
事务(Transaction)就是一组操作的集合,这些操作被视为一个原子单元,要么全部成功,要么全部失败。
举个例子:你在银行用手机转账,系统会执行如下两个操作:
- 从你的账户扣钱;
- 给对方账户加钱。
如果只完成第 1 步,出错了,第 2 步没执行,那就尴尬了(钱没了😅)。事务的作用就是保证这两步操作要么都成功,要么都失败。
事务的四大特性(ACID)
事务有四个核心特性(Atomicity、Consistency、Isolation、Durability),简称 ACID。
特性 | 含义 |
---|---|
原子性(A) | 事务中的操作要么全部执行,要么全部不执行。 |
一致性(C) | 事务执行前后,数据必须保持一致状态。 |
隔离性(I) | 多个事务并发执行时,相互之间不会互相干扰。 |
持久性(D) | 事务一旦提交,对数据库的修改是永久性的,不会因宕机等原因丢失。 |
🌟 你可以记住:ACID 是事务的“守护神”,它保证了事务执行的正确性与稳定性。
并发访问下的问题
当多个用户或程序同时访问同一个数据时,数据库就进入了“并发操作”状态。并发本身没错,但会带来一些潜在的问题,例如 脏读、不可重复读以及 幻读 等。
脏读
脏读(Dirty Read)是指一个事务读取了另一个未提交事务的修改内容。
比如:你读取了某人账户余额是 1000,但其实对方还在进行转账操作,余额最终会变成 800。你看到的是“不确定”的数据。
不可重复读
不可重复读(Non-repeatable Read)是指在同一个事务中,两次读取同一条记录,结果却不一样。
比如:你两次查询商品价格,第一次是 100,第二次变成 120,说明别的事务在你执行中间修改了价格。
幻读
幻读(Phantom Read)是指在同一事务中,两次执行查询,结果集中突然出现或消失了“记录”。
比如:你第一次查“工资 > 5000”的员工有 10 人,第二次又查一次,变成 12 人了,说明别的事务插入了符合条件的新数据。
并发控制机制
为了解决上述问题,数据库系统提供了各种并发控制手段,主要包括两类:锁机制 和 事务隔离级别。
锁机制
锁(Lock)是防止数据被“同时修改”的关键手段,常见的锁类型有:
锁类型 | 含义 |
---|---|
共享锁(S) | 允许多个事务同时“读取”数据 |
排他锁(X) | 只允许一个事务“读取和修改”数据 |
行级锁 | 锁住一行数据,影响较小 |
表级锁 | 锁住整张表,影响较大 |
🌟 一般来说,读操作使用共享锁,写操作使用排他锁。
事务隔离级别
隔离级别(Isolation Level)决定了一个事务对“其他事务的可见程度”。SQL 标准定义了四种隔离级别:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(Read Uncommitted) | ✅ | ✅ | ✅ |
读已提交(Read Committed) | ❌ | ✅ | ✅ |
可重复读(Repeatable Read) | ❌ | ❌ | ✅ |
串行化(Serializable) | ❌ | ❌ | ❌ |
🌟 级别越高,数据越安全,但性能开销也越大。常用的是 读已提交 和 可重复读。
小结
通过本节内容,你了解了事务和并发控制的基本知识:
- 事务保证多步操作要么都成功,要么都失败,具有 ACID 四大特性;
- 并发问题包括脏读、不可重复读和幻读,需要重点防范;
- 通过锁机制(共享锁/排他锁)和隔离级别设置(读未提交到串行化),可以有效控制并发行为。
事务是数据库中保障数据一致性的核心机制,特别是在涉及银行、财务、电商等系统中,它的正确实现至关重要。