18.1 SQL Server阻塞
SQL Server阻塞
简介
当两个会话试图同时更新同一数据时,会发生阻塞。
第一个会话锁定数据,第二个会话需要等待第一个会话完成并释放锁定。
结果,第二会话被阻止更新数据。一旦第一会话完成,第二会话恢复操作。
通常,当一个会话持有资源上的锁,而第二个会话试图获取同一资源上的冲突锁类型时,就会发生阻塞。
下图说明了SQL Server阻塞:
通常,第一个会话锁定数据的时间很短。当它释放锁时,第二个会话可以获取它自己对资源的锁并继续处理。
阻塞是基于锁的并发的SQL Server不可避免的设计特性。这是正常行为,不会影响服务器性能。
示例
先创建一个新的HR数据库,其中包含一个名为People
的表,用于演示:
DROP DATABASE IF EXISTS HR;
GO
CREATE DATABASE HR;
GO
USE HR;
CREATE TABLE People (
Id int IDENTITY PRIMARY KEY,
FirstName varchar(50) NOT NULL,
LastName varchar(50) NOT NULL
);
INSERT INTO People (FirstName, LastName)
VALUES ('Jane', 'Doe');
SELECT * FROM People;
People表有一行Id为1。
首先,开始一个事务并将Id为1的行的LastName
更新为“Smith”:
BEGIN TRAN;
UPDATE People
SET LastName = 'Smith'
WHERE Id = 1;
注意,我们没有在第一个会话中提交或回滚事务。
然后,创建一个新会话。在第二个会话中,将id为1的行的LastName
更新为“Brown”:
BEGIN TRAN;
UPDATE People
SET LastName = 'Brown'
WHERE Id = 1;
COMMIT;
由于第一会话中的事务正在进行,所以第二会话将等待第一会话完成。
如果使用SQL Server Management Studio,将看到以下消息:
Executing query....
要列出当前连接到SQL Server的所有进程,使用sp_who2
存储过程。
sp_who2;
输出显示系统进程ID(SPID)55被SPID 69阻塞。在本例中,第一个会话为69,而第二个会话为55。注意,你的SPID可能与本例中的不同。
第三步,返回第一个事务并提交:
COMMIT;
一旦第一个会话完成其事务,然后释放锁,第二个会话就也会完成。