问题标签 [select-for-update]

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 投票
1 回答
129 浏览

mysql - MySQL 8.0.x 中令人困惑的 SELECT FOR UPDATE 行为

mysql 8.0.x

我们坚持混淆 SELECT ... LIMIT 1 FOR UPDATE SKIP LOCKED 的不同行为取决于主索引字段类型。

让我们考虑 2 个类似表的情况。

情况1:

案例2:

它们仅在字段类型上有所不同 - INT 和 BINARY。

插入 6 个 id 为 1 到 6 的项目。

运行 2 个并发事务。

交易2:

如果 id 是一个 INT 字段,则 select ... for update from transaction 2 执行时无需等待第一个事务提交。

如果 id 是二进制文件 select ... for update from transaction 2 在第二个事务提交后执行

第二种情况的 SHOW ENGINE INNODB STATUS 输出的一部分:

这是一个很大的惊喜...

谁能解释为什么mysql(innodb)在这些情况下表现如此不同。

0 投票
1 回答
120 浏览

mongodb - MongoDB - 选择文档进行更新 - 选择后没有其他操作修改同一文档

我有一份需要阅读和更新的文件。同时,很可能另一个进程正在执行相同的操作,这会破坏文档更新。

例如,如果进程 A 读取文档 d 并向其添加字段 'a' 并写入文档,并且进程 B 在进程 A 写入之前读取文档 d,并添加字段 b 并写入文档,则无论哪个进程将更改写出会得到他们的改变,因为它破坏了第一个写的人的改变。

我已经阅读了这篇文章以及其他一些关于 mongo 的非常复杂的事务文章。有人可以描述一个简单的解决方案吗 - 我还没有遇到让我对此感到满意的东西。

https://www.mongodb.com/blog/post/how-to-select--for-update-inside-mongodb-transactions

[更新]-此外,我正在尝试扩充可能尚不存在的文档。如果文档不存在,我需要创建它。我还需要阅读它来分析它。一个关键是“relatedIds”(一个数组)。如果在其中找不到 id,我会推送到该数组。如果文档不存在,我需要创建文档的另一种方法添加到单独的对象集合中。

[另一个更新 x2] --> 从我一直在阅读和从各种来源获得的内容 - 这是为此正确创建事务的唯一方法 - 是“findOneAndModify”文档以使用某些字段将其标记为脏肯定会更新,例如使用 objectId “锁定”(因为这永远不会导致 NO-OP - 即,它肯定会导致更改)。

如果另一个操作尝试写入它,Mongo 现在可以检测到该记录已经是事务的一部分。

因此,任何写入它的东西都会在其他操作上导致 writeError。然后我的事务可以慢慢地处理该记录并锁定它。当它写出并提交时,该记录绝对不会被其他任何东西触及。如果由于某种原因没有交易就无法做到这一点,那么我是否在这里以最简单的方式创建交易?

0 投票
1 回答
239 浏览

postgresql - PostgreSQL SELECT ... FOR UPDATE:并发长时间运行的查询会发生什么?

我想知道当两个事务SELECT ... FOR UPDATE并行执行查询时会发生什么。背景是我想使用SELECT ... FOR UPDATEwith实现一个作业队列SKIP LOCKED,如下所示:https ://vladmihalcea.com/database-job-queue-skip-locked/ 。但在本文中,查询非常简单。

具有两个事务 T1 和 T2 的示例(事务隔离级别设置为READ_COMMITTED):

  1. T1 开始
  2. T1 执行SELECT ... FOR UPDATE,搜索新行,这需要一些时间。
  3. T2开始
  4. T2SELECT ... FOR UPDATE使用与 T1 相同的 WHERE 子句和参数执行,这也需要一些时间。
  5. T1 终于找到所有行,锁定它们
  6. T1 开始更新行(例如,通过将它们标记为现在为 IN_PROGRESS)
  7. T2 终于找到行 => 现在会发生什么?

一些问题:

  1. 我假设 T1 将行锁定在原子操作中。这个对吗?
  2. 那么当 T2 最终找到它的结果集并尝试锁定它无法做到的行时?在这种情况下,T2 如何反应?我的假设是它会等到 T1 释放锁(当不使用 NOWAIT 时)。
  3. 如果 T2 在 T1 进行任何更改(例如将作业状态从 NEW 更改为 IN_PROGRESS)之前完成查询怎么办?两个事务可以找到相同的结果集吗?
  4. 如果 T1 以某种方式标记锁定的行(例如,通过将状态列从 NEW 更改为 IN_PROGRESS)并且 T2 查找原始状态(NEW),那么 T2 是否会SKIP LOCKED跳过标记的行?在 T1 进行更改后,T2 会重新评估它的结果集吗?
0 投票
0 回答
136 浏览

postgresql - 为什么在子查询中使用 'SELECT .. FOR UPDATE' 时 PostgreSQL 会返回过时的数据?

问题陈述

在 PostgreSQL 10.7 中,我有一个查询,它在子选择中使用 'SELECT .. FOR NO KEY UPDATE SKIP LOCKED' 并聚合另一个表中的行。在聚合表中同时使用 select 和 insert 执行两个事务我能够观察到插入成功时的状态,但 select 没有获取它并且未处理。

重现步骤

数据库设置:

测试用例:

请注意,在每次执行之前,请确保该balance表为空并且customer_balance_update有 1 个客户的行is_balance_updated = TRUE

我有 Java 应用程序,它有 2 个线程:第一个用于选择,第二个用于插入。在第一个线程中,我有以下伪代码(它作为一个事务执行,最后提交):

在第二个线程中,我有以下伪代码(它作为另一个事务执行,最后提交):

当两个线程完成时,我进行以下检查:

我认为我可以观察三种情况:

  1. 第一个线程中的 SELECT 更快,并且我已经锁定customer_balance_update了行,以便获取的余额0.0和带有 INSERT 的线程将仅在第一个线程提交后完成。在这种情况下,稍后选择的is_balance_updated标志应该为真。
  2. 在第二个线程中插入更快,在第一个线程中进行选择时,我跳过了锁定的行,没有选择任何内容。在这种情况下,获取的余额将是null,后来选择is_balance_updated的标志应该是真的。
  3. 甚至在第一个线程中的选择之前执行了第二个线程中的 INSERT,因此我选择了余额与1.0金额。后来选择is_balance_updated的标志应该是假的。

但是,我能够观察到第四个案例:

  • is_balance_updated的,并在第一个线程余额中捕获0.0

有谁知道这怎么可能?

SELECT .. FOR NO KEY UPDATE实际上,当我SELECT ... FROM balance分成两个顺序查询时,我无法重现上述问题。

0 投票
0 回答
70 浏览

django - 嵌套或多个 select_for_updates

我希望在多个不相关的对象上使用.select_for_update. 我需要用 包装每个电话transaction.atomic吗?我已经阅读了Django 文档和 postgres 的行锁定中的部分,但目前还不清楚。

这是一个人为的例子,但鉴于上述模型,我可以这样做吗?

还是我需要这样做?

0 投票
1 回答
239 浏览

postgresql - 为什么 SELECT FOR UPDATE SKIP LOCKED 时 PostgreSQL 会抛出并发更新错误?

我的 Java 应用程序通过 MyBatis 与 PostgreSQL 交互。

它从多个线程执行此请求

有时会得到ERROR: could not serialize access due to concurrent update。我记得这个错误发生在乐观更新的情况下,在这里我只使用 SELECT,甚至没有 UPDATE,并且无法解释发生了什么。

v_packet_unread- 是一个简单的视图,连接两个小表(每个 2 列),没有任何隐藏效果(如函数调用的触发器)。

你能帮我找出这种行为的原因以及如何避免这种行为吗?

例外:

版本:

0 投票
2 回答
67 浏览

postgresql - 如何在 Postgres 中选择更新表 A 中的一行和表 B 中的所有连接行?

我有一个表,它是一个任务队列,每个任务都需要独占访问多个资源。我希望我的查询选择一个不需要其他类似会话声称的资源的单个任务。

如果每个任务都必须在一个资源上工作,我会写这样的东西:

但是由于我有多个资源,我不得不以某种方式将它们全部锁定:

我不能限制为 1,因为我需要锁定resources.

在我看来,我也应该尝试锁定的所有resources,所以一定不是skip locked,而是nowait为了资源和skip locked为了tasks.

0 投票
0 回答
25 浏览

mysql - mysql RC多线程先搜索后删除,但有些搜索只返回1行

我使用mysql处理一些数据使用多线程,首先我搜索数据使用id范围,如:

结果 id 像 '1, 2, 3, 4, 5, ... 1001'。

其次,我将从下面的 sql 表中删除这些带有附加条件 confirm_state 的匹配数据:

所有的id范围没有交集。</p>

我发现有些线程需要返回1001行,但只返回第一行,我尝试了几次使用相同的代码和相同的数据,但左边的数据也不相同,共同的特点是只返回需要的批次计数的第一行全部返回。</p>

当我 for update为select sql添加时,它工作正常,

我怎么能理解会发生什么?

0 投票
1 回答
50 浏览

mysql - MySQL InnoDB - 在使用连接表进行锁定读取期间,即使没有选择任何列,连接的行也会被锁定吗?

我知道这与其他问题(例如, this one )非常相似,但我觉得我还没有找到一个答案,其中包括查询的 SELECT 部分如何影响锁的具体问题。

具体来说,我有两个表之间的父子关系,通过引用父主键的子表上的外键强制执行。在我正在开发的一个软件中,我想采用“路径”(父键+子键)并仅在子行是有效的“路径”时才返回子行。因此,查询将类似于:

我从我链接的另一个问题中了解到,如果我执行了SELECT *. 但是当我实际上没有返回任何父行的列时,我不确定这是否会改变。

文档说(强调我的):

对于 SELECT ... FOR UPDATE 或 SELECT ... LOCK IN SHARE MODE,为扫描的行获取锁,并为不符合包含在结果集中的行(例如,如果它们不符合WHERE 子句中给出的标准)。但是,在某些情况下,可能不会立即解锁行,因为结果行与其原始源之间的关系在查询执行期间丢失。

但我可以用多种方式来解释。“有资格”包含在结果集中是什么意思?我没有在我的SELECT不合格”中包含任何列的事实吗?还是“限定”仅指JOIN...ON, WHERE, 和HAVING子句?

谢谢!

0 投票
1 回答
138 浏览

db2 - DB2 for z/OS:CURSOR FOR UPDATE 锁定行为

我对 IBM DB2 for z/OS 的 CURSOR 中的 FOR UPDATE 子句有疑问。假设隔离级别光标稳定性(BIND 命令中的标准参数)。DB2 版本为 11。

我的第一个问题是:使用 FOR UPDATE 子句编码的 CURSOR 是否可以防止并发事务从读取 CURSOR 当前所在的行开始?我的第二个问题是:UPDATE ... WHERE CURRENT OF ... 语句是否检测到在打开 CURSOR 之后和从 CURSOR 结果集中获取更新行之前何时更改了更新行?

我在网上阅读了一些关于这些问题的相互矛盾的陈述。根据我(当前)的理解,FETCH 操作仅在获取的行上获取更新锁,因此并发事务至少可以读取同一行。U-Lock 仅在实际完成 UPDATE WHERE CURRENT OF CURSOR 的情况下才升级为 X-Lock(取决于应用程序逻辑)。但这让我感到困惑,因为它不会防止丢失更新现象(当允许并发进程在第一个进程中的更新完成之前读取值时,它会继续使用旧值进行处理并覆盖第一个进程的更新通过 CURRENT OF CURSOR 更新的进程)。