SQL Server中能否创建无锁快照事务?(永不提交仅回滚场景)
针对SQL Server的无锁临时数据分支方案(事务永不提交场景)
以下是几个完全符合你需求的方案,无需克隆数据库或修改原表架构:
方案1:优化快照隔离事务,规避锁等待
你之前的快照隔离思路方向是对的,问题出在快照隔离下写操作仍会获取排他锁,导致等待其他持久化事务。结合你“事务永不提交”的场景,可以这样优化:
- 开启事务前执行:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT; - 所有读操作直接读取快照版本,不会阻塞其他事务,也不会被其他事务阻塞
- 写操作前先通过快照读取目标行的当前版本,若发现该行被其他事务锁定,可直接跳过等待(比如给用户返回“数据正在被修改”的提示),而非强制等待锁释放
- 无论操作完成与否,最终强制执行
ROLLBACK TRANSACTION;,确保所有更改被丢弃
方案2:用tempdb会话级临时表做隔离
这是最轻量化的隔离方案,完全无锁且不影响原表:
- 针对用户需要操作的表,动态生成会话级临时表:
SELECT * INTO #Temp_OriginalTable FROM OriginalTable WHERE [过滤用户需要的数据];(只复制用户相关的数据集,而非全表,提升速度) - 用户的所有增删改操作都在临时表上执行,原表完全不受影响,也不会产生任何锁
- 由于你的Web应用跨请求保持连接,会话级临时表(#开头)会一直存在到连接关闭,完美适配跨请求的上下文
- 优势:零锁竞争、性能极高;唯一需要注意的是,如果用户操作关联表,需要同步生成对应的关联临时表
方案3:非持久化内存优化表(SQL Server 2016+)
如果你的SQL Server版本支持,这个方案性能最优且无锁:
- 创建独立的内存优化表,指定
DURABILITY = SCHEMA_ONLY——这意味着表结构会保留,但数据永远不会持久化到磁盘 - 将用户需要的数据集从原表导入到这个内存表中,所有操作都在内存表上进行
- 内存优化表采用乐观并发控制,完全没有传统的行锁,读写操作不会阻塞任何事务
- 无需修改原表架构,内存表是独立的,可提前创建或动态生成
方案4:短生命周期数据库快照
虽然你提到克隆数据库太慢,但SQL Server的数据库快照是增量式的,创建速度远快于全量备份:
- 创建快照:
CREATE DATABASE User_Snapshot ON (NAME = OriginalDB_Data, FILENAME = 'D:\Snapshots\User_Snapshot.ss') AS SNAPSHOT OF OriginalDB; - 用户连接到这个快照,开启显式事务进行操作——快照本身是只读的,SQL Server会自动将用户修改的页复制到tempdb中,形成临时可写版本
- 用户会话结束后,直接删除快照:
DROP DATABASE User_Snapshot; - 优势:完全镜像原库状态,无需同步表结构;缺点:创建快照的时间取决于数据库大小,适合用户量不大的场景
内容的提问来源于stack exchange,提问作者wischi
相关产品推荐
相关产品推荐

