【MySQL 进阶之路】事务隔离级别
事务隔离级别详解
数据库的事务隔离级别(Transaction Isolation Levels)决定了事务之间如何互相隔离,并发执行时不同事务之间的可见性。每个级别在数据一致性和并发性之间做出了不同的权衡。根据 SQL 标准,事务隔离级别有四种:读未提交、读已提交、可重复读、和串行化。
1.事务隔离级别概述
隔离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
---|---|---|---|
未提交读(Read Uncommitted) | 可能 | 可能 | 可能 |
已提交读(Read Committed) | 不可能 | 可能 | 可能 |
可重复读(Repeatable Read) | 不可能 | 不可能 | 可能 |
串行化(Serializable) | 不可能 | 不可能 | 不可能 |
读未提交(Read Uncommitted)
特点:
- 脏读(Dirty Read):事务 A 修改了某行数据但尚未提交,事务 B 可以读取该数据。如果事务 A 后续回滚,事务 B 读取的数据将是“假数据”。
- 不可重复读和幻读:事务 B 在读取数据后,事务 A 可能会修改这些数据,导致事务 B 获取到不同的数据。
示例:
事务 A 修改数据但未提交,事务 B 读取到的数据可能不一致:
-- 事务 A 修改数据但未提交
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
-- 事务 B 读取事务 A 修改但未提交的数据(脏读)
BEGIN;
SELECT balance FROM accounts WHERE user_id = 1;
读已提交(Read Committed)
特点:
- 不发生脏读:事务 B 只能读取事务 A 已提交的数据。
- 不可重复读(Non-repeatable Read):事务 B 多次读取同一数据时,可能读取到不同的值,因为事务 A 在事务 B 读取之后提交了数据。
示例:
事务 A 提交后,事务 B 读取到数据:
-- 事务 A 修改数据并提交
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
COMMIT;
-- 事务 B 读取已提交的数据
BEGIN;
SELECT balance FROM accounts WHERE user_id = 1;
COMMIT;
可重复读(Repeatable Read)
特点:
- 不发生脏读和不可重复读:事务 B 在同一事务中多次读取同一数据时,始终获取相同的数据。
- 可能发生幻读(Phantom Read):事务 B 在查询一个数据范围时,事务 A 插入或删除了符合条件的数据,导致事务 B 获取的结果集发生变化。
示例:
事务 A 和事务 B 的并发执行:
-- 事务 A 修改数据并提交
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
COMMIT;
-- 事务 B 读取已提交的数据(可重复读)
BEGIN;
SELECT balance FROM accounts WHERE user_id = 1;
COMMIT;
问题:如何避免幻读?
为了避免幻读,可以将隔离级别提高到串行化(Serializable),在这种级别下,所有的读操作都需要获取表级共享锁,阻止其他事务插入新数据。但这会极大地影响并发性,因此只有在对数据一致性要求极高的场景下才使用该隔离级别。
串行化(Serializable)
特点:
- 完全隔离:事务间互相隔离,仿佛每个事务是串行执行的,避免了脏读、不可重复读和幻读。
- 性能最差:由于严格的隔离,事务执行时需要锁定更多的数据,导致并发性极差,性能较低。
使用场景:
适用于需要保证高度一致性的场景,如资金转账、证券交易等。
-- 事务 A 执行操作
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
COMMIT;
-- 事务 B 执行查询时等待事务 A 完成(串行化)
BEGIN;
SELECT balance FROM accounts WHERE user_id = 1;
COMMIT;
2. MySQL 事务锁机制
在MySQL中,事务使用行级锁来实现数据的并发控制。行级锁的主要目的是允许多个事务同时修改不同的行,而不互相干扰。在执行SELECT、UPDATE等语句时,可以使用行级锁来阻止其他事务修改或读取同一行的数据。
锁类型 | 锁定对象 | 特点 |
---|---|---|
行级锁(Record Lock) | 锁定指定的行 | 只有对具体的行进行锁定,其他行可并发访问。 |
表级锁(Table Lock) | 锁定整个表 | 锁住整张表,其他事务不能访问该表的数据。 |
意向锁(Intention Lock) | 表示事务意图(行级锁) | 用来表明当前事务将会对某些行进行锁定,避免与其他事务的冲突。 |
原文地址:https://blog.csdn.net/ajsbxi/article/details/144314548
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!