问题标签 [snapshot-isolation]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
4732 浏览

sql-server - SQL Server 内存中 oltp 事务快照隔离

试图了解事务隔离级别如何在 SQL Server 内存优化表(内存中 oltp)上工作。

如果我执行以下查询:

显示错误消息:

仅自动提交事务支持使用 READ COMMITTED 隔离级别访问内存优化表。显式或隐式事务不支持它。使用诸如 WITH (SNAPSHOT) 之类的表提示为内存优化表提供支持的隔离级别。

现在,如果我通过添加表提示来修改查询,它可以工作:

但是,如果我通过更改事务隔离级别SET TRANSACTION ISOLATION LEVEL SNAPSHOT并删除表提示:

它再次显示错误消息不起作用:

当会话 TRANSACTION ISOLATION LEVEL 设置为 SNAPSHOT 时,无法访问或创建内存优化表和本机编译模块。

为什么它与表提示一起使用,并通过设置事务隔离级别

才不是?

更新:尝试设置MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOTON,仍然从上次查询中得到相同的错误:

当会话 TRANSACTION ISOLATION LEVEL 设置为 SNAPSHOT 时,无法访问或创建内存优化表和本机编译模块。

0 投票
0 回答
1355 浏览

sql-server - 数据库“tempdb”中的快照隔离事务失败,因为 statem 访问了对象

我在我的应用程序数据库上设置了 allow_snapshot_isolationREAD_COMMITTED_SNAPSHOT 。我有使用临时表的 SP。如果对 SP 进行并发访问,则会引发以下错误。没有一个 SP 有 alter temp table 命令,我的意思是它没有更新任何元数据。

相同的场景在 SQL 2008 R2 中运行良好,但在 SQL 2017 中却不行

“数据库'tempdb'中的快照隔离事务失败,因为该语句访问的对象自该事务开始以来已被另一个并发事务中的DDL语句修改。这是不允许的,因为元数据没有版本化。对元数据的并发更新如果与快照隔离混合会导致不一致。在批处理结束时检测到不可提交的事务。事务被回滚。

0 投票
1 回答
37 浏览

sql - SNAPSHOT 隔离如何读取 tempdb 的快照数据?

我试图了解 SNAPSHOT 隔离如何将数据拉入 tempdb。我知道由于 tempdb 中的行版本控制存在事务一致性,但我更好奇的是,这些数据首先是如何复制到 tempdb 中的。

文档更多地讨论了如何从快照中读取数据,但并未真正涉及如何拍摄快照。在我看来,快照将以序列化方式完成,因为这将是数据库在特定时间的最准确表示。但是,我知道比假设要好。

有谁知道这是如何工作的?

0 投票
1 回答
224 浏览

postgresql - Postgres SSI 行为

我试图了解 SSI 在 Postgres 中的实际行为方式。我的理解是,如果我有两个事务与同一个表交互,但事务没有与表中的相同行交互,那么不会发生异常。

但是,我正在运行以下测试,其中事务一执行以下操作:

当上面的第一个事务处于休眠状态时,我运行第二个事务:

在这种情况下,第二个事务只涉及 class = 2 的行,而第一个事务只涉及 class = 1 的行。但这会导致第一个事务失败,并出现以下异常:

供参考mytab非常简单,如下所示:

除了标准engine = psycopg2.connect设置之外,我还在运行上述代码之前使用此行设置事务隔离级别:

0 投票
0 回答
329 浏览

sql-server - 在活动事务上从 SNAPSHOT 切换隔离级别并运行 DDL

我想强制 MS SQL Server 使用 SNAPSHOT 隔离级别,但是在同一个事务中,我必须运行 DML 和 DDL 操作。据我所知,我们无法在具有 SNAPSHOT 隔离级别的事务中运行 DDL(大部分 DDL 操作)。

在文章https://docs.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-2017我们可以阅读

如果事务以 SNAPSHOT 隔离级别启动,您可以将其更改为另一个隔离级别,然后再返回到 SNAPSHOT。事务在第一次访问数据时开始。

所以我的想法是使用 SNAPSHOT 隔离级别运行 DML 事务,然后将事务切换到 READ COMMITTED 隔离级别,这是一个问题。

结果,我得到

所以看起来不可能,但我找不到不可能的严格答案。

我怀疑SET TRANSACTION ISOLATION LEVEL ...在一个打开的事务上正在改变锁定的行为,但不是整个事务类型。

0 投票
0 回答
45 浏览

sql-server - 使用数据库快照与快照隔离级别事务

我维护了一个 MVC 应用程序,其中包含一些长时间运行的批处理过程,用于发送新闻通讯、生成报告等。

我以前遇到过很多死锁问题,其中一个长时间运行的查询可能会在一行上持有锁,然后需要由另一个进程更新。

我最初想出的解决方案是有一个计划任务,它创建数据库快照,就像这样......

然后我的应用程序有一些逻辑可以找到最新的可用快照,并将其用于长时间运行的进程的只读连接,或者需要只读连接的任何其他地方。

当前设置功能完善且可靠。然而,依赖于该计划任务并不能让我开心。我可以想象,在未来的某个阶段,如果其他人在照顾这个项目,这可能是一个容易引起混淆的问题的来源。例如,如果将数据库移动到另一台服务器,并且未正确设置快照创建计划任务。

从那以后,我意识到我可以通过使用快照事务隔离来获得类似的结果,并避免管理数据库快照的创建和清理的所有额外复杂性。

但是,我现在想知道使用事务执行此操作与继续使用静态快照是否可能存在任何性能缺陷。

考虑以下场景。

该系统会定期向大约 20,000 个订阅者发送个性化的工作列表。对于这些订阅者中的每一个,它都会进行数据库查找以创建匹配的作业列表。

一直在做的事情是遍历完整的收件人列表,并且对于每一个...

  1. 打开与快照数据库的连接
  2. 运行查询以查找匹配的作业
  3. 关闭快照数据库连接

相反,它会执行以下操作...

  1. 打开与普通数据库的数据库连接(非快照)
  2. 创建快照隔离事务
  3. 运行查询以查找匹配的作业
  4. 关闭交易
  5. 关闭数据库连接

这实际上会转化为数据库服务器的更多工作吗?

具体来说,我想知道第 2 步涉及到什么。

从应用程序中消除复杂性是一件好事,但不会以牺牲性能为代价。特别是因为这个特定的过程已经是服务器密集型的,并且需要很长时间才能运行。

0 投票
2 回答
263 浏览

sql - 快照隔离行为。第一次查询时“触发”?

我正在做一些测试以尝试了解快照隔离的工作原理……但我没有。我在我的数据库中(对atmSET ALLOW_SNAPSHOT_ISOLATION ON不感兴趣)。READ_COMMITTED_SNAPSHOT然后我做以下测试。我将通过 [s1] 和 [s2] 标记标记不同的会话(在我的 ssms 中实际上是不同的选项卡),[s2] 是隔离会话,而 [s1] 模拟另一个非隔离会话。

首先,做一张桌子,让我们给它一行。@[s1]:

现在让我们开始一个孤立的事务。@[s2]:

插入另一行,@[s1]:

现在让我们看看隔离事务“看到”了什么,@[s2]:

奇怪的。隔离不应该从“Begin tran”那一刻起“开始计数”吗?在这里,它不应该返回 2....让我们再做一次。@[s1]:

@[s2]:

所以,这一次它按我的预期工作,并没有考虑最新的插入。

如何解释这种行为?隔离是否在第一次访问每个表后开始工作?

0 投票
0 回答
343 浏览

sql-server - 避免 SQL Server 中数据读取之间的死锁

我们在 SQL Server 中遇到“死锁”问题,其中不涉及显式锁,并且想知道如何绕过它们。

一些相关的背景信息:我们的应用程序非常古老且庞大。我们最近开始消除一些阻碍并发的问题,因此我们踏上了 SQL Server 上的死锁问题。我们没有资源来处理应用程序中的每个 select 语句,但正在寻找配置级别的更通用方法。

我们可以将一个示例性问题简化如下:基本上,我们有两个实体,EntityA并且EntityB。两者都映射到 SQL Server 架构中的各个表。在这两个实体之间,存在 am:n 关系,通过一个AToB表在数据库中映射,该表包含一些额外的上下文(即,AToB对于相同的AB.

在一个业务操作期间,一个新的实例AB被插入到数据库以及表中的多个条目AToB中。稍后在同一事务中再次读取所有这些数据(没有 for update)。在并行执行此操作时会发生死锁。这些死锁链接到AToB表。

比如说,我们有A1and B1,它们通过A1B1_1andA1B1_2A2and链接B2,它们通过A2B2_1and链接A2B2_2。我的猜测是会发生以下情况:

AToB现在,在对表的并发读取期间,t1获得了一个锁PAGE1t2获得了一个锁,PAGE2导致死锁。

第一个问题:这是发生僵局的合理解释吗?

第二个问题:在研究过程中给我的印象是,索引AToB.A可能会迫使 SQL Server 锁定表上的较少条目(甚至可能将其减少为一行,而不是页锁)。这是正确的吗?

第三个问题:我进一步的印象,这个问题可以通过snapshot-locking来解决。那正确吗?

我们尝试了这种方法,但是它把我们带入了下一个地狱循环:在业务事务期间,有一次业务标识符被分配给A. 这来自一个单独的表,它在As 中必须是唯一的。不可能通过数据库序列来分配它。我们的解决方案是通过第四个表上的select/来分配这个标识符。这是通过语句完成的。当采用快照锁定时,此锁定在获取期间被忽略,并且只会在提交期间导致乐观锁定异常。这导致我们updateIdentifierfor updatefor update

第四个问题:当使用快照锁定时,是否仍然有特殊事务仍然运行在悲观锁定上,或者是否可以告诉 SQL Server,某些表被排除在乐观锁定之外?

0 投票
1 回答
88 浏览

sql-server - 如果 RCSI 下不存在则插入

我有一个 READ_COMMITTED_SNAPSHOT_ISOLATION 设置为 ON 的数据库(无法更改)。

我在许多并行会话上将新行插入到表中,但前提是它们尚不存在(经典左连接检查)。

插入代码如下所示:

如果我在许多并行会话上运行它,我会得到很多重复的键错误,因为不同的会话会一遍又一遍地尝试插入相同的 OrderID。

这是预期的,因为 RCSI 下缺少共享锁。

这里推荐的解决方案(根据我的研究)是使用 READCOMMITTEDLOCK 提示,如下所示:

这有点工作,因为大大减少了重复的键错误,但(令我惊讶的是)并没有完全消除它们。

作为一个实验,我删除了 Destination 表上的唯一约束,并看到许多重复项在同一毫秒内进入表,来自不同的会话。

似乎尽管有表格提示,但我仍然在存在检查时得到误报,并且冗余插入触发。

我尝试了不同的提示(SERIALIZABLE),但它使情况变得更糟,并让我陷入了死锁。

我怎样才能使这个插入在 RCSI 下工作?

0 投票
1 回答
45 浏览

sql - 为什么要在设置 TRANSACTION ISOLATION LEVEL SNAPSHOT 之前检查 TRANCOUNT

使用快照隔离时,为什么在设置事务级别之前经常看到IF @@TRANCOUNT = 0?

即,在存储过程中: