pg_dump在PostgreSQL长事务中是否保证序列值的一致性?
核心结论
pg_dump 默认以REPEATABLE READ隔离级别在单个事务中执行全量备份,导出的序列值是备份启动时的快照状态,不会捕获备份期间(比如你提到的1小时)对序列的修改。
具体解释
pg_dump 的备份机制
pg_dump 整个全量备份流程运行在一个独立的事务中,该事务采用REPEATABLE READ隔离级别。事务启动时PostgreSQL会生成一个数据库快照,后续所有读取操作(包括读取序列的last_value、is_called等核心属性)都基于这个快照,完全不会感知到事务启动后其他会话对数据库的任何修改,自然也包括序列的更新。和你实验中Serializable事务行为的差异
你测试的Serializable事务中能拿到序列最新值,本质是因为使用了nextval()这类写操作:PostgreSQL的序列属于特殊的持久化对象,nextval()、setval()这类操作会直接修改序列的物理存储状态,而且修改是全局即时可见的,不受事务隔离级别约束——哪怕在Serializable事务里调用nextval(),也会获取到全局最新的序列值,同时直接更新序列本身。
但pg_dump备份序列时,并不会调用nextval(),而是直接查询系统表(如pg_sequence)读取序列的当前属性,这个查询基于备份事务启动时的快照,因此得到的是备份开始时的序列状态,和备份期间其他会话对序列的修改完全无关。
简单验证方法
你可以在pg_dump启动后,立刻在另一个会话中用setval()修改某个序列的值,备份完成后查看导出的SQL文件,会发现序列的初始化值仍然是备份启动时的数值,而非你修改后的最新值。
内容的提问来源于stack exchange,提问作者Shiva

