pg_resetxlog [-f] [-n] [-ooid ] [-x xid ] [-e xid_epoch ] [-m mxid ] [-O mxoff ] [-l timelineid, fileid, seg ] datadir
pg_resetxlog 清理预写日志(WAL)并且可以有选择地重置其它一些存储在 pg_control 文件中的控制信息。有时候,如果这些文件崩溃了,就需要这个功能。一定只把它用作最后的方法,就是说只有因为这样的崩溃导致服务器无法启动的时候才使用。
运行这个命令之后,可能就可以启动服务器了,但是,一定要记住数据库可能因为部分提交的事务而含有不完整的数据。你应该马上转储数据,运行 initdb ,然后重新加载。在重新加载之后,检查不完整的部分然后根据需要进行修复。
这个命令只能由安装服务器的用户运行,因为它需要对数据目录的读写权限。出于安全考虑,pg_resetxlog 不使用环境变量 PGDATA ,你必须在命令行上声明数据目录。
如果 pg_resetxlog 抱怨说它无法判断用于 pg_control 的有效数据,那么你可以强制它继续处理,方法是声明 -f(强制)开关。在这种情况下,那些丢失了的数据将用模糊的近似数值代替。大多数字段都可以匹配上,但是下一个 OID 、下一个事务 ID 、下一个事务 ID 的 epoch(时间点)、下一个多事务 ID(两阶段提交的东西)、下一个多事务偏移量、WAL 开始地址、数据库区域字段可能需要手工帮助,前面六个可以用下面讨论的开关设置。pg_resetxlog 自己的环境是猜测区域字段的来源;看看 LANG 等东西,它们应该和 initdb 运行的环境相匹配。如果你不能判断所有这些字段的正确数值,那么 -f 仍然可以使用,但是这样恢复过来的数据库正确性更值得怀疑:立即转储和重新加载是必须的。在转储之前不要执行任何修改数据的操作,因为任何这样的动作都可能把事情搞得更糟糕。
-o, -x, -e, -m, -O, -l 开关允许手工设置下一个 OID 、下一个事务 ID 、下一个事务 ID epoch 、下一个多事务 ID 、下一个多事务偏移量、WAL 起始位置的数值。只有在 pg_resetxlog 无法通过读取 pg_control 判断合适的数值的时候才需要它。安全的数值可以用下面的方法判断:
对于下一个事务 ID(-x)而言,一个安全的数值是看看数据目录里的 pg_clog 里数值最大的文件名,然后加一,然后再乘上 1048576 。请注意那些文件名是十六进制的。通常也以十六进制的形式声明开关值是最简单的。比如,如果 0011 是 pg_clog 里最大的记录,-x 0x1200000 就可以了(后面的五个零提供了合适的乘积)。
下一个多事务 ID(-m)的安全值可以通过查看数据目录里 pg_multixact/offsets 子目录里面的数字最大的文件名,加一,然后乘以 65536 得到。和上面一样,文件名是十六进制的,因此最简单的方法是给开关声明一个十六进制的开关值,然后在结尾加四个零。
下一个多事务偏移量(-O)的安全值可以通过检查数据目录里 pg_multixact/members 子目录下的数字最大的文件名,加一,然后乘以 65536 得到。和上面一样,文件名是十六进制的,因此最简单的方法是给开关声明一个十六进制的开关值,然后在结尾加四个零。
WAL 的起始位置(-l)应该比目前存在于数据目录 pg_xlog 里面的任何文件号都大。它的文件名也是十六进制的,并且有三部分。第一部分是"时间线 ID",通常应该保持相同。第三部分不要选择大于 255(0xFF);应该是在达到 255 的时候给第二部分增一然后重置第三部分为 0 。比如,如果 00000001000000320000004A 是 pg_xlog 里最大的条目,那么 -l 0x1,0x32,0x4B 就可以了;但如果最大的条目是 000000010000003A000000FF ,那么选择 -l 0x1,0x3B,0x0 或更多。
没有很容易的办法来判断比数据库中最大的 OID 大一号的下一个 OID ,不过很走运的是获取正确的下一个 OID 并非非常关键的事情。
除了由 pg_resetxlog 设定的字段外,事务 ID epoch 实际上并未存储在数据库里的任何地方。所以只要是涉及到数据库自身的任何数值都有效。你可能需要调整这个值以确保诸如 Slony-I 之类的备份系统能够正常工作。如果是这样的话,应当从下游已复制的数据库中获取恰当的值。
-n(无操作)开关指示 pg_resetxlog 打印从 pg_control 重新构造的数值然后不修改任何值就退出。这主要是一个调试工具,但是在 pg_resetxlog 真正处理前进行的整洁性检查的时候可能会有用。