【问题标题】:Unusual high number of exclusive locks in PostgreSQL databasePostgreSQL 数据库中异常的大量排他锁
【发布时间】:2018-01-31 09:37:02
【问题描述】:

总的来说,我对数据库设计和 PostgreSQL 很陌生,但我知道 Postgres 中行版本控制、事务和排他锁背后的一般概念(例如,this 文章给出了很好的概述)。

我目前的问题是 a) 我不知道为什么我的 PG 数据库日志文件中出现这么多排他锁,以及 b) 为什么这些锁是完全发生了。

我运行 PostgreSQL 10(+ PostGIS 扩展),在 5 个表 (200GB) 上有大约 3 亿行。我有大约 5 个脚本(4x PHP 和 1x Python Psycopg2)24/7 运行,可以进行大量插入(以及 DO UPDATECOALESCE,以防条目已经存在)。但是,据我了解,PHP Postgres 扩展在每个 SQL 查询之后和我的 Python 脚本中自动提交,增加提交并不会显着减少锁。我有几个动态更新行的触发器,但据我从日志文件中可以看出,它们不是锁定的原因。我的两个或多个脚本同时插入/更新同一行的情况通常很少见。

这是一个示例日志条目:

2018-01-31 01:04:02 CET [808]: [258-1] user=user1,db=maindb,app=[unknown],client=::1 LOG:  process 808 still waiting for ExclusiveLock on page 0 of relation 26889 of database 16387 after 1015.576 ms
2018-01-31 01:04:02 CET [808]: [259-1] user=user1,db=maindb,app=[unknown],client=::1 DETAIL:  Process holding the lock: 680. Wait queue: 1728, 152, 808.
2018-01-31 01:04:02 CET [808]: [260-1] user=user1,db=maindb,app=[unknown],client=::1 STATEMENT:  

                INSERT INTO "table1" (...) 
                VALUES (...)                                                                                                                                                                                              
                ON CONFLICT (...)                                                                                                                                                                                                                                                       
                DO UPDATE SET                                                                                                                                                                                                       
                ...;

我大约每 2-3 分钟就有一次类似的日志条目。他们有问题吗?它们究竟是什么意思,是锁最终解决了还是事务的数据丢失了?没有日志条目表明锁已解决或更新最终提交到数据库。

第二种频繁日志条目类似这样:

2018-01-31 07:22:16 CET [2504]: [16384-1] user=,db=,app=,client= LOG:  checkpoint complete: wrote 9999 buffers (3.8%); 0 WAL file(s) added, 0 removed, 7 recycled; write=269.842 s, sync=0.218 s, total=270.123 s; sync files=85, longest=0.054 s, average=0.002 s; distance=66521 kB, estimate=203482 kB
2018-01-31 07:22:46 CET [2504]: [16385-1] user=,db=,app=,client= LOG:  checkpoint starting: time  

这是否意味着解决所有锁定的 Auto-Vaccum 或 Auto-Commit?

我的一般问题:我应该关心并做某事还是干脆保持现状?

【问题讨论】:

  • 这意味着进程 680 设置了排他锁。您将不得不检查此过程的作用。它可能会做大量工作,或者有时数据库中存在潜在的延迟问题(例如,I/O 速度慢)。
  • 谢谢克劳斯。您能解释一下我如何找出进程 680 的作用吗?它似乎没有出现在日志中(例如“680...acquired ExclusiveLock”
  • 我发现this 页面解释了如何监控锁。看起来我的锁的存在时间都不超过几分钟,这表明它们根本没有问题
  • 您的日志行抱怨大约 1 秒。那么为什么现在分钟还可以呢?
  • 大多数锁在 1000 到 100.000 毫秒之间,但似乎有相当大的波动。上面的日志行只是一个有代表性的例子。

标签: php python postgresql locking plpgsql


【解决方案1】:

过了一会儿,我发现了导致这些锁的原因以及如何解决它们。所有独占锁都发生在数据库中的一个关系上: ...ExclusiveLock on page 0 of relation 26889 of database...

26889 是什么?

SELECT relname FROM pg_class WHERE OID=26889

结果:idx_post_hashtags

这都是由具有 Array (Text) 的特定列上的 GIN 索引引起的。此外,这个 GIN 索引是无用的,因为数组的长度是可变的,并且查找任何特定的数组值都不会从索引中受益。我放弃了它:所有独占锁都消失了!

仔细阅读日志真的很有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-09
    • 2010-10-27
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多