MySQL 事务隔离性理论
在实际开发中,MySQL 服务往往同时被多个客户端进程或线程访问,且这些访问通常以事务的形式进行。一个事务可能包含多条 SQL 语句,这意味着它存在执行前、执行中和执行后的阶段。所谓的原子性,就是让用户层要么看到执行前的状态,要么看到执行后的状态;如果执行中出现问题,可以随时回滚。
但问题在于,当多个事务各自执行多条 SQL 时,它们之间可能会互相影响。比如多个事务同时访问同一张表甚至同一行数据。为了保证事务执行过程中尽量不受干扰,数据库引入了隔离性。而允许事务受不同程度的干扰,则对应了不同的隔离级别。
理解隔离性
SQL 操作本身具有原子性,update 和 select 谁先来谁先跑。但在并发环境下,每个事务都应该看到他应该看到的数据,而不是最新的数据。这就好比每个人只能看到自己时间线内的内容,不能看到出生前的历史,这就是隔离性的体现。
隔离性具体要隔离到什么程度?这就引出了隔离级别的概念。你可以把它想象成试衣服:进试衣间需要完全隔离,而试鞋子可能就不需要那么严格的隔离。

四种隔离级别
- 读未提交 (Read Uncommitted):所有事务都能看到其他事务未提交的修改结果。这相当于没有隔离,实际生产环境几乎不会用。
- 读提交 (Read Committed):一个事务 commit 之后,另一个事务才能看到这个事务的提交结果。
- 可重复读 (Repeatable Read):这是 MySQL 的默认隔离级别。相当于一个事务做完操作后,只要没关闭,在操作途中看不到其他事务的结果。只有两个事务都关闭并重新启动后,才能看到新结果。就像两个小孩在浑浊的水中潜水,必须浮出水面才能确认对方是否还在。
- 串行化 (Serializable):最高的隔离级别,一个事务执行完另一个才能执行。效率最低,但最安全。
隔离机制基本通过锁实现,不同级别使用的锁策略也不同。需要注意的是,上述四种级别主要关注的是读写并发场景,读读场景通常采用串行化处理。
隔离级别的设置和查看
隔离级别可以设置在会话(Session)级别或全局(Global)级别。
- 会话级:只影响当前事务,MySQL 默认使用会话的隔离级别。
- 全局级:对所有新连接的事务生效,修改后需重新登录才能生效。
查看当前隔离级别
-- 查看会话隔离级别
SELECT @@session.tx_isolation;
-- 查看全局隔离级别
SELECT @@global.tx_isolation;
-- 或者简写,效果同上
SELECT @@tx_isolation;
设置隔离级别
语法结构如下:
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED REPEATABLE READ SERIALIZABLE};


