我们有一个多租户 SaaS 应用。我们一直为所有租户使用共享数据库,并将 TenantId 作为所有表中的外键。一切都运行良好,直到我们的业务需要每个租户架构的数据库(或模式)。
我们升级了后端 (ASP.NET Core 8) 来处理这种架构,并雄心勃勃地将所有租户迁移到集群上的单独数据库。集群上有大约 1000 个数据库,因此我们的迁移过程非常艰难。在数据量和负载相同的情况下,即使是 32 GB 4 CPUr7g.xl
实例似乎也配置过度,现在,即使是 16 CPU 128 GB r7g.4xl
AWS 实例有时也似乎配置不足。
在 1000 个数据库中,超过一半的数据甚至不会超过 100 MB。很少有数据库的数据量能达到几 GB。
由于我们一直在使用 AWS DMS(无服务器),因此复制也有一段时间处于非活动状态。因此一段时间后,出现了警告:
WARNING: oldest xmin is far in the past
当我们检查所有可能的原因时,结果发现复制槽正在持有 xmin。以下是以下查询返回的内容:
SELECT c.relnamespace::regnamespace as schema_name, c.relname as table_name,
greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age,
2^31-1000000-greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as remaining
FROM pg_class c LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
WHERE c.relkind IN ('r', 'm') ORDER BY 4;
结果:
该值不断增加,我们尝试删除复制槽两次,每次都导致停机,集群无法恢复,我们不得不从备份中创建新集群。因此,当我们删除不活动的复制槽时,会发生以下情况:
插入/更新查询本来运行良好,但在删除复制槽后突然开始显示 LW 锁。
现在看起来是这样的(插槽未被删除):
我们认为,每个集群拥有超过 300 个 DB 是一个错误。因此,我们将使用多个集群,每个集群拥有大约 300 个 DB。
但是我们现在应该做什么,为什么删除复制槽会触发这些锁?
过时的复制槽阻止了自动清理执行其维护工作。由于您的表现在包含比
autovacuum_freeze_max_age
事务更早的未冻结行,因此自动清理正在启动反回绕自动清理运行,这似乎会消耗足够的资源来影响您的应用程序。您可以尝试以下操作:设置
autovacuum_freeze_max_age
为 1500000000 和vacuum_freeze_table_age
500000000。vacuum_freeze_min_age
然后删除过时的复制槽。更改的设置将阻止自动清理启动密集活动。本质上,您正在争取一些时间。利用这段时间手动处理VACUUM (FREEZE)
所有超过 1 亿的表age(pg_class.relfrozenxid)
。确保在达到增加的限制之前完成这些操作。如果成功,age(pg_database.datfrozenxid)
将低于 2 亿。完成后,将参数重置为其默认值。如果您不采取行动,您的数据库将在某个时候拒绝新的交易,并且您将不得不延长
VACUUM
受影响表的停机时间。