Tôi đã có một lựa chọn trong SQL SERVER khóa toàn bộ bảng.
Đây là tập lệnh thiết lập (đảm bảo bạn không ghi đè lên bất cứ điều gì)
USE [master]
GO
IF EXISTS(SELECT 1 FROM sys.databases d WHERE d.name = 'LockingTestDB')
DROP DATABASE LockingTestDB
GO
CREATE DATABASE LockingTestDB
GO
USE [LockingTestDB]
GO
IF EXISTS(SELECT 1 FROM sys.tables t WHERE t.name = 'LockingTestTable')
DROP TABLE LockingTestTable
GO
CREATE TABLE LockingTestTable (
Id int IDENTITY(1, 1),
Name varchar(100),
PRIMARY KEY CLUSTERED (Id)
)
GO
INSERT INTO LockingTestTable(Name) VALUES ('1')
INSERT INTO LockingTestTable(Name) VALUES ('2')
GO
Mở một cửa sổ truy vấn mới và chạy giao dịch sau (có chờ trong đó):
USE [LockingTestDB]
GO
BEGIN TRANSACTION
SELECT * FROM LockingTestTable t WITH (UPDLOCK, ROWLOCK) WHERE t.Name = '1'
WAITFOR DELAY '00:01:00'
COMMIT TRANSACTION
--ROLLBACK
GO
USE [master]
GO
Và một cái khác sẽ chạy (đảm bảo chúng chạy cùng một lúc):
USE [LockingTestDB]
GO
SELECT * FROM LockingTestTable t WITH (UPDLOCK, ROWLOCK) WHERE t.Name = '2'
USE [master]
GO
Bạn sẽ nhận thấy truy vấn thứ hai sẽ bị chặn bởi truy vấn thứ nhất. Dừng truy vấn đầu tiên và thực hiện ROLLBACK và lần thứ hai sẽ hoàn thành.
Tại sao chuyện này đang xảy ra?
PS: Thêm chỉ mục không được nhóm (có phạm vi bảo hiểm đầy đủ) vào Tên sẽ khắc phục:
USE [LockingTestDB]
GO
CREATE NONCLUSTERED INDEX [IX_Name] ON [dbo].[LockingTestTable]
(
[Name] ASC
)
INCLUDE ( [Id]) WITH (STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Một lần nữa tại sao?