Ami*_*ari 3 sql-server sql-server-2016
我有一个具有这种结构的表:
CREATE TABLE [dbo].[a](
[id] [INT] IDENTITY(1,1) NOT NULL,
[aa] [INT] NULL,
CONSTRAINT [PK_a] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
然后创建新事务,然后更新所有记录,但不要提交。所以我有这样的事情:
BEGIN TRANSACTION
UPDATE dbo.a
SET aa=4
Run Code Online (Sandbox Code Playgroud)
在新会话中,我执行选择并获得结果!并在更新前查看旧值。
SELECT * FROM a
Run Code Online (Sandbox Code Playgroud)
当我想执行更新时,它会等待另一个事务提交。
我的问题是:
当我们在事务中更新一个表时,我们会在它上面创建一个锁,直到提交事务并且没有人可以从中选择,但为什么我可以呢?
我有 57 条记录,当我用这个检查 sql 上的锁定状态时:
SELECT resource_type, request_mode, resource_description
FROM sys.dm_tran_locks
WHERE resource_type <> 'DATABASE'
Run Code Online (Sandbox Code Playgroud)
我得到这样的结果:
resource_type request_mode resource_description
------------------- ------------------- -------------------
OBJECT IX
OBJECT IX
OBJECT IX
KEY X (d8295d9f49e9)
PAGE X 4:17377
PAGE X 4:17376
PAGE X 4:17379
PAGE X 4:17378
PAGE X 4:17381
PAGE X 4:17380
PAGE X 4:17383
PAGE X 4:17382
EXTENT X 4:17376
OBJECT Sch-S
PAGE X 4:17598
PAGE X 4:17599
PAGE X 4:17596
PAGE X 4:17597
PAGE X 4:17594
PAGE X 4:17595
PAGE X 4:17592
PAGE X 4:17593
PAGE X 4:17590
EXTENT X 4:17592
PAGE X 4:17591
PAGE X 4:17588
PAGE X 4:17589
PAGE X 4:17586
PAGE X 4:17587
PAGE X 4:17614
EXTENT X 4:17600
PAGE X 4:17615
PAGE X 4:17612
PAGE X 4:17613
PAGE X 4:17610
PAGE X 4:17611
PAGE X 4:17608
PAGE X 4:17609
EXTENT X 4:17608
PAGE X 4:17606
PAGE X 4:17607
PAGE X 4:17604
PAGE X 4:17605
PAGE X 4:17602
PAGE X 4:17603
PAGE X 4:17600
PAGE X 4:17601
PAGE X 1:1412
PAGE X 1:1413
PAGE X 1:1414
PAGE X 1:1415
PAGE X 1:1409
PAGE X 1:1410
PAGE X 1:1411
METADATA Sch-S object_id = -1277451255, index_id or stats_id = 4
METADATA Sch-M object_id = -1277451255, stats_id = 4
METADATA Sch-M object_id = -1277451255, stats_id = 3
METADATA Sch-S object_id = -1277451255, index_id or stats_id = 2
METADATA Sch-M object_id = -1277451255, stats_id = 2
METADATA Sch-S object_id = -1277451255, index_id or stats_id = 3
PAGE X 1:1647
PAGE X 1:1646
OBJECT Sch-S
OBJECT Sch-S
OBJECT Sch-S
OBJECT X
OBJECT Sch-S
OBJECT Sch-S
OBJECT Sch-S
KEY X (508b5231be99)
OBJECT Sch-S
OBJECT Sch-S
OBJECT Sch-S
OBJECT Sch-S
KEY X (e54dfecee7ff)
KEY X (bc73762086ca)
ALLOCATION_UNIT S
OBJECT Sch-S
KEY X (8da779ef3812)
KEY X (162836d95642)
EXTENT X 3:29752
PAGE X 3:29755
PAGE X 3:29754
PAGE X 3:29753
PAGE X 3:29752
PAGE X 3:29759
PAGE X 3:29758
PAGE X 3:29757
PAGE X 3:29756
EXTENT X 5:13736
PAGE X 5:13736
PAGE X 5:13737
PAGE X 5:13738
PAGE X 5:13739
PAGE X 5:13740
PAGE X 5:13741
PAGE X 5:13742
PAGE X 5:13743
PAGE X 3:29985
PAGE X 3:29984
PAGE X 3:29987
PAGE X 3:29986
PAGE X 3:29989
PAGE X 3:29988
PAGE X 3:29991
PAGE X 3:29990
EXTENT X 3:29984
PAGE X 3:29969
PAGE X 3:29968
PAGE X 3:29971
PAGE X 3:29970
PAGE X 3:29973
PAGE X 3:29972
PAGE X 3:29975
EXTENT X 3:29976
PAGE X 3:29974
PAGE X 3:29977
PAGE X 3:29976
PAGE X 3:29979
PAGE X 3:29978
PAGE X 3:29981
PAGE X 3:29980
PAGE X 3:29983
PAGE X 3:29982
EXTENT X 3:29968
OBJECT Sch-S
EXTENT X 3:29960
PAGE X 3:29961
PAGE X 3:29960
PAGE X 3:29963
PAGE X 3:29962
PAGE X 3:29965
PAGE X 3:29964
PAGE X 3:29967
PAGE X 3:29966
KEY X (7688db35ca94)
PAGE X 5:13966
PAGE X 5:13967
OBJECT Sch-S
EXTENT X 5:13976
PAGE X 5:13974
PAGE X 5:13975
PAGE X 5:13972
PAGE X 5:13973
PAGE X 5:13982
PAGE X 5:13983
PAGE X 5:13980
PAGE X 5:13981
PAGE X 5:13978
PAGE X 5:13979
PAGE X 5:13976
PAGE X 5:13977
OBJECT Sch-M
KEY X (8c6bc9fc53ee)
Run Code Online (Sandbox Code Playgroud)
如果您可以对另一个会话在 Read Committed 隔离中使用 X 锁的表运行 SELECT 查询,则您必须位于设置了READ_COMMITTED_SNAPSHOT的数据库中。
使用 READ_COMMITTED_SNAPSHOT Read Committed 查询不使用共享 (S) 锁。相反,如果查询遇到自查询开始以来被锁定或已被修改的行,它将从版本存储中读取该行的“最后一个已知的好”版本。
这就是为什么您会看到“更新前的旧值”。如果您需要其他会话的 SELECT 查询阻塞直到事务完成,您可以使用像 UPDLOCK 或 READCOMMITTEDLOCK 这样的锁定提示。