如何防止Postgres在并发单行upserts上陷入僵局?

时间:2019-05-04 10:31:35

标签: postgresql

我正在尝试找出导致我的应用程序出现问题的原因。问题的要点是postgres服务器日志在upsert查询中显示死锁,我不确定为什么会发生这种情况-我没有将upsert包裹在事务中,并且我的ups不超过一次1行。

我的表的结构如下:

postgres=> \d test_data_table
         Table "public.test_data_table"
 Column | Type  | Collation | Nullable | Default 
--------+-------+-----------+----------+---------
 id     | text  |           | not null | 
 data   | jsonb |           |          | 
Indexes:
    "test_data_table_pkey" PRIMARY KEY, btree (id)

和正在运行的upsert查询是这样的:

INSERT INTO test_data_table (id, data)
  VALUES ($1, to_jsonb($2::jsonb))
  ON CONFLICT (id) DO
    UPDATE SET id = $3, data = to_jsonb($4::jsonb);

我将问题简化为两个Java线程,它们仅同时运行upsert查询(如果相关,请使用HikariCP + Postgres JDBC驱动程序)。通过在代码中放入打印语句,我可以看到只有一个线程能够正确完成升序。当我使用this Postgres wiki page中的“阻止和阻止活动的合并”(具体地说,是包含应用程序名称的“替代”版本)时,得到以下输出:

 blocked_pid | blocked_user | blocking_pid | blocking_user |                                                             blocked_statement                                                             |                                                   current_statement_in_blocking_process                                                   |  blocked_application   |  blocking_application  
-------------+--------------+--------------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+------------------------+------------------------
        2576 | postgres     |         2575 | postgres      | INSERT INTO test_data_table (id, data)VALUES ($1, to_jsonb($2::jsonb)) ON CONFLICT (id) DO UPDATE SET id = $3, data = to_jsonb($4::jsonb) | INSERT INTO test_data_table (id, data)VALUES ($1, to_jsonb($2::jsonb)) ON CONFLICT (id) DO UPDATE SET id = $3, data = to_jsonb($4::jsonb) | PostgreSQL JDBC Driver | PostgreSQL JDBC Driver
(1 row)

在这一点上,我不确定可以采取什么措施有效地解决这个问题。

我已经看到:

  • This question(我认为不适用),因为我的用例一次只向上填充一行。
  • This question,出于与第一个原因相同的原因,我认为它不适用。

0 个答案:

没有答案