supabase:“prisma migrate dev”有时会超时(postgres 建议锁)

tlz*_*z13 2 postgresql timeout prisma supabase

我有一个supabase数据库(postgres 15.1.0.88)并且我使用prisma作为ORM(最新版本prisma@4.15.0)。当尝试使用 来应用迁移时prisma migrate dev,该命令大多数时候会返回一条超时错误消息:Timed out trying to acquire a postgres advisory lock

pnpm prisma migrate dev结果是:

Error: Error: P1002

The database server at `db.***.supabase.co`:`5432` was reached but timed out.

Please try again.

Please make sure your database server is running at `db.***.supabase.co`:`5432`.

Context: Timed out trying to acquire a postgres advisory lock (SELECT pg_advisory_lock(72707369)). Elapsed: 10000ms. See https://pris.ly/d/migrate-advisory-locking for details.
Run Code Online (Sandbox Code Playgroud)

在 supabase 的日志中,我也收到此错误消息,但不确定它是否与我的错误有关:

Event message
relation "_prisma_migrations" does not exist
Severity
ERROR

Timestamp
2023-06-11T09:48:31.165Z

Postgres Username
postgres

Session ID
***

Metadata
{
  "file": null,
  "host": "***",
  "metadata": [],
  "parsed": [
    {
      "application_name": null,
      "backend_type": "client backend",
      "command_tag": "PARSE",
      "connection_from": "***",
      "context": null,
      "database_name": "postgres",
      "detail": null,
      "error_severity": "ERROR",
      "hint": null,
      "internal_query": null,
      "internal_query_pos": null,
      "leader_pid": null,
      "location": null,
      "process_id": 17257,
      "query": "SELECT \"id\", \"checksum\", \"finished_at\", \"migration_name\", \"logs\", \"rolled_back_at\", \"started_at\", \"applied_steps_count\" FROM \"_prisma_migrations\" ORDER BY \"started_at\" ASC",
      "query_id": 0,
      "query_pos": 126,
      "session_id": "***",
      "session_line_num": 4,
      "session_start_time": "2023-06-11 09:48:30 UTC",
      "sql_state_code": "42P01",
      "timestamp": "2023-06-11 09:48:31.165 UTC",
      "transaction_id": 0,
      "user_name": "postgres",
      "virtual_transaction_id": "12/1941"
    }
  ],
  "parsed_from": null,
  "project": null,
  "source_type": null
}
Run Code Online (Sandbox Code Playgroud)

然后,大约 2:03 分钟后,我在 supabase postgres 日志中收到另外 2 条错误消息:

  • connection to client lost
  • canceling statement due to statement timeout(<- 为SELECT pg_advisory_lock(72707369) command)

当我等待一段时间后,该命令会再次起作用,一次甚至几次。同样的情况也发生在prisma migrate reset

小智 9

Prisma 使用带有幻数 ID 的PostgreSQL咨询锁72707369,如果前一个迁移仍处于连接状态且空闲,则会阻止新的迁移。这种锁仅在连接完全关闭并从表pg_stat_activity(显示当前实例中所有活动和空闲连接的内部 PostgreSQL 表)中删除时释放。

还有另一个表,pg_lock其中包含所有锁,通过简单的 SELECT 查询,您可以在objid列中找到带有幻数的锁72707369

因此,每次使用 Prisma 进行迁移时(特别是迁移步骤之后)都必须运行以下查询:

SELECT pg_terminate_backend(PSA.pid)
FROM pg_locks AS PL
    INNER JOIN pg_stat_activity AS PSA ON PSA.pid = PL.pid
WHERE PSA.state LIKE 'idle'
    AND PL.objid IN (72707369);
Run Code Online (Sandbox Code Playgroud)

pg_terminate_backend断开连接并释放每个关联的锁。这是硬编码为 Prisma 锁的幻数,因为我们不想删除每个当前的空闲连接。

了解更多信息: