理解MySQL事务隔离
在实际开发中,MySQL 服务往往被多个客户端同时访问,这些访问通常以事务的形式进行。一个事务可能包含多条 SQL,原子性要求让用户要么看到执行前的状态,要么看到执行后的状态。当多个事务并发执行时,它们可能会互相影响,比如同时操作同一张表甚至同一行数据。为了让事务执行过程中尽量不受干扰,数据库引入了隔离性。而允许事务受到不同程度的干扰,就对应了不同的隔离级别。
这就好比试衣服:进试衣间需要完全隔离,而试鞋子可能就不需要那么严格的隔离。

四种隔离级别
标准定义了四种隔离级别,按隔离程度由低到高:
- 读未提交(Read Uncommitted):所有事务都能看到其他事务未提交的修改。这相当于几乎没有隔离,生产环境基本不用。
- 读提交(Read Committed):一个事务提交后,另一个事务才能看到它的修改。但这会导致同一个事务内多次读取同一数据可能得到不同的值,即不可重复读。
- 可重复读(Repeatable Read):MySQL 的默认级别。事务执行过程中看到的数据与事务开始时一致,其他事务的提交对当前事务不可见,只有都结束并重新启动后才能看到新结果。
- 串行化(Serializable):最高的隔离级别,事务一个接一个串行执行,效率最低但最安全。
隔离大多通过锁机制实现,不同级别使用的锁策略也不同。注意这几种级别主要针对读写并发,读读场景通常还是串行化处理。
如何查看和设置隔离级别
隔离级别可以在会话(Session)或全局(Global)级别设置。会话级只影响当前连接,全局级影响所有新连接(已存在的连接需重新登录才生效)。
查看当前隔离级别:
-- 查看会话级
SELECT @@session.tx_isolation;
-- 查看全局级
SELECT @@global.tx_isolation;
-- 简写,效果同上
SELECT @@tx_isolation;
设置语法:
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE};
例如,把当前会话设为串行化:
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 验证
SELECT @@global.tx_isolation;
@.tx_isolation;


