MSSQL里事务和锁到底怎么搭边,锁机制又是咋回事儿呢?
- 问答
- 2026-01-07 16:37:24
- 4
要搞清楚MSSQL里事务和锁是怎么搭边的,咱们得先弄明白它们各自是干嘛的,你可以把数据库想象成一个大家共用的仓库,里面放着各种货物(也就是数据),事务呢,就像是仓库管理员要执行的一个“任务包”,这个任务包里可能包含好几个小动作,比如从A货架拿点东西,再放到B货架,或者修改一下C货架上的货物标签,这个“任务包”有个核心规矩,叫做ACID,其中最关键的两个是“原子性”和“隔离性”。
“原子性”就是说,这个任务包里的所有小动作,必须要么全部成功,要么全部失败,不能只做一半,比如你的任务是“从张三账户转100块到李四账户”,这个任务包含两个动作:扣张三100块,加李四100块,绝对不能发生只扣了张三的钱,却没给李四加上这种事儿。
那“隔离性”是啥呢?它说的是,当很多个管理员(也就是很多个用户连接)同时在仓库里执行各自的任务包时,他们不能互相干扰,不能说我正看着张三的账户余额呢,另一个管理员唰一下把钱转走了,导致我看到的数儿一会儿一变,不准了,或者说,更严重的是,两个管理员同时都觉得能修改同一件货物,结果改乱了套。
(这里开始,锁就登场了,它俩就这么搭上边了)
SQL Server靠什么来保证这个“隔离性”,让多个同时进行的事务不打架呢?答案就是锁,锁就是事务用来“占坑”的工具。
当你的事务开始执行,比如你要修改“张三的账户余额”这条记录时,MSSQL就会自动替你这个事务在“张三账户余额”这条记录上挂一把“锁”,这把锁就像一个“正在施工,请勿触碰”的牌子,只要你的修改没完成(事务没提交),这把锁就一直挂着。
这时候,如果另一个事务也想来读或者修改“张三的账户余额”,它会发现上面已经有一把锁了,那它会怎么办?这就取决于它想干什么以及你挂的是什么锁了。
锁机制是咋回事儿呢?
MSSQL里的锁有很多种,但咱们就说最核心的两种,你就明白咋回事了:
- 共享锁(S锁):就像“只读锁”,当事务只是想看看数据(比如查询余额),而不修改时,它会申请一把共享锁,共享锁的特点是可以共享:好多事务可以同时在同一份数据上挂共享锁,大家一起看,没问题,一旦有共享锁存在,就不能再挂排他锁了(因为有人正在看,你不能当着大家面修改)。
- 排他锁(X锁):就像“独占锁”或“写锁”,当事务要修改数据时,它必须申请一把排他锁,排他锁的特点是排他:一个数据上一旦挂了排他锁,其他事务就不能再挂任何其他锁了(既不能再来修改,也不能来读取——这里说的不能读取是指不能获取共享锁来保证一致性读取,具体看隔离级别),也就是说,这把锁一挂,这块地儿就归你这个事务独占了,别人都得等着。
现在我们把事务和锁串起来看个例子:

假设有两个事务同时发生:
-
事务A:给张三发工资,要给他的余额加1000块。
-
事务B:查询张三的当前余额。
-
时刻1:事务A开始,它要修改张三的余额,于是MSSQL自动在“张三余额”这条记录上挂了一把排他锁(X锁),事务A开始进行加法计算。
-
时刻2:事务B开始,它想读取张三的余额,它试图在“张三余额”上挂一把共享锁(S锁)。
-
关键时刻:事务B发现记录上已经有一把强大的排他锁了,根据规则,排他锁不允许任何其他锁存在,事务B的共享锁申请被阻塞了(就是卡住了,等着),事务B必须乖乖地排队,等事务A干完活。

-
时刻3:事务A计算完毕,把新余额写进去,然后提交事务,事务一提交,它占有的所有锁(包括那把排他锁)就全部释放了。“正在施工”的牌子被摘掉了。
-
时刻4:事务B终于等到了,它成功获取了共享锁,读到了张三更新后的余额(1000块已经加上了),然后读完也释放了共享锁。
你看,通过锁这个机制,就保证了事务B不会读到事务A修改到一半的、不完整的余额(比如只加了500块?),这就实现了“隔离性”,如果没有锁,事务B可能读到一个乱七八糟的中间值,业务就乱套了。
锁的粒度和阻塞问题
锁不仅可以锁住一行记录,还可以锁更大或更小的范围,这叫锁粒度,比如可以锁整个表(表锁)、锁一个数据页(页锁)、锁一行(行锁),甚至锁一个键值(键锁),行锁是最精细的,并发性最好,因为只锁住要改的那一行,其他行别人照样可以访问,表锁最粗暴,一锁锁整个表,并发性差,但管理简单。
你可能会问,如果事务A一直不提交,事务B不就一直等下去吗?是的,这就叫阻塞,如果事务A因为某种原因(比如程序bug、网络问题)永远不提交,也不回滚,事务B就会永远等下去,这就是可怕的“死等”,更复杂的是死锁:事务A锁住了资源1,等着资源2;同时事务B锁住了资源2,却等着资源1,俩人互相等,形成了死循环,MSSQL有个死锁监视器,会定期检查这种情况,一旦发现,就会选择“牺牲”其中一个事务(通常是代价较小的那个),把它回滚,从而让另一个事务能继续执行。
简单总结:事务要靠锁来保证自己执行过程中的隔离性和数据正确性;锁是事务实现其ACID特性中“I”(隔离性)的核心机制。 你设置不同的事务隔离级别(比如读已提交、可重复读等),本质上就是指示MSSQL在什么时候加什么样的锁、锁多久,理解了它们之间这种“目的”和“手段”的关系,就抓住了核心。
本文由水靖荷于2026-01-07发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/76299.html
