小编Fab*_*ied的帖子

我可以依赖按顺序读取 SQL Server 标识值吗?

TL;DR:下面的问题归结为:插入行时,在生成Identity值和锁定聚集索引中的相应行键之间是否存在机会窗口,外部观察者可以在其中看到更新的值 Identity并发事务插入的值?(在 SQL Server 中。)

详细版

我有一个 SQL Server 表,其中有一个Identity名为的列CheckpointSequence,它是该表的聚集索引(它还具有许多其他非聚集索引)的键。行由多个并发进程和线程(在隔离级别和没有)插入到表中。同时,有进程定期从聚集索引中读取行,按该列排序(也在隔离级别,关闭该选项)。READ COMMITTEDIDENTITY_INSERTCheckpointSequenceREAD COMMITTEDREAD COMMITTED SNAPSHOT

我目前依赖于读取过程永远不能“跳过”检查点的事实。我的问题是:我可以依赖这个属性吗?如果没有,我该怎么做才能使它成为现实?

示例:当插入标识值为 1、2、3、4 和 5的行时,读者在看到值为 4 的行之前不得看到值为 5 的行。测试表明该查询包含一个ORDER BY CheckpointSequence子句 (和WHERE CheckpointSequence > -1子句),当第 4 行被读取但尚未提交时可靠地阻塞,即使第 5 行已经提交。

我相信至少在理论上,这里可能存在竞争条件,可能会导致这个假设被打破。不幸的是,Identity关于Identity在多个并发事务的上下文中如何工作的文档并没有太多说明,它只说“每个新值都是基于当前的种子和增量生成的”。和“特定事务的每个新值都不同于表上的其他并发事务。” (微软)

我的推理是,它必须以某种方式工作:

  1. 事务开始(显式或隐式)。
  2. 生成身份值 (X)。
  3. 根据标识值在聚集索引上获取相应的行锁(除非锁升级开始,在这种情况下整个表都被锁定)。
  4. 该行已插入。
  5. 事务被提交(可能在很长时间之后),所以锁被再次移除。

我认为在第 2 …

sql-server concurrency identity locking

27
推荐指数
3
解决办法
4875
查看次数

检测 SQL Server 表中的更改

在我的应用程序中,有一个运行在 SQL Server 2012 上的数据库,我有一个作业(计划任务),它定期执行一个昂贵的查询并将结果写入一个表,稍后可以由应用程序查询。

理想情况下,我只想在自上次执行查询后发生更改时运行该昂贵的查询。由于源表非常大,我不能只选择所有候选列的校验和或类似的东西。

我有以下想法:

  • 每当我更改源表中的某些内容时,将上次更改的时间戳、“必须是查询”标志或类似内容显式写入跟踪表。
  • 使用触发器来做同样的事情。

但是,我真的很想知道是否有一种轻量级的方法来检测表上的更改,而无需我明确跟踪写入。例如,我可以获取ROWVERSION表格的“当前”或类似的信息吗?

sql-server sql-server-2012 change-tracking

15
推荐指数
3
解决办法
8万
查看次数