问题

The database cluster was initialized with RELSEG_SIZE 1048576, but the server was compiled with RELSEG_SIZE 2097152
原因
相应源码:
if (ControlFile->relseg_size != RELSEG_SIZE)
ereport(FATAL,
(errmsg("database files are incompatible with server"),
errdetail("The database cluster was initialized with RELSEG_SIZE %d,"
" but the server was compiled with RELSEG_SIZE %d.",
ControlFile->relseg_size, RELSEG_SIZE),
errhint("It looks like you need to recompile or initdb.")));
如果控制文件($PGDATA/global目录下名为pg_control,可以通过pg_controldata查看)里的relseg_size不等于编译时的RELSEG_SIZE,就会有相应报错
控制文件的relseg_size通过pg_controldata显示为:Blocks per segment of large relation
RELSEG_SIZE 是一个磁盘文件中允许的最大块数。因此,单个文件的最大大小为 RELSEG_SIZE * BLCKSZ;比这更大的表被分成多个文件。
RELSEG_SIZE * BLCKSZ 必须小于操作系统对文件大小的限制。在 32 位操作系统中,这通常是 2 GB 或 4 GB,除非您启用了大文件支持。默认情况下,我们将限制设置为 1 GB,以避免操作系统中任何可能的整数溢出问题
在configure文件中有如下定义:

RELSEG_SIZE=(1024 * 1024 * segsize) / blocksize,其中segsize可以通过configure时的--with-segsize指定,默认是1GB;blocksize可以通过configure时的--with-blocksize指定,默认是8KB。
可以简单理解为RELSEG_SIZE其实是在configure时就已经确定,初始化数据库(initdb)时将RELSEG_SIZE的值赋给pg_control文件的relseg_size。
此问题一般出现在:远程恢复整个数据目录(通过pg_baseackup进行物理复制,在另一台服务器恢复)
现在这个问题原因就很明显了,由于在编译时的RELSEG_SIZE和读取数据目录中控制文件pg_control中的relseg_size值不同,就会出现上述错误提示
解决办法
重新编译或者初始化
如果对于远程恢复库而言,选择重新编译而不是初始化的原因是:目的是恢复库,数据目录是已经存在的,重新初始化一个数据目录后也是空的,不能达到远程恢复库的这个目的;
如果是对于正常启动数据库来说(不考虑数据问题),最好选择重新初始化(看到有说编译会影响数据)
可以计算出编译时所需要指定的大小:(这里只是提供一个思路)
(1)查看blocksize的大小:
pg_controldata查看Database block size
(2)根据报错提示查看正确的(编译时需要计算出的)RELSEG_SIZE
例如上面的报错:RELSEG_SIZE=2097152
(3)计算出编译时需要指定的各个参数的大小
–with-blocksize=第一步查看的blocksize的大小
–with-segsize=( RELSEG_SIZE * blocksize) / (1024 * 1024)
这里只是针对于报错的几个参数进行了分析,编译时的一些其他参数也需要注意,能找到源库编译时指定的选项大小还是根据那个来,上面的计算只是提供了一个思路
也可以通过pg_config --configure查看编译项[postgres@node1 ~]$ pg_config --configure '--prefix=/opt/pg14' '--with-pgport=6000' '--enable-debug' '--enable-dtrace' '--enable-cassert' '--enable-depend'




