相关疑难解决方法(0)

优化 Postgres 中的并发更新

我正在运行这样的并发 Postgres 查询:

UPDATE foo SET bar = bar + 1 WHERE baz = 1234
Run Code Online (Sandbox Code Playgroud)

每个查询都会影响固定的 K 行数,我找不到强制执行更新行顺序的方法,最终导致死锁。目前我通过手动执行订单来解决这个问题,但这意味着我必须执行比平时更多的查询,同时还将搜索复杂度从 O(log N + K) 提高到 O(K log N)。

有没有办法提高性能而不会最终容易陷入死锁?我怀疑如果Postgres 以扫描它们的相同顺序更新行,用(baz)索引替换(baz, id)索引可能会起作用,这是一种值得追求的方法吗?

postgresql deadlock locking update

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

尽管存在冲突,但仍会出现多行插入的死锁 DO NOTHING

设置

我有一个如下所示的批量插入功能set_interactions(arg_rows text)

with inserts as (
    insert into interaction (
        thing_id,
        associate_id, created_time)
    select t->>'thing_id', t->>'associate_id', now() from
    json_array_elements(arg_rows::json)  t
    ON CONFLICT (thing_id, associate_id) DO NOTHING
    RETURNING thing_id, associate_id
) select into insert_count count(*) from inserts;

-- Followed by an insert in an unrelated table that has two triggers, neither of which touch any of the tables here (also not by any of their triggers, etc.)
Run Code Online (Sandbox Code Playgroud)

(我这样包装它是因为我需要计算实际插入的数量,而没有“假行更新”技巧。)

该表interaction有:

  1. 只有一个约束:多列主键 (thing_id, associate_id)
  2. 没有索引
  3. 只有一个触发器:插入后,对于每一行。

触发器执行以下操作:

DECLARE …
Run Code Online (Sandbox Code Playgroud)

postgresql deadlock plpgsql upsert postgresql-9.6

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

我是否需要在 UPDATE 的 CTE 中显式 FOR UPDATE 锁?

在 Postgres 13 中,我有一个经常更新的表。然而,更新查询相当复杂,并且多次使用相同的值。因此,使用 CTE 似乎是一件非常合乎逻辑的事情。

一个简化的示例如下所示:

WITH my_cte AS (
    SELECT
          my_id,
          CASE WHEN my_value1 > 100 THEN 50 ELSE 10 END AS my_addition     
    FROM my_table      
    WHERE my_id = $1
)
UPDATE my_table
        SET my_value1 = my_table.my_value1 + my_cte.my_addition,
            my_value2 = my_table.my_value2 + my_cte.my_addition
FROM my_cte
WHERE my_table.my_id = my_cte.my_id
Run Code Online (Sandbox Code Playgroud)

现在我想知道:如果在SELECTCTE 和 之间UPDATE,表被另一个查询更新,my_value1从而发生变化,那么当发生这种情况时,were 的计算my_addition就会变得过时且错误,会发生什么UPDATE。会出现这样的情况吗?或者 Postgres 是否自动设置隐式锁?

如果 Postgres 在这里没有魔法,我需要自己处理它:FOR UPDATESELECTCTE 中做就足够了吗?

抱歉,如果我没有在这里说清楚:我并不是想“看到”这些并发修改,我想阻止它们,即一旦计算完成SELECT,没有其他查询可能会修改该行,直到计算UPDATE …

postgresql cte locking update postgresql-13

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

用于标识要删除的行的系统列“ctid”是否合法?

我有一个包含数亿行的表,我需要从中删除数据。

现有的索引是最有效的。

但是,我可以使用现有索引通过使用ctid值查找要删除的行:

DELETE FROM calendar_event WHERE ctid IN
(SELECT ctid FROM calendar_event WHERE user_id = 5 LIMIT 100 FOR UPDATE)
Run Code Online (Sandbox Code Playgroud)

ctid在这种情况下依赖 的风险是什么?我最糟糕的情况是删除错误的行。

postgresql performance delete concurrency postgresql-performance

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

有没有办法在 Postgres 中获取事务提交时间戳?

我有数据拉取功能,可以在 5 秒内根据modified_timestamp列从 Postgres 表中抓取所有数据。它的工作方式如下:

  1. SELECT * FROM my_table WHERE modified_timestamp > _some_persisted_timestamp
  2. _some_persisted_timestamp = CURRENT_TIMESTAMP
  3. 处理从步骤 1接收到的数据
  4. 睡眠 5 秒
  5. 转到步骤 1

其中modified_timestamp使用触发器更新(在任何行更新modified_timestamp变为 之后CURRENT_TIMESTAMP)。它工作正常,直到我注意到CURRENT_TIMESTAMPPostgres 实际上是事务开始时间戳并且一些更新丢失了。他们为什么会迷路?这很简单 - 在我执行查询时,SELECT * FROM my_table WHERE modified_timestamp > _some_persisted_timestamp一些更改已经发生,但modified_timestamp在更新_some_persisted_timestamp之前,因为事务仍在进行中。

当更新对其他事务可见(换句话说,事务提交时间戳)而不是 CURRENT_TIMESTAMP 或 clock_timestamp()时,可以通过在步骤 2 中 分配时间戳来轻松解决此问题。

我阅读了文档,但没有发现与事务提交时间戳相关的任何内容。你能不能给点建议?

顺便说一句,我知道逻辑解码,我知道这种机制在理论上更适合我的需求,但有一些实际问题不允许我使用它。

postgresql timestamp

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

Postgres 错误:元组同时更新

我有一个大表测试,其中 user_id 2 有 500000 条记录。所以我想以 100 条记录为单位删除这条记录,但出现错误。这是我的查询:

delete from test where test_id in (select test_id
from test where User_id = 2 limit 100 )
Run Code Online (Sandbox Code Playgroud)

错误:元组同时更新

这是什么问题。我怎样才能解决它。

postgresql postgresql-9.0

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

使用 WHERE 子句更新数组的第 n 个元素

我在 PostgreSQL 10 数据库product中有一个jsonb名为“元数据”的列的表。这是我第一次使用文档和 Postgres。jsonb值看起来像这样:

{
  "name": "l33t 衬衫",
  “价格”:“1200”,
  "数量": "60",
  “选项” : 
    {
      “类型”:“收音机”,
      "title": "颜色",
      “选择”:[
        {“价值”:“红色”,“价格”:“-100”,“数量”:“30”},
        {“价值”:“蓝色”,“价格”:“+200”,“数量”:“10”},
        {“价值”:“绿色”,“价格”:“+300”,“数量”:“20”}
      ]
    }
}

两个问题:

1.如何选择“opts”数组中的特定元素?

select metadata->'options'->'opts'->(element here) from product
where  metadata->'options'->'opts' @> '[{"value" : "blue"}]'
Run Code Online (Sandbox Code Playgroud)

2 、当售出一件或多件时,如何更新“数量”(减去当前的“数量”)?

对指南/注释的进一步链接表示赞赏。

postgresql update json postgresql-10

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

Postgres - 使用限制更新同一查询中的多行

我正在尝试使用以下语句更新表中的多行:

update test as t set
    column_a = c.column_a
from (values
    ('123', 1),
    ('345', 2)  
) as c(column_b, column_a) 
where c.column_b = t.column_b;
Run Code Online (Sandbox Code Playgroud)

但是,在我的数据库中 column_b 中的值不是唯一的(例如,多行可以有“123”)。我还有一个带有 DATE 类型的 column_c。对于更新语句中的每一行,我只希望上述更新发生在 column_c 中具有最新日期的行上,例如通过按日期对数据进行排序并使用 LIMIT 1。

因此,我试图将此查询与此处提供的答案结合起来。但是,我很难做到这一点。

postgresql postgresql-9.6

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

为什么单个 UPDATE 查询会出现死锁?

我有两个进程并行执行这样的代码:

begin;
update foos set unread=false where owner_id=123 and unread=true;
commit;
Run Code Online (Sandbox Code Playgroud)

这会导致死锁。

我对导致死锁的原因的理解就像这个问题中描述的场景,“交织” UPDATE 语句以不同的顺序更新两个不同的行。我不明白单个 UPDATE 语句如何导致死锁。我无法在我的开发环境中使用两个并行 psql 会话来复制死锁场景。我为什么不能复制它的猜测:

  1. 我误解了导致死锁错误的代码,并且每个事务中实际上有多个 UPDATE 语句
  2. “交织”方面正在发生,但“在”涵盖多行的 UPDATE 语句中,因此很难复制。

这个单一的 UPDATE 是否有可能造成死锁?

postgresql deadlock concurrency transaction update

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

一次(保证)更改后索引对“状态”字段的影响

介绍

我有一个 PostgreSQL 表设置作为队列/事件源。

我非常希望保留事件的“顺序”(即使在处理队列项之后)作为 e2e 测试的来源。

我开始遇到查询性能下降的问题(可能是因为表膨胀),并且我不知道如何有效地查询不断变化的键上的表。

初始设置

Postgres:v15

表DDL

CREATE TABLE eventsource.events (
    id serial4 NOT NULL,
    message jsonb NOT NULL,
    status varchar(50) NOT NULL,
    createdOn timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT events_pkey PRIMARY KEY (id)
);
CREATE INDEX ON eventsource.events (createdOn)
Run Code Online (Sandbox Code Playgroud)

抓取查询(伪代码)

BEGIN;  -- Start transaction

SELECT message, status
FROM eventsource.events ee
WHERE status = 'PENDING'
ORDER BY ee.createdOn ASC
FOR UPDATE SKIP LOCKED
LIMIT 10;  -- Get the OLDEST 10 events that are pending
-- I …
Run Code Online (Sandbox Code Playgroud)

postgresql index queue event query-performance

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

哪个更新数千个表行更快?

使用PostgreSQL v10.1.2 中的存储过程,哪种方法最快或哪种更好:检查行是否存在然后更新或尝试直接更新,但可能找不到与条件匹配的行?我需要检查很多条件相同的表,表是不是“非规范化”,我进行了几次测试,有时选项 1在其他情况下更快,选项 2 ...

选项1:

IF EXISTS ( SELECT  1
FROM   public.table1 
WHERE  column1 = 'oldvalue' )
THEN
   UPDATE public.table1
   SET   column1 = 'newvalue' , date_update= .... 
   WHERE  column1 = 'oldvalue';
END IF ;
Run Code Online (Sandbox Code Playgroud)

选项 2:

UPDATE public.table1
SET   column1 = 'newvalue' , date_update= ... 
WHERE  column1 = 'oldvalue';
Run Code Online (Sandbox Code Playgroud)

选项 3:

perform FROM   public.table1 WHERE  column1 = 'oldvalue' ;
if found then 
   UPDATE public.table1 SET column1='newvalue', date_update = ... WHERE column1 …
Run Code Online (Sandbox Code Playgroud)

postgresql performance stored-procedures update postgresql-10

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

编写一个查询,如果目标行上有锁,该查询将退出

是否可以编写一个UPDATE查询,如果它尝试更改的记录被另一个进程锁定(而不是等待锁被释放),则该查询将简单地退出?

我有一个进程应该更新表中的记录,有时这些记录会被锁定。更新这些记录是可取的,但不是必需的。如果记录正在使用中,我宁愿我的流程忘记更新并继续处理更重要的事情。

我当前的方法是将命令超时设置为 1 秒,但即使这也比我想要等待的时间长 - 正常更新需要不到一毫秒,因此等待一秒是一个主要开销。

postgresql locking update query-performance

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

带有子查询 LIMIT 1 的 UPDATE 返回多行

我正在努力处理随机返回多行而不是一行的查询。我正在使用 PostgreSQL 9.4.12

查询如下:

UPDATE folder as f set locked = 'locked', date_locked = current_timestamp 
from (
    SELECT * from folder as f2 
    WHERE f2.locked = 'available'
    LIMIT 1 FOR UPDATE ) as folderToUpdate 
WHERE f.id = folderToUpdate.id returning f.*
Run Code Online (Sandbox Code Playgroud)

id是主键。

它是通过一系列集成测试执行的。当我只执行上述查询的测试时,我没有任何问题。但是,当我执行所有测试时,我随机得到多行。你有什么建议吗?

postgresql concurrency update postgresql-9.4

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