标签: select-for-update

何时使用SELECT ... FOR UPDATE?

请帮我理解背后的用例SELECT ... FOR UPDATE.

问题1:以下是SELECT ... FOR UPDATE应该何时使用的一个很好的例子?

鉴于:

  • 客房[ID]
  • 标签[id,name]
  • room_tags [room_id,tag_id]
    • room_id和tag_id是外键

该应用程序希望列出所有房间及其标签,但需要区分没有标签的房间与已移除的房间.如果未使用SELECT ... FOR UPDATE,可能发生的情况是:

  • 原来:
    • 房间包含 [id = 1]
    • 标签包含 [id = 1, name = 'cats']
    • room_tags包含 [room_id = 1, tag_id = 1]
  • 线程1: SELECT id FROM rooms;
    • returns [id = 1]
  • 线程2: DELETE FROM room_tags WHERE room_id = 1;
  • 线程2: DELETE FROM rooms WHERE id = 1;
  • 线程2:[提交交易]
  • 线程1: SELECT tags.name FROM room_tags, tags WHERE room_tags.tag_id = 1 AND tags.id …

mysql sql sql-server transactions select-for-update

106
推荐指数
2
解决办法
8万
查看次数

Postgres SELECT ... FOR UPDATE in functions

关于在Postgres函数中使用SELECT ... FOR UPDATE行级锁定,我有两个问题:

  • 我选择哪一列是否重要?他们与我需要锁定然后更新的数据有什么关系吗?

    SELECT * FROM table WHERE x=y FOR UPDATE;
    
    Run Code Online (Sandbox Code Playgroud)

    VS

    SELECT 1 FROM table WHERE x=y FOR UPDATE;
    
    Run Code Online (Sandbox Code Playgroud)
  • 我不能在没有保存数据的情况下在函数中进行选择,所以我保存为虚拟变量.这似乎是hacky; 这是正确的做事方式吗?

这是我的功能:

CREATE OR REPLACE FUNCTION update_message(v_1 INTEGER, v_timestamp INTEGER, v_version INTEGER)
RETURNS void AS $$
DECLARE
    v_timestamp_conv TIMESTAMP;
    dummy INTEGER;
BEGIN
    SELECT timestamp 'epoch' + v_timestamp * interval '1 second' INTO v_timestamp_conv;
    SELECT 1 INTO dummy FROM my_table WHERE userid=v_1 LIMIT 1 FOR UPDATE;
    UPDATE my_table SET (timestamp) = (v_timestamp_conv) WHERE userid=v_1 AND version < v_version; …
Run Code Online (Sandbox Code Playgroud)

postgresql plpgsql postgresql-9.1 select-for-update

31
推荐指数
1
解决办法
4万
查看次数

SQLAlchemy - 选择更新示例

我正在寻找在SQLAlchemy中使用select for update的完整示例,但是没有找到一个谷歌搜索.我需要锁定单行并更新列,以下代码不起作用(永久阻塞):

s = table.select(table.c.user=="test",for_update=True)
# Do update or not depending on the row
u = table.update().where(table.c.user=="test")         
u.execute(email="foo") 
Run Code Online (Sandbox Code Playgroud)

我需要提交吗?我怎么做?据我所知,你需要:开始事务选择...用于更新更新提交

python sqlalchemy select-for-update

25
推荐指数
3
解决办法
2万
查看次数

Postgres:锁释放后 SELECT FOR UPDATE 看不到新行

尝试在我的应用程序中支持 PostgreSQL DB,发现了这种奇怪的行为。

准备:

CREATE TABLE test(id INTEGER, flag BOOLEAN);
INSERT INTO test(id, flag) VALUES (1, true);
Run Code Online (Sandbox Code Playgroud)

假设有两个并发事务 ( Autocommit=false, READ_COMMITTED ) TX1TX2

TX1:

UPDATE test SET flag = FALSE WHERE id = 1;
INSERT INTO test(id, flag) VALUES (2, TRUE);
-- (wait, no COMMIT yet)
Run Code Online (Sandbox Code Playgroud)

TX2:

SELECT id FROM test WHERE flag=true FOR UPDATE;
-- waits for TX1 to release lock
Run Code Online (Sandbox Code Playgroud)

现在,如果我在TX1中COMMIT,则 TX2 中的 SELECT 将返回空光标。

这对我来说很奇怪,因为 Oracle 和 MariaDB 中的相同实验导致选择新创建的行 (id=2)。

我在 …

postgresql locking transactions postgresql-11 select-for-update

8
推荐指数
1
解决办法
2471
查看次数

Postgres SELECT COUNT ... FOR UPDATE

这是我正在尝试做的伪代码:

rate_count = SELECT COUNT(id) FROM job WHERE last_processed_at >= ?

current_limit = rate_limit - rate_count
if current_limit > 0
  UPDATE job SET state='processing'
  WHERE id IN(
    SELECT id FROM job
    WHERE state='pending'
    LIMIT :current_limit
  )
Run Code Online (Sandbox Code Playgroud)

除了并发问题,我让它工作。当同时从多个会话运行时,两个会话都会选择并因此更新相同的内容:(

我可以通过在 SELECT 子查询中添加 FOR UPDATE 来获得第二个查询原子。但是我不能将 FOR UPDATE 添加到第一个查询中,因为聚合函数不允许 FOR UPDATE

我怎样才能使这件作品成为原子交易?

sql postgresql select-for-update

5
推荐指数
1
解决办法
1333
查看次数

select for update 如何适用于具有多行/结果的查询?

因此考虑到这笔交易:

select * from table_a where field_a = 'A' for update;
Run Code Online (Sandbox Code Playgroud)

假设这给出了多行/结果,数据库会立即锁定所有结果吗?或者它会一次锁定一行。

如果后者为真,这是否意味着并发运行此查询会导致死锁?

那么是否需要添加一个order by来保持顺序的一致性来解决这个问题?

sql postgresql select-for-update

4
推荐指数
1
解决办法
4053
查看次数

postgres:在冲突插入时更新一行并返回旧值

我需要一个查询来更新表中的一行,但如果 id 不存在,它会插入默认值。它还必须避免线程竞争条件。

我在这里找到了一个应该没问题的答案 /sf/answers/554957021/

使用此查询:

UPDATE tbl x
SET    tbl_id = 24
     , name = 'New Gal'
FROM  (SELECT tbl_id, name FROM tbl WHERE tbl_id = 4 FOR UPDATE) y 
WHERE  x.tbl_id = y.tbl_id
RETURNING y.tbl_id AS old_id, y.name AS old_name, x.tbl_id, x.name;
Run Code Online (Sandbox Code Playgroud)

所以我认为它应该在更新后返回旧值,并且应该防止线程竞争条件。

但是,如果该行不存在,我需要添加一个插入,并且这次还返回插入的值(旧值没有意义,因为它们不存在)。

所以基本上我需要做类似的事情

INSERT INTO tbl 
    (...) VALUES (...) 
    RETURNING ..., ... 
ON CONFLICT DO
UPDATE tbl x
SET    tbl_id = 24
     , name = 'New Gal'
FROM  (SELECT tbl_id, name FROM tbl WHERE tbl_id = …
Run Code Online (Sandbox Code Playgroud)

sql postgresql insert-update race-condition select-for-update

4
推荐指数
1
解决办法
2219
查看次数

涉及 SELECT FOR UPDATE 的死锁

我有几个查询的交易。首先,选择FOR UPDATE带锁的行:

SELECT f.source_id FROM files AS f WHERE
    f.component_id = $1 AND
    f.archived_at IS NULL
FOR UPDATE
Run Code Online (Sandbox Code Playgroud)

接下来,有一个更新查询:

UPDATE files AS f SET archived_at = NOW()
WHERE
hw_component_id = $1 AND
f.source_id = ANY($2::text[])
Run Code Online (Sandbox Code Playgroud)

然后有一个插入:

INSERT INTO files AS f (
    source_id,
    ...
)
VALUES (..)
ON CONFLICT (component_id, source_id) DO UPDATE
SET archived_at = null,
is_valid = excluded.is_valid
Run Code Online (Sandbox Code Playgroud)

我有两个应用程序实例,有时我会在 PostgreSQL 日志中看到死锁错误:

ERROR:  deadlock detected
DETAIL:  Process 3992939 waits for ShareLock on transaction 230221362; blocked by process …
Run Code Online (Sandbox Code Playgroud)

sql postgresql concurrency deadlock select-for-update

3
推荐指数
1
解决办法
3844
查看次数

选择更新行为

我很好地理解当使用 SELECT FOR UPDATE 并发生另一个 SELECT/UPDATE 时,行的更新会发生什么。但是,当使用 SELECT FOR UPDATE 发出两个请求时会发生什么。

例如:

  1. 线程 A启动一个事务,对一行执行 SELECT FOR UPDATE,检索一些信息并开始一个需要时间的 HTTP 请求。调用返回后,事务被提交并且会话被关闭
  2. 当 A 等待请求时,线程 B启动一个新事务并在同一行上执行 SELECT FOR UPDATE。它将检索信息并继续处理 HTTP 请求,还是等待线程 A 提交/执行更新,然后从行中检索数据。

我不关心一旦请求返回并且更新表的时间到来时会发生什么。用于更新的第二个将抛出或更新该行上的最后一个可能的数据。

但是实际的HTTP请求会由他们两个来完成吗?换句话说,在这种情况下 SELECT FOR UPDATE 是否可以被使用(滥用)作为线程同步机制?

postgresql concurrency multithreading thread-safety select-for-update

2
推荐指数
1
解决办法
299
查看次数

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. T2 使用SELECT ... 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 查找原始状态 …

postgresql concurrency transactions select-for-update

2
推荐指数
1
解决办法
1666
查看次数

用JDBC选择"for update"?

我想for update使用JDBC在Java中创建一个select语句,但不确定如何完成.

如果您不熟悉更新,可以在此处阅读 https://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE

例如,我有以下select语句

我的选择声明

select email from email_accounts where already_linked = false order by random() limit 1
Run Code Online (Sandbox Code Playgroud)

我的更新声明

UPDATE email_accounts set already_linked = true, account_link_timestamp = now() where email = ?
Run Code Online (Sandbox Code Playgroud)

在使用JDBC时如何使用JDBC完成这项工作for update

java postgresql jdbc select-for-update

1
推荐指数
1
解决办法
4211
查看次数