基于 ARM 架构的 M1 Mac 在 Big Sur 上出现了 Postgres 错误

28
自从我买了一台新的基于ARM架构的M1 MacBook Pro之后,我一直在遇到严重而持续的PostgreSQL问题(psql 13.1)。无论我使用Rails服务器还是Foreman,我都会在浏览器和终端中收到错误消息,例如 "PG::InternalError: ERROR: could not read block 15 in file "base/147456/148555": Bad address"、"PG::Error (invalid encoding name: unicode)" 或 "Error during failsafe response: PG::UnableToSend: no connection to the server"。奇怪的是,我经常可以重复刷新浏览器以使事情正常工作(直到它们再次出现问题)。
我知道所有与基于ARM的M1 Mac相关的配置挑战,这就是为什么我已经以多种方式多次卸载和重新安装了Homebrew和Postgres等所有东西(包括Rosetta,不包括Rosetta,使用“arch -x86_64 brew”命令,使用Postgres应用程序而不是Homebrew安装)。我在随机留言板上遇到过几个遇到同样问题(也是在新Mac上)并没有任何运气的人,这就是为什么我不愿意相信它是一个驱动器损坏问题的原因。(我也多次运行了Disk Utility FirstAid检查;它说一切都健康,但我不知道它有多可靠。)
我使用thoughtbot平等性来将我的开发环境数据库与当前在生产中的内容同步。当我运行"development restore production"时,我会在终端中看到数百行输出,这些输出看起来像下面的输出(这是在下载完成之后但在继续创建默认值、处理数据、序列设置等之前立即出现的)。我相信这是问题的根源,但我不确定解决方案是什么:
pg_restore: dropping TABLE [table name1]
pg_restore: from TOC entry 442; 1259 15829269 TABLE [table name1] u1oi0d2o8cha8f
pg_restore: error: could not execute query: ERROR:  table "[table name1]" does not exist
Command was: DROP TABLE "public"."[table name1]";
pg_restore: dropping TABLE [table name2]
pg_restore: from TOC entry 277; 1259 16955 TABLE [table name2] u1oi0d2o8cha8f
pg_restore: error: could not execute query: ERROR:  table "[table name2]" does not exist
Command was: DROP TABLE "public"."[table name2]";
pg_restore: dropping TABLE [table name3]
pg_restore: from TOC entry 463; 1259 15830702 TABLE [table name3] u1oi0d2o8cha8f
pg_restore: error: could not execute query: ERROR:  table "[table name3]" does not exist
Command was: DROP TABLE "public"."[table name3]";
pg_restore: dropping TABLE [table name4]
pg_restore: from TOC entry 445; 1259 15830421 TABLE [table name4] u1oi0d2o8cha8f
pg_restore: error: could not execute query: ERROR:  table "[table name4]" does not exist
Command was: DROP TABLE "public"."[table name4]";

还有其他人遇到过这个问题吗?非常感谢任何解决方案的建议。谢谢!

编辑:我在一台较旧的MacBook Pro上(也运行Big Sur)复制了相同的问题,因此似乎与M1无关,但可能与Big Sur有关。


1
“Bad address”是与EFAULT相关联的消息,这意味着Postgres将无效指针传递给read()或类似的系统调用。这表明Postgres或某个关联库中存在相当低级别的错误,或者由于不良硬件、过热等原因导致了内存损坏。 - Nate Eldredge
1
谢谢,Nate。有没有可靠的方法来诊断是硬件问题还是低级Postgres(或相关库)的错误? - Carl
1
我在我的ARM MacBook Air上遇到了同样的问题,但并不总是出现。如果我重新启动Postgres,错误就不会再一段时间内弹出。这很可能是一个问题,直到有本地ARM版本出现才能解决。 - AndSmith
1
是的,在我的 M1 Mac Mini 上也遇到了同样的问题。我通过 homebrew 安装了 Postgres 的本地版本。 - Ersin Akinci
1
我的 M1 Mini 也有同样的问题,无论是本地还是 x86。奇怪的是,重新启动 Postgres 有时似乎可以消除错误。 - Josh Dzielak
显示剩余9条评论
4个回答

13

解决此问题的明确方法:

在尝试其他答案中的所有解决方法后,我仍然偶尔会遇到此错误。即使倾倒并还原数据库,切换到M1本机postgresql,运行各种维护脚本等。

经过对postgresql.conf进行大量调整,唯一可靠地解决这个问题的方法是:

在postgresql.conf中更改:

max_worker_processes = 8

max_worker_processes = 1

在进行了这个更改后,我对之前常出错的数据库进行了各种测试,但它再也没有显示相同的错误。以前,在处理大约2000万条记录的数据库上运行的提取例程会在处理100-200万条记录后出现错误地址。现在它可以完成整个过程。

显然,减少并行工作人员的数量会有一定的性能损失,但这是我找到的唯一可靠和永久解决此问题的方法。


2
好知道,但它似乎更像是一种变通方法而不是修复。听起来像是Postgres有一些竞争缺陷,如果竞争只有一个参与者就可以避免这个问题 :) - Nate Eldredge
1
感谢Nate--我调整了答案,因为它明显是一种解决方法,而不是修复方法,因为会有性能损失。顺便说一下,我通过psql日志中的一些“无法映射动态共享内存段”错误被引导到减少并行工作进程。在M1 Mac上,显然存在着关于内存访问和postgres并行工作进程的问题--这是这台机器唯一令人沮丧的事情。 - Ben Wilson

2

更新 #2:

调整 WAL Buffer 等设置可以延长错误出现的时间,但无法完全消除。最终我重新使用 Homebrew 安装了新的 Apple Silicon 版本的 Postgres,然后对现有数据库(出现错误)进行了 pg_dump,并将其恢复到新的安装/集群中。

有趣的是:pg_restore 无法恢复数据库中的一个索引,并在恢复过程中记录了此问题(否则已完成)。我的直觉是,该索引的损坏或其他问题导致了 Bad Address 错误。因此,我对此问题的最终建议是执行 pg_dump,然后使用 pg_restore 而不是 pg_dump 来恢复数据库。pg_restore 显然标记了 pg_dump 没有标记的这个问题,写入了一个不带故障索引的干净数据库。

更新:

尝试了几种解决方法后,包括完整的受影响数据库的 pg_dump 和恢复,仍然遇到了这个问题。虽然一些修复措施似乎可以延长出现错误的时间(特别是增加共享缓冲区内存),但没有证明是永久性的修复。

话虽如此,通过对 postgres 邮件列表的进一步研究,我发现这个 "Bad Address" 错误可能会与 WAL(预写式日志)问题同时发生。因此,我现在在我的 postgresql.conf 文件中设置了以下内容,显著增加了 WAL 缓冲区大小:

wal_buffers = 4MB

自那以来,我就没有遇到过这个问题了(再次敲木头)。

这是有道理的,因为 wal_buffer 大小默认按比例增加共享缓冲区大小(如上所述,增加共享缓冲区大小提供了临时缓解)。无论如何,直到我们得到关于这个 bug 的确定性消息之前,可以尝试其他方法。


在 M1 MacBook Air 上偶尔出现了这个确切的问题:ERROR: could not read block 和各种排列组合的 Bad Address

我在 postgres 论坛上读到,这个问题可能会在虚拟机设置中出现。因此,我认为这是 Rosetta 引起的。即使您使用了 postgres 的通用版本,您也很可能仍在某些附属进程中使用 x86 二进制文件(例如,在我的情况下是 Python)。

无论如何,以下是解决问题的方法(至少目前是这样):重新索引数据库

注意:您需要从命令行重新索引,而不是使用 SQL 命令。当我尝试使用 SQL 重新索引时,我一遍又一遍地遇到了同样的 Bad Address 错误,并且重新索引从未完成。

当我使用命令行重新索引时,进程完成了,Bad Address 错误没有再次出现(再次敲木头)。

对于我来说,只需要执行以下操作:

reindexdb name_of_database

将一个12GB的数据库转换大约需要20-30分钟。现在不仅不会再出现这些错误,而且数据库看起来更加迅速。只希望在Rosetta中重复读取/写入/创建索引时不会再遇到此问题。我不确定为什么这样可以解决问题...也许在M1 Macs上创建的索引容易出现损坏?也许由于Rosetta的交互导致索引因写入或访问而变得损坏?


感谢您的回复,@Ben Wilson。不幸的是,当我尝试重新索引时,出现了以下错误:"reindexdb: error: processing of database "database_name" failed: ERROR: could not read block 22 in file "base/16384/16600": Bad address"... 我尝试多次运行它,但块编号一直在增加。然后我重启了postgres并再次尝试,它似乎做了一些事情(终端没有任何反馈表示发生了任何事情,有时这可能是好消息)。然而,在本地主机:3000中浏览应用程序后,我开始再次看到错误。 - Carl
还有一件事可以尝试:增加共享缓冲区内存。在我执行重新索引之后,我能够避免这个问题几天,但它最终会再次发生(不如以前频繁)。这个(以及这个线程:https://www.postgresql.org/message-id/4DFB32F4020000250003E7E2%40gw.wicourts.gov)让我想到可能存在内存问题。更改postgresql.conf文件中的**shared_buffers**行。我的设置为128MB--我将其设置为512MB,问题尚未再次发生。您可以使用以下命令找到您的conf文件:psql -U postgres -c 'SHOW config_file' - Ben Wilson
1
感谢您的跟进,@Ben——我非常感激。我尝试将shared_buffers增加到512MB,但这也没有改变任何东西...对我产生影响的是我的雇主昨天给我发送了一台基于英特尔的MacBook。它安装了Catalina(我还没有更新到Big Sur),在Postgres中使用相同的数据库时一切都运行顺畅。抱歉——我知道这不能解决其他遇到此问题的人的问题 :/ - Carl
对于其他遇到此问题的人,再更新一下...在增加了共享缓冲区后,问题又出现了。显然,在M1 Mac上,与postgres相关的某些东西会随着时间的推移而退化(在重新启动服务器后一段时间内不会出现此问题)。最新尝试:将postgres数据库导出为pgdump(pg_dump db_name > ~/db_name.dump),然后重新导入它(pg_restore)。自从我这样做以来,问题就没有再次发生了(抱着好运的心态)。 - Ben Wilson
1
这与负载有关,因为我在常规开发过程中没有遇到此问题,但在自动化测试套件期间(并行运行并在较长时间内每秒重新创建数据库)会出现此问题 - 因此它可能与负载、清空或其他原因有关,目前还不确定。 - Kamil Tomšík
显示剩余2条评论

2

Big Sur Beta 11.3是否可能修复了此问题?

自从在我的Mac mini M1上使用MacPorts安装PostgreSQL 13以来(现在是PostgreSQL 13.2),我一直遇到与OP相同的问题。

我会看到could not read block错误:

  1. 偶尔在运行特定查询时
  2. 总是在编译多个查询的R Markdown书籍时
  3. 总是在对主数据库运行VACUUM FULL时(此实例在此计算机上约为620 GB,与VACUUM FULL所需时间相比,该错误将非常快速地抛出)。

(到目前为止,我的“解决方案”是将我的Mac指向我办公室角落里运行的Ubuntu服务器,因此对我来说没有真正的问题。)

但是自从今天升级到Big Sur Beta 11.3后,我已经成功完成了2和3而没有出现错误(在升级之前立即失败)。这个操作系统中的某些内容是否可能修复了这个问题?


自从上次更新以来,我更加频繁地使用了我的数据库,并且再也没有遇到这个问题(之前真的无法使用)。 - Ian Gow
就我个人而言,在最新的Big Sur更新后,当将max_worker_processes设置为8时,我仍然遇到了这个问题,我的设备是MacBook Air M1。 - Ben Wilson
1
我曾经每次尝试特定任务(列表中的第二项,意味着我只是指向我的Ubuntu PostgreSQL)时都会遇到这些问题,但现在我从未再遇到过这个问题(所以我现在只使用我的Mac mini M1实例)。我检查了一下,我也将max_worker_processes设置为8。所以谜团仍在继续。(我使用MacPorts PostgreSQL,我的数据目录位于单独的硬盘上。) - Ian Gow

-1

我从postgresql.conf.sample中恢复了postgresql.conf(并重新启动了数据库服务器),自那以后它就一直正常工作。

顺便说一句,我在这里尝试了wal_buffersmax_worker_processes,但都没有帮助。我是偶然发现的,因为我尝试了很多东西,只需要回到之前的状态。我没有重新初始化整个数据库或类似的操作,只是修改了配置文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接