必须将SET TRANSACTION ISOLATION LEVEL放在BEGIN TRANSACTION之前且在任何数据操作语句之前执行,否则隔离级别不生效导致脏读;SQL Server按会话级生效,语句执行时即锁定当前级别,后续SET无法回溯修正。

SET TRANSACTION ISOLATION LEVEL 必须放在 BEGIN TRANSACTION 之前
很多存储过程里写了 SET TRANSACTION ISOLATION LEVEL READ COMMITTED,但依然出现脏读,原因几乎都是它被放在了 BEGIN TRANSACTION 后面。SQL Server 的隔离级别是会话级生效的,一旦语句开始执行(比如第一个 SELECT),就按当时已生效的级别走——哪怕后面才 SET,也救不回来。
常见错误现象:SELECT 读到了未提交的数据,而你明明在存储过程里写了 SET;或者两个并发调用中一个读到脏数据、另一个没读到,说明隔离级别没稳定继承。
-
SET TRANSACTION ISOLATION LEVEL必须在任何数据操作语句(SELECT、UPDATE、INSERT)之前执行 - 不能依赖调用方设置,必须在存储过程开头显式覆盖
- 嵌套调用时,上游没重置级别,下游也会继承——所以每个关键存储过程都得自己设
- 别用注释代替实际执行,生产环境没人帮你统一改连接配置
READ COMMITTED 不等于“不加锁”,它仍会阻塞写操作
设成 READ COMMITTED 只能防脏读,不代表读操作就无感。SQL Server 默认(READ_COMMITTED_SNAPSHOT = OFF)下,每次 SELECT 都会加共享锁(S 锁),直到语句结束才释放。这意味着:一个长耗时的 SELECT(比如全表扫描)会把后续 UPDATE 卡住,反过来也成立。
常见触发场景:报表类存储过程查大量历史数据,同时业务线程在更新同一张表的热点行,结果互相等待,报 deadlock 或长时间超时。
- 检查执行计划是否出现
Table Scan或Index Scan,优先优化为Index Seek - 避免在事务开头就
SELECT *一堆无关数据,锁持有时间直接拉长 - 如果读多写少且能接受快照一致性,考虑启用数据库级
READ_COMMITTED_SNAPSHOT ON -
READ COMMITTED SNAPSHOT不影响UPDATE/DELETE加排他锁,写冲突仍需排队
别乱用 SERIALIZABLE,它锁范围远超你想象
设 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 后,SQL Server 不只是锁住查询到的行,还会锁住“可能插入新行的间隙”。哪怕你只查 WHERE id = 123,只要索引上有 id BETWEEN 100 AND 150 的空隙,就可能全被锁住。高并发下极易死锁。
典型错误:订单状态更新存储过程用了 SERIALIZABLE,结果批量补单时 20 个线程全卡在 INSERT 上,死锁图里全是“等待键锁”。
-
SERIALIZABLE在绝大多数业务场景下都不该作为默认选择 - 真要强一致性,优先用
UPDLOCK + ROWLOCK配合BEGIN TRANSACTION锁具体行 -
UPDLOCK必须和事务绑定,单独用只是临时锁,毫无意义 - 索引缺失时,
ROWLOCK提示会被优化器忽略,照样升级成页锁甚至表锁
内存优化表或 ATOMIC 块需要额外处理隔离级别
如果你的存储过程操作的是内存优化表(Memory-Optimized Table),或者用了本机编译的 ATOMIC 块,SET TRANSACTION ISOLATION LEVEL 就不完全适用了。这类对象默认走快照隔离,且不支持传统锁机制。
常见问题:在显式事务里操作内存优化表,却没配 MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT = ON,结果报错或行为异常;或者跨容器事务(磁盘表 + 内存表混用)中隔离级别不一致,导致读取结果不可预期。
- 对内存优化表的
SELECT,必须显式加表提示如WITH (SNAPSHOT),否则可能失败 - 混合使用磁盘表和内存表时,不同表可指定不同隔离级别,例如
SELECT * FROM disk_table JOIN memory_table WITH (SNAPSHOT) -
ATOMIC块内所有语句自动包裹在单个事务中,无法中途改隔离级别 - 元数据查询(如
sys.tables)在SNAPSHOT或SERIALIZABLE下可能失败,因为元数据不支持版本控制
复杂点在于:隔离级别不是开关,而是和索引、执行计划、表类型、甚至连接池残留状态耦合在一起的。最容易被忽略的是——你以为设了就生效,其实它早被上游污染,或者根本没落到关键语句上。

















