自学内容网 自学内容网

【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)!