详情

首页手游攻略 PostgreSQL 19 WAIT怎么用?主库写完后让备库等到新数据

PostgreSQL 19 WAIT怎么用?主库写完后让备库等到新数据

佚名 2026-11-02 12:20:01

保存地址后提示成功,刷新却还看到旧地址,过一会儿又正常了。若系统把写入送到主库、读取分给备库,可能只是复制尚未追上,不一定是保存出了问题。

19新增WAIT,可以在备库等待指定的日志进度完成后再读。应用不用重复自己写进度轮询,但仍要传递LSN、检查等待结果,并安排超时后的做法。

一、“读己之写”是什么意思?

读己之写,就是自己刚保存的修改,在接下来的读取里也应该可见。异步复制下,主库提交与所有备库可查询之间,可能存在一个短暂间隔。

WAIT 的思路是给备库一个明确目标:不是随便睡 100 毫秒,而是等到你这次写入对应的日志位置已经被重放。这个位置称为 LSN,可以把它理解成这套数据库 WAL 日志里的进度坐标。

二、正确顺序:先提交,再取位置,再等待

应用在主库完成写入,并确认事务提交后,再取得一个不早于这次提交完成的日志位置:

BEGIN;UPDATE public.profilesSET display_name = 'Alice'WHERE id = 42;COMMIT;SELECT pg_current_wal_insert_lsn();

这组示例应在同一主库连接上按顺序执行。不能在 COMMIT 之前就取一个位置,然后认为等到它就证明事务已经提交。返回值由应用保存,并传给接下来要读取的备库连接。

假设拿到的实际位置是 0/306EE20,在备库执行:

WAIT FOR LSN '0/306EE20'WITH (MODE 'standby_replay', TIMEOUT '500ms', NO_THROW);

只有结果为 success,才继续在同一备库会话读取。示例 LSN 不能原样用于真实业务,必须替换成这次写入后取得的值。

三、为什么必须等 replay,而不只是收到日志?

备库收到日志,不代表日志已经应用到可查询的数据。想让后面的 SELECT 看见修改,需要等重放完成,也就是 standby_replay;它也是 WAIT 的默认模式。

其他模式分别关注日志写入或持久保存等进度,适合另外的用途,不能当成“新数据已经能查询”的同义词。做读写分离时,先把目标选对,再讨论等待多久。

四、等不到时,应用应该怎么做?

不要省略等待时间。默认没有有限超时,复制异常时可能一直占着连接。示例中的 500ms 只是演示,要根据页面允许的响应时间安排。

返回结果应用处理
success继续在已确认的备库上查询
timeout按业务选择回主库、有限重试或提示稍后刷新
not in recovery重新确认服务器角色和切换状态,不直接当作等待成功

NO_THROW 让部分未成功的结果以状态返回,而不是直接报错。它不会替应用检查状态,也不会吞掉所有错误。程序如果收到 timeout 仍继续读旧数据,WAIT 就没有达到目的。

五、连接池和故障切换还有哪些坑?

等待成功后,查询不能被连接池分到另一台尚未追上的备库。应把等待和随后的读取固定到同一条实际连接,或确保目标节点一致。

等待也要放在读取之前,不要先查表、取得锁或旧快照,再来等复制进度。最简单的安排是在事务外先 WAIT,确认成功后再开始需要新数据的查询。

WAIT只比较日志位置数字,不会自动校验主库切换后的时间线,也不能用于比较两套无关数据库。主备角色改变时,应与连接管理、故障处理一起重新判断。

六、哪些场景值得用?

修改资料后立即查看、创建记录后打开详情,比较适合这种等待。可容忍短暂延迟的普通列表和统计查询,则未必需要每次等待,以免多占连接和资源。

业务较小时,也可让写入后的几次读请求直接访问主库,逻辑更简单。采用WAIT之前,先判断读写分离带来的好处,是否值得增加等待与回退处理。

相关资讯
点击查看更多
游戏推荐
推荐专题
热门阅读
推荐下载