请帮我理解背后的用例SELECT ... FOR UPDATE
.
问题1:以下是SELECT ... FOR UPDATE
应该何时使用的一个很好的例子?
鉴于:
该应用程序希望列出所有房间及其标签,但需要区分没有标签的房间与已移除的房间.如果未使用SELECT ... FOR UPDATE,可能发生的情况是:
[id = 1]
[id = 1, name = 'cats']
[room_id = 1, tag_id = 1]
SELECT id FROM rooms;
returns [id = 1]
DELETE FROM room_tags WHERE room_id = 1;
DELETE FROM rooms WHERE id = 1;
SELECT tags.name FROM room_tags, tags WHERE room_tags.tag_id = 1 AND tags.id …
关于在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) 我正在寻找在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)
我需要提交吗?我怎么做?据我所知,你需要:开始事务选择...用于更新更新提交
尝试在我的应用程序中支持 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 ) TX1和TX2:
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
这是我正在尝试做的伪代码:
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
我怎样才能使这件作品成为原子交易?
因此考虑到这笔交易:
select * from table_a where field_a = 'A' for update;
Run Code Online (Sandbox Code Playgroud)
假设这给出了多行/结果,数据库会立即锁定所有结果吗?或者它会一次锁定一行。
如果后者为真,这是否意味着并发运行此查询会导致死锁?
那么是否需要添加一个order by来保持顺序的一致性来解决这个问题?
我需要一个查询来更新表中的一行,但如果 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
我有几个查询的交易。首先,选择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) 我很好地理解当使用 SELECT FOR UPDATE 并发生另一个 SELECT/UPDATE 时,行的更新会发生什么。但是,当使用 SELECT FOR UPDATE 发出两个请求时会发生什么。
例如:
我不关心一旦请求返回并且更新表的时间到来时会发生什么。用于更新的第二个将抛出或更新该行上的最后一个可能的数据。
但是实际的HTTP请求会由他们两个来完成吗?换句话说,在这种情况下 SELECT FOR UPDATE 是否可以被使用(滥用)作为线程同步机制?
postgresql concurrency multithreading thread-safety select-for-update
SELECT ... FOR UPDATE
我想知道当两个事务并行执行查询时会发生什么。背景是我想使用SELECT ... FOR UPDATE
with实现一个作业队列SKIP LOCKED
,如下所示: https: //vladmihalcea.com/database-job-queue-skip-locked/。但在本文中,查询非常简单。
具有两个事务 T1 和 T2 的示例(事务隔离级别设置为READ_COMMITTED
):
SELECT ... FOR UPDATE
,搜索新行,这需要一些时间。SELECT ... FOR UPDATE
与 T1 相同的 WHERE 子句和参数执行,这也需要一些时间。一些问题:
我想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
?
postgresql ×9
sql ×5
concurrency ×3
transactions ×3
deadlock ×1
java ×1
jdbc ×1
locking ×1
mysql ×1
plpgsql ×1
python ×1
sql-server ×1
sqlalchemy ×1