|
|
Greenplum Database 管理员指南 V6.2.1
在CREATE TABLE时,可以在WITH子句中通过属性来设置,也可以通过参数
gp_default_storage_options来指定缺省值,不过,建议不要修改缺省值,因为,
这样做将会使得所有AO表都失去checksum校验的保护。例如:
在当前会话设置缺省的存储参数:
=# set gp_default_storage_options to 'checksum=false';
在系统级别修改缺省的存储参数:
$ gpconfig -c gp_default_storage_options -v 'checksum=false';
创建一张checksum为false的AO表:
=# CREATE TABLE sales2 (LIKE sales)
WITH (appendoptimized=true,checksum=false);
注意:编者建议不要在生产环境做这种尝试。
计算实例的Mirror镜像
GP将数据分散存储到多个计算实例上,每个计算实例,实际上是一个PostgreSQL
数据库实例。根据CREATE TABLE时定义的数据分布策略,数据分散到所有计算实例
上。在启用Mirror实例时,每个Primary实例都对应一个Mirror实例,二者是互为
镜像的关系。从6版本开始,Mirror通过WAL同步的方式保持与Primary的实时一致,
这与之前版本中Master和Standby的同步方式是完全一致的,之前的版本中,Mirror
通过filerep的方式保持与Primary的实时一致,filerep的方式引入了一些其他问
题,比如需要persistent系统表,无法从根本上避免page损毁的扩散等。
对Mirror的配置,可以在执行gpinitsystem命令时配置,也可以通过
gpaddmirrors命令为没有Mirror的GP集群配置Mirror镜像。当然,在进行
gpexpand操作时,如果现有GP集群有Mirror,也必须为新的Primary配置相应的
Mirror。通常,需要把配对的Primary和Mirror分散到不同的主机上,这样才能确
保发生主机故障时,配对的Primary和Mirror不会同时发生故障。Mirror的分散策
略可以根据用户的具体情况来确定,不过,在考虑Mirror的策略时,需要考虑主机故
障时的性能影响,同时,也需要考虑可发生故障的主机的数量,需要在性能和安全性之
间找到一个平衡点。可以参考"Instance镜像"章节。编者更推荐PAIR镜像模式,可
以更好的兼顾性能和安全性。
Master的镜像
GP集群可以为Master配置一个Standby实例,类似于Primary和Mirror的关系,
Standby也应该被部署在与Master不同的主机上。Standby是一个Warm状态,在
Master健康时,客户端只能通过Master来建立连接并执行SQL命令。Standby通过
版权所有:Esena(陈淼 ) 编写:陈淼 - 300 -
Greenplum Database 管理员指南 V6.2.1
WAL同步保持与Master的实时一致。
在Master发生故障,无法继续提供服务时,需要在Standby主机上执行
gpactivatestandby命令来激活Standby为新的Master。至少到目前为止的所有发
型版本和开源版本中,都没有实现Standby的自动激活,如有必要,需自行实现该功
能,专业服务团队也提供了付费方案帮助用户实现该功能,但这不是产品自身的实现,
是专业服务团队的工具,属于专属付费服务。
可以为Master和Standby分配一个虚IP,用于在Master和Standby之间漂移,
当Standby被激活时,将虚IP漂移到Standby所在的主机,这样,客户端将不需要修
改连接信息,可以继续访问数据库。
双集群灾备
维护两个GP数据库集群,可以提供更高级别的冗余,两个集群存储相同的数据,
还可以将两个集群放置在不同的地理位置,以应对灾难性故障。
双集群灾备,有多种可以考虑的方式。目前的版本,产品本身还没有实现容灾的功
能,未来可能会有很好的实现,从6版本开始,Primary和Mirror的同步方式是WAL
同步,期待未来可以通过多WAL复制的方式实现容灾部署。
目前常见的灾备方案有:双ETL、备份恢复、增量同步等,由于其他方案几乎毫无
价值,目前只介绍这三种。
双ETL,其实是同时维护两套集群,数据的抽取、转换和加载,需要在两个集群同
时被执行,而且要确保任务间依赖关系和执行顺序的一致。当然,可提供的数据查询访
问的能力也是翻倍的,不过,这种方案,会带来数据不一致的问题,比如逻辑的先后,
时间戳等,都会导致两个集群之间的数据不一致,甚至两个并发业务之间的互相影响,
也不能保证重复执行的结果完全一致,这涉及到事务隔离级别的问题,读已提交事务隔
离级别不能达到可串行化的效果,而且这种不一致还会随着时间的推移逐渐放大。同时,
保持两个集群的业务逻辑完全一致,也是开发和调度的难题,很多调度工具都无法做到
同步管理两个集群的任务。另外,一旦一个集群出现了灾难性故障,之后再恢复故障集
群,又将面临极大的困难,这可能会涉及到全量数据的备份拷贝和恢复。这种方案的优
势是,两个集群几乎可以保持实时的可用性切换。
备份恢复,首先需要一个共享存储,用于备份数据的共享转移,在主集群中,将数
据备份到共享存储上,然后在备用集群上,从共享存储恢复备份文件到数据库。与双
ETL方案相比,这种方案将需要花费更多的时间来同步数据,同时需要较大容量的共享
存储设备,但可以保证数据的一致性,同时,不需要业务逻辑和作业调度做出任何的修
改。如果存储和时效性都可以接受,可以考虑该方案。
增量同步,这是编者为付费用户实施的灾备方案,目前已有多个用户在生产中实施
并长期稳定运行。该方案,通过组合使用编者的一套自己开发的命令脚本来实现,首先
通过DDL比对命令,比对出主集群和灾备集群之间的表结构差异,并自动生成一致化
版权所有:Esena(陈淼 ) 编写:陈淼 - 301 -
Greenplum Database 管理员指南 V6.2.1
SQL脚本,在灾备集群执行该SQL脚本即可完成两个集群之间的表结构一致化调整。之
后,运行表数据的增量同步命令,命令会自动判断源集群哪些表发生了变化,并同步到
灾备集群。对于设计比较合理的OLAP型集群来说,这种增量同步,有些用户可以在一
小时内完成每日的增量同步。该方案的优势是,不需要业务和调度系统做出任何调整,
可以保证两个集群的数据一致性,不需要共享存储来中转数据。劣势是,两个集群之间
存在一定时间的数据差异,典型的时间差是一天的延迟,对于任务可重复执行的分析型
系统来说,这往往不是一个问题。
逻辑备份与恢复
逻辑备份,指的是,将数据从数据库中导出并备份到文件系统中。GP数据库是一
个分布式系统,难以在线进行物理备份并保证数据的可恢复性,所以,目前都是采用逻
辑备份的方式对数据库进行备份。
备份是另一个层面的数据保护,有着其他方案无法替代的优势,比如,对于使用了
增量备份的GP数据库集群,能够将数据库恢复到之前的某个备份时间。这就意味着,
对于数据库的误操作,也是可以恢复的,而之前提到的灾备集群的保护,无法实现这一
点。备份,可以容许各种异常情况的发生,唯一的缺点是,恢复需要较多的时间。
从5版本开始,GP数据库不再使用gpcrondump等旧的备份命令,而是使用完全重
新开发的备份恢复命令:gpbackup和gprestore。gpbackup可以选择将每个表备份
到单独的文件中,这是一个巨大的进步,这样,将允许在备份过程中出现个别表的备份
失败,而不影响其他表的备份成功。gpbackup在备份单个表时,集群中的所有Primay
并行进行备份,同时,可以有多张表同时进行备份,所以,gpbackup可以更好的利用
硬件的资源来快速完成备份工作,因此,备份的性能将取决于单个主机上存储的数据量
和计算能力,而与集群的规模没有直接关系。
在规划备份策略时,首先要考虑的是,备份数据存放在哪里。对于每个Primary
来说,都可以将数据备份到Primary所在主机的本地路径,但是,不要将备份数据一
直存放在计算节点主机的本地磁盘上,这不仅仅是因为备份数据会占用本地磁盘的存储
空间,最重要的是,一旦主机的磁盘发生故障,数据库中的数据文件可能会和备份数据
一同丢失。基于以上这些原因,应该在备份之后,马上将备份数据转移到独立的存储设
备,或者直接备份到独立的存储设备上,最常见的方式是通过NFS的方式将远程存储挂
载为一个本地的路径,直接将备份数据存储到该路径。
通过使用gpbacku和gprestore的存储插件,可以发送备份数据到远程存储,或
者从远程存储恢复到数据库中,目前GP数据库的备份恢复存储插件支持Amazon的S3
协议和Dell EMC的Data Domain存储设备。更多内容可以参考gpbackup和
gprestore命令的详细说明。
编者也一直在维护着一套备份恢复的命令脚本,可以更快速的备份DDL信息,更灵
活的进行自定义备份,以及支持heap表的变化识别等。
版权所有:Esena(陈淼 ) 编写:陈淼 - 302 -
Greenplum Database 管理员指南 V6.2.1
Instance 镜像概述
当GP数据库集群开启了Instance镜像的高可用配置,Instance则可以分为两种
类型,Primary和Mirror,而且,Primary和Mirror总是成对出现,每个Primary
都有一个配对的Mirror。Primary负责接收Master分发的任务,执行数据的查询和
修改,同时,把对数据的修改复制到配对的Mirror。如果数据库发现Primary出现故
障或者无法访问,会自动激活与该Primary配对的Mirror,同时,会将Mirror置为
Primary角色,将故障的Primary置为Mirror角色。在发生故障切换期间的事务,将
会失败,需要重新提交执行。在发生故障切换之后,运维人员,应该尽快找到故障原因
并解决,然后将处于Mirror角色的失败Instance重新与配对的Primary角色的
Instance进行同步,并且在完成同步之后,寻找一个合适的时间来交换这一对
Instance的角色到初始状态。
如果GP数据库集群没有开启Instance镜像的高可用配置,那么,任何Instance
的失败,都会导致整个数据库停止工作。管理员需要手动恢复所有的故障Instance,
然后才能恢复数据库的可用状态。
在为一个没有Mirror的集群添加Mirror时,Primary将继续提供数据库服务,
同时为Mirror设置一个快照,在将快照从Primary同步到Mirror过程中,Primary
会记录下数据的变化。在Mirror同步完快照之后,Mirror将通过WAL复制的方式保持
与Primary的同步状态。GP数据库的WAL同步,使用wal sender和wal receiver
进程来完成,wal sender是Primary发送WAL日志的的进程,wal receiver是
Mirror接收WAL日志的进程。
在数据发生修改时,记录了数据修改信息的WAL日志,将以流的形式发送给Mirror,
Mirror通过重放WAL日志的方式保持与Primary的一致。
当GP数据库发现一个Primary失败了,WAL同步将会停止,Mirror将以Primary
的角色被自动激活,同时,被激活的Mirror作为Primary的角色开始工作之后,将会
记录之后的修改操作,用于未来恢复之前失败的Primary。当GP数据库发现一个
Mirror失败了,WAL同步同样会停止,Primary会记录之后的修改操作,用于未来恢
复失败的Mirror。
可以通过gp_segment_configuration系统表来查看集群中Instance的配置
信息和当前的状态。通过gp_stat_replication视图查看walsender进程的同步情
况。
关于Instance镜像的不同分散模式,可以参见"Instance镜像"章节。在使用
gpinitsystem命令或者gpaddmirrors命令配置Mirror时,都可以选择group镜像
策略或者spread镜像策略,group是缺省值。
如果要设置自定义的镜像策略,可以参考gpinitsystem命令的-I参数或者
版权所有:Esena(陈淼 ) 编写:陈淼 - 303 -
Greenplum Database 管理员指南 V6.2.1
gpaddmirrors命令的-o和-i参数的详细解释。
Master 镜像概述
当为Master配置Standby时,Standby是warm状态。在为一个没有Standby的
集群添加Standby时,Master将继续提供数据库服务,同时为Standby设置一个快照,
在将快照从Master同步到Standby过程中,Master会记录下数据的变化。在
Standby同步完快照之后,Standby将通过WAL复制的方式保持与Master的同步状态。
GP数据库的WAL同步,使用wal sender和wal receiver进程来完成,wal sender
是Master发送WAL日志的的进程,wal receiver是Standby接收WAL日志的进程。
这个机制,在Master和Standby之间,一直如此,包括之前的4版本和5版本,而从6
版本开始,这个机制与Primary和Mirror之间,完全相同。更多关于Master与
Standby的介绍,请参见"Master镜像"章节。
为 GPDB 配置镜像
本节将介绍如何为没有高可用的GP数据库集群配置高可用镜像,这涉及到
gpaddmirrors命令和gpinitstandby命令,关于gpinitsystem时配置镜像的内
容,本节不再介绍,可以参考"初始化GP数据库集群"章节。
为 Primary 配置 Mirror
Mirror的存在,使得GP数据库集群可以在Primary出现故障时自动切换到
Mirror并继续提供服务。缺省情况下,Mirror会被配置在集群内的其他Primary所
在的主机上,也就是说,每台计算节点的主机,既作为Primary的载体,也作为其他
主机Primary配对的Mirror的载体。不过,如果真的喜欢,可以将Mirror配置在完
全不同的主机上,虽然编者并不赞同这种方案。如同之前介绍的,Mirror的分散策略
是可以通过gpaddmirrors命令的-o参数和-i参数来自定义的,那么,当然可以添加
任意喜欢的Mirror策略,然而,在GP数据库集群处于正常状态时,Mirror是不对外
提供服务的,如果将Mirror配置在与Primary无关的主机上,该主机的计算资源将长
期处于被浪费的空闲状态。
在集群内按照缺省选项配置Mirror
版权所有:Esena(陈淼 ) 编写:陈淼 - 304 -
Greenplum Database 管理员指南 V6.2.1
1. 为Mirror配置数据存储的路径,包括工作目录和表空间的目录,对于6版本来说,
是表空间的目录需要被创建,对于6之前的版本来说,是文件空间的目录需要被创
建。对于GP数据库来说,是基于操作系统的目录(或者说路径)来工作的,所以,
需要确保分配的路径有足够的存储空间,Mirror所在磁盘的存储空间应该与对应
的Primary的存储空间相当,否则将会有容量不匹配的问题,因为Mirror实例的
尺寸与对应的Primary实例的尺寸是完全相同的。虽然,Mirror的路径最好能与
Primary的路径不同,然而,在6版本创建表空间时,Primary的路径又必须与
Mirror的路径相同,所以,这真的是一个很尴尬的问题。为了能够从工作目录上
区分Primary和Mirror,可以在上层路径相同的情况下,修改prefix的值,比
如,Primary使用pgpseg作为prefix,Mirror使用mgpseg作为prefix,这
会涉及gpinitsystem和gpaddmirrors的参数文件修改操作,详情,请参见
gpinitsystem命令的-I参数和gpaddmirrors命令的-o和-i参数的解释。例如:
2. 通过gpssh-exkeys确保所有主机之间可以实现免密码的ssh和scp操作,GP数据
库的很多操作都依赖免密码ssh,一旦该功能出现问题,将会导致很多操作失败。
3. 执行gpaddmirrors命令来配置Mirror,命令会进入交互式过程,根据提示信息
输入Mirror的工作目录,根据提示信息确认是否继续配置Mirror。例如:
Enter mirror segment data directory location 1 of 2 >
/data/default/
Enter mirror segment data directory location 1 of 2 >
/data/default/
Continue with add mirrors procedure Yy|Nn (default=N):
> y
如果是 6 之前的版本,且有文件空间的话,还需要输入文件空间的目录,而 6 版
本不需要输入表空间的目录,因为 6 版本中,表空间的目录,Mirror 必须与
Primary 相同,所以,不需要另外提供,但这些目录也必须事先创建好。
可以通过-p参数为gpaddmirrors命令指定Mirror的PORT偏移量。-p参数指的
是,Primary的PORT增加一个数字,作为Mirror的PORT。例如:
$ gpaddmirrors -p 10000
如果可以,编者还是建议采用gpaddmirrors的-o和-i参数来确认Mirror的详
细配置。接下来将介绍这种操作方法。
版权所有:Esena(陈淼 ) 编写:陈淼 - 305 -
Greenplum Database 管理员指南 V6.2.1
自定义配置Mirror(包括主机不在现有集群内)
1. 首先要确保所有新增的主机上都成功安装了GP数据库软件,所有新主机都按照GP
数据库的运行要求进行了参数的修改和配置,详情可参见"安装部署与初始化"章
节。
2. 为Mirror配置数据存储的路径,包括工作目录和表空间的目录,对于6版本来说,
是表空间的目录需要被创建,对于6之前的版本来说,是文件空间的目录需要被创
建。
3. 通过gpssh-exkeys确保所有主机之间可以实现免密码的ssh和scp操作,GP数据
库的很多操作都依赖免密码ssh,一旦该功能出现问题,将会导致很多操作失败。
4. 通过gpaddmirrors命令的-o参数生成一个配置文件,其中会列出每个Mirror
实例的主机名,端口,工作目录等信息。实际上,对于6之前的版本,还会列出
Mirror的同步端口和Primary的同步端口。在不清楚如何创建这个配置文件时,
可以参考gpaddmirrors命令的-i参数和help中的EXAMPLES,或者先通过-o参
数生成一个样例配置:
$ gpaddmirrors -o mirror_config_file
执行该命令时,命令会进入交互式过程,根据提示信息输入Mirror的工作目录,
根据提示信息确认是否继续配置,不同的是,该操作不会继续配置Mirror,而是
生成一个配置文件之后,就退出了命令。
6版本的Mirror配置文件格式为:
contentID|address|port|data_dir
其中contentID对应的是配对的Primary的content值,address是该Mirror
将会配置在哪个主机的网络端口上,port是Mirror的监听端口,data_dir是
Mirror的工作目录。
6之前版本的Mirror配置文件格式为:
mirror<content>=<content>:<address>:<port>:<mir_replication_port>:<pri_
replication_port>:<fselocation>
区别在于,mirror<content>=<content>是固定格式,
mir_replication_port是Mirror实例的复制端口,
pri_replication_port是Primary实例的复制端口。如果要调整镜像模式,
需要注意的是,必须确保每个主机上的端口不能有重复,否则,在添加Mirror时
会有端口冲突的报错,并导致Mirror添加失败。
版权所有:Esena(陈淼 ) 编写:陈淼 - 306 -
Greenplum Database 管理员指南 V6.2.1
例如,这是6版本的Mirror配置文件的例子(6之前的版本不再举例,不过文件格
式也的确要复杂很多,尤其是端口重复问题,无数人败在此处,编者为商业用户提
供了自动化命令来完成该操作):
0|sdw003|50000|/data/default/mgpseg0
1|sdw004|50001|/data/default/mgpseg1
2|sdw004|50000|/data/default/mgpseg2
3|sdw003|50001|/data/default/mgpseg3
4|sdw001|50000|/data/default/mgpseg4
5|sdw002|50001|/data/default/mgpseg5
6|sdw002|50000|/data/default/mgpseg6
7|sdw001|50001|/data/default/mgpseg7
这个例子展示的是,有4个计算节点主机,每个主机上有2个Primary,其中sdw001
上有content为0和1的Primary,sdw002上有content为2和3的Primary,
sdw003上有content为4和5的Primary,sdw004上有content为6和7的
Primary。设置的镜像关系为,sdw001的镜像分散在sdw003和sdw004上,
sdw002的镜像分散在sdw004和sdw003上,sdw003的镜像分散在sdw001和
sdw002上,sdw004的镜像分散在sdw002和sdw001上。这就是编者前文提到的
PAIR镜像模式。4台机器,所有的宕机可能性为:
sdw001
sdw002
sdw001 + sdw002
sdw003
sdw004
sdw003 + sdw004
总共有6种组合,如果将这4台机器按照GROUP模式进行Mirror镜像,可宕机也是
6种组合,但PAIR模式更具有性能优势,当只有一台计算节点主机宕机时,性能损
失的程度要比GROUP模式低。
在这一步,可以做任意符合GP运行要求的修改,比如,把Mirror设置在现有集群
之外的主机上,或者有的主机设置多一些的Mirror,有些主机设置少一些的
Mirror,只要环境配置没有问题,怎么做都可以,甚至把配对的Mirror和
Primary放在同一台机器上也是允许的。
5. 使用编辑后的文件,通过gpaddmirrors -i参数添加Mirror镜像。例如:
$ gpaddmirrors -i mirror_config_file
对于一个较大的集群,编辑此文件困难重重,但,此方法已经几乎是无所不能。
版权所有:Esena(陈淼 ) 编写:陈淼 - 307 -
Greenplum Database 管理员指南 V6.2.1
为 Master 配置 Standby
可以在gpinitsystem时通过-s参数来指定Standby,也可以在没有Standby的
集群通过gpinitstandby命令的-s参数来添加Standby。关于gpinitstandby命令
的更多信息,请参考命令的相关help信息。
为现有集群配置Standby
1. 首先要确定的是,集群中没有Standby。至少到目前为止,GP数据库还不支持多
Master的配置,Standby最多只能有一个,如果已经有Standby,继续添加
Standby的操作会立即收到失败报错并退出:
Validating environment and parameters for standby initialization...
Standby master already configured
If you want to start the stopped standby master, use the -n option
Failed to create standby
Error initializing standby master: standby master already configured
2. 首先要确保将作为Standby的主机上成功安装了GP数据库软件,且已经按照GP数
据库的运行要求进行了参数的修改和配置,详情可参见"安装部署与初始化"章节。
3. 为Standby配置数据存储的路径,包括工作目录和表空间的目录,对于6版本来说,
是表空间的目录需要被创建,对于6之前的版本来说,是文件空间的目录需要被创
建。
4. 通过gpssh-exkeys确保所有主机之间可以实现免密码的ssh和scp操作,GP数据
库的很多操作都依赖免密码ssh,一旦该功能出现问题,将会导致很多操作失败。
5. 在当前的Master主机上,使用gpadmin用户执行gpinitstandby命令来添加
Standby,通过-s参数指定Standby的主机名。例如:
$ gpinitstandby -s smdw
注意:对于4.3以上的版本来说,使用gpinitstandby命令来添加Standby是在线操
作,整个操作过程不影响数据库的正常运行和对外服务(也不是零影响,后续章节会有
更详细的介绍)。对于4.2以及更老的版本来说,使用gpinitstandby命令来添加
Standby会自动进行数据库的重启,才能完成添加操作,不过,如果在看到这段内容
时还在使用5以前的版本,说明,您所使用的GP数据库集群已经快成古董了。
检查Standby的同步状态
版权所有:Esena(陈淼 ) 编写:陈淼 - 308 -
Greenplum Database 管理员指南 V6.2.1
可以通过gpstate命令的-f参数检查Standby的同步状态:
$ gpstate -f
检查命令的输出结果,Sync state为sync,表示Standby保持了实时同步状态。
还可以直接查询WAL同步状态的函数来获取:
=# SELECT sync_state FROM pg_stat_get_wal_senders();
查询得到结果为sync,表示Standby保持了实时同步状态。
检测失败的 Instance
在集群中,Master会有一个专门的子进程用于检测Primary和Mirror的状态,
这个进程的名称为ftsprobe,通常被称为FTS (Fault Tolerance Server)。
FTS会定期轮询检查集群的状态,每次轮询,FTS会根据
gp_segment_configuration系统表中配置的hostname和port信息,尝试通过
TCP连接来测试Primary的可连接性。如果连接可以成功,FTS还会做一些简单的检查,
包括对Primary的工作目录执行stat命令,以及检查Primary有没有发生内部错误。
如果整个检查没有发现任何异常,FTS将不会对该Primary采取任何动作。
如果无法连接,或者连接超时,FTS会进行重试,如果尝试失败的次数超过配置的
最大限制,FTS则会认为该Primary有问题,会确认其配对的Mirror是否处于启动且
同步的状态,如果是,则会在gp_segment_configuration系统表中将故障的
Primary标记为down的状态,将配对的Mirror标记为Primary角色,同时激活
Mirror接替Primary的任务,之后,被激活的Mirror会持续记录数据库的修改,以
便以后对失败的Primary进行增量恢复。
当Primary处于健康状态,而配对的Mirror出现了down的情况,Primary的状
态将变为不同步(mode字段为n),之后,会持续记录数据库的修改,以便以后对失败
的Mirror进行增量恢复。
任何Instance状态的变化,都会在gp_configuration_history系统表中间记录。
对数据库修改的记录,在6版本之前,使用的是change tracking,6版本开始
使用WAL日志记录。
通过gpstate命令的-e参数,可以查看Primary和Mirror的异常情况,通过
gpstate的-m参数可以查看Mirror的同步状态,通过gpstate的-c参数可以成对的
版权所有:Esena(陈淼 ) 编写:陈淼 - 309 -
Greenplum Database 管理员指南 V6.2.1
显示Primary和Mirror的配置信息以及同步状态。
还可以通过查询gp_segment_configuration系统表来获取Primary和
Mirror的状态信息。mode字段,s表示状态已同步,n表示状态不同步,对于6之前的
版本,还有一个状态值,r,表示正在重新同步。status字段,u表示启动状态,d表
示down的状态。
可以通过gprecoverseg命令来重新恢复Mirror实例,状态为down的Primary
其role是Mirror,缺省情况下,gprecoverseg将执行增量恢复,通过重放Primary
记录的WAL日志的方式实现。如果无法进行增量恢复,则需要通过gprecoverseg的
——F参数进行全量恢复,全量恢复,意味着,Primary的所有数据全量覆盖到Mirror。
对于6之前的版本来说,增量恢复,是根据Primary的change tracking信息,将
Mirror故障期间发生了变化的page信息覆盖到Mirror。
在完成了Primary和Mirror之间的差异恢复之后,gpstate -e可能会列出
Primary与Mirror发生了角色切换的信息。例如:
[INFO]:-Segments with Primary and Mirror Roles Switched
Current Primary Port
Mirror
Port
sdw001
50000 sdw002
40000
这样的信息表明,Primary和Mirror目前没有处在最初的角色,数据库处于不平
衡的状态,不过,这并不表示此时数据库不在高可用的状态,只要所有的Primary和
Mirror保持着同步状态,高可用状态就是正常的,是否高可用,与
gp_segment_configuration系统表中role属性和preferred_role属性是否相
同,没有直接关系。在数据库处于不平衡状态时,数据库的资源利用将可能是倾斜的,
因为原本属于Primary的任务由Mirror承担了。这里是说可能,而且绝大部分情况下,
也的确如此,但也一定可以找到发生了角色切换却不倾斜的情况,比如,所有的
Primary和Mirror都发生了角色切换。
是否存在角色切换,取决于gp_segment_configuration系统表中的role属性
和preferred_role属性是否相同,两个字段的取值有两种:p和m,p表示Primary,
m表示Mirror,preferred_role属性指的是,该Instance在系统初始化时的角色,
也就是其应该作为的角色,该属性不会发生变化(如果你要手动改,那是另一回事),
role属性会在Primary和Mirror发生切换时发生改变。
要恢复Primary和Mirror为最初的角色,对于6版本来说,必须通过
gprecoverseg的-r参数来完成,而对于6之前的版本来说,最好通过重启数据库来完
成,在重启数据库时,6之前的版本会根据Primary和Mirror的状态是否同步来决定
是否应该切换其角色到最初的状态,而6版本,在重启数据库时不会切换Primary和
Mirror的状态。当然,在6版本,如果不使用gprecoverseg -r,也可以手动停止
Primary从而触发切换,然后再执行gprecoverseg重新同步来完成切换动作。
版权所有:Esena(陈淼 ) 编写:陈淼 - 310 -
Greenplum Database 管理员指南 V6.2.1
6 版本故障切换的恢复过程
接下来,通过一对Primary和Mirror发生故障切换的例子来说明Instance的不
同状态。下面的表格展示的是gp_segment_configuration系统表中已经发生故障切
换的一对Primary和Mirror的信息:
初始化角色
preferred_role
role
mode
status
Primary
p(Primary)
m(Mirror)
n(不同步)
d(Down)
Mirror
m(Mirror)
p(Primary)
n(不同步)
u(Up)
通过执行gpstate -e也可以查看Primary和Mirror的故障切换情况。例如:
Segment Mirroring Status Report
----------------------------------------------------
Segments with Primary and Mirror Roles Switched
Current Primary Port
Mirror
Port
sdw001
50000 sdw002
40000
----------------------------------------------------
Unsynchronized Segment Pairs
Current Primary Port
Mirror
Port
sdw001
50000 sdw002
40000
----------------------------------------------------
Downed Segments (may include segments where status could not be retrieved)
Segment Port
Config status
Status
sdw002
40000 Down
Down in configuration
从目前的状态来看,这两个Instance的角色与初始化时的角色不同,因为
Primary出现了故障切换,Mirror转化为Primary,而发生故障的Primary转化为
Mirror。在解决了故障实例所在主机的问题之后,可以通过执行gprecoverseg命令
来执行Mirror和Primary的同步。
在执行gprecoverseg命令时,6版本的过程与6之前的版本有着明显的不同,6
之前的版本,gprecoverseg其实是启动一个恢复操作,一旦恢复操作完成必要的检
查和空文件的创建工作,就会转入后台的数据同步过程,gprecoverseg命令就会退
出,Instance的mode变为r的状态。而在6版本,gprecoverseg命令完成时,就是
所有同步操作都结束的时间,期间,gprecoverseg命令会输出Primary和Mirror
之间的同步进度。例如:
sdw002 (dbid 4): 19630/54815 kB (35%), 0/1 tablespace (.../default/mgpseg0/base/1/12668_vm)
sdw002 (dbid 3): 18630/54687 kB (34%), 0/1 tablespace (...default/pgpseg1/base/1/12624_fsm)
在完成Primary和Mirror的同步之后,会显示同步完成的信息。例如:
版权所有:Esena(陈淼 ) 编写:陈淼 - 311 -
Greenplum Database 管理员指南 V6.2.1
sdw002 (dbid 4): pg_basebackup: base backup completed
sdw002 (dbid 3): pg_basebackup: base backup completed
在完成gprecoverseg之后,需要确认Primary和Mirror的状态,确保故障实例
的status为u,配对的Primary和Mirror的mode都是s,这样,就恢复了同步的状态。
初始化角色
preferred_role
role
mode
status
Primary
p(Primary)
m(Mirror)
s(已同步)
u(Up)
Mirror
m(Mirror)
p(Primary)
s(已同步)
u(Up)
在确保Primary和Mirror已经处于同步状态后,对于6版本来说,可以执行
gprecoverseg -r来切换角色到初始化角色。对于6之前的版本,可以通过执行
gprecoverseg -r来切换角色到初始化角色,也可以通过重启集群来恢复初始化角色。
恢复之后的状态为:
初始化角色
preferred_role
role
mode
status
Primary
p(Primary)
p(Primary)
s(已同步)
u(Up)
Mirror
m(Mirror)
m(Mirror)
s(已同步)
u(Up)
注意:在查询gp_segment_configuration系统表时,6版本中,Master的mode
始终为n,这与之前的版本不同,不要使用这个值来判断Master与Standby的同步状
态,最好使用gp_stat_replication视图,或者pg_stat_get_wal_senders()
函数,或者执行gpstate -f命令来检查Standby的同步状态。另外,此处的例子中
介绍的是6版本的情况,对于6之前的版本,mode有三种状态:s、n和r,分别表示:
同步,不同步和正在重新同步中。
6 之前版本故障切换的恢复过程
鉴于目前6版本版本还没有全面升级,这里有必要介绍一下6版本之前的情况。由
于6之前的版本Primary和Mirror之间是文件block级别的复制,原理与6版本完全不
同,所以,gprecoverseg命令后台的操作也完全不同。例如,故障切换后的Primary
和Mirror的状态为:
初始化角色
preferred_role
role
mode
status
Primary
p(Primary)
m(Mirror)
n(不同步)
d(Down)
Mirror
m(Mirror)
p(Primary)
n(不同步)
u(Up)
虽然gprecoverseg命令是一个在线的操作,但是,有两个时间段,IO操作会被
挂起。第一次是开始恢复时(执行gprecoverseg命令期间),在Mirror上创建空文件
版权所有:Esena(陈淼 ) 编写:陈淼 - 312 -
Greenplum Database 管理员指南 V6.2.1
的过程,第二次是,数据文件已经同步完成之后,事务日志之类的数据库系统文件拷贝
期间。这个时间的长度,取决于有多少空文件需要被创建,以及数据库系统文件的尺寸。
在数据复制同步期间,数据库可以访问并执行任何SQL命令,同时,所有对数据的修改
操作也会及时被同步。不过,对于增量恢复,IO挂起的时间可能会很短,因为只有故
障实例down期间,Primary上有增删的文件,需要在Mirror(故障时的role为m)上
被创建或者删除。
gprecoverseg命令执行如下步骤的操作:
1.
确定故障的实例,输出故障实例的信息,以及缺省将采取的恢复方式(缺省为增量
恢复),如果没有指定-a参数,将会提示是否继续。
2.
确定Mirror服务是否已经停止,并重新启动或者重新初始化Mirror并启动。
3.
对于指定了-F参数的情况来说,由于是全量恢复,所以会有如下动作:
删除Mirror的数据目录,包括filespace的目录。
创建新的目录结构,包括filespace的目录结构。
4.
修改gp_segment_configuration系统表中mode字段属性的值为
r(resynchronizing)。
5.
后台执行如下操作:
IO挂起--可以连接到数据库,但是不能对正在恢复的实例进行读写操作。
扫描Primary实例的persistent表获取文件信息。
对于每个persistent文件(可参考pg_class系统表的relfilenode字段
的值),在Mirror上创建对应的数据文件。
数据文件的数量越大,IO挂起的时间越长。增量恢复的IO挂起时间会比较短。
6.
gprecoverseg命令完成并退出。
在gprecoverseg命令完成之后,并不意味着恢复操作已经全部完成,而是转入
后台执行,因为还有一些文件的数据需要被同步到Mirror上。此时,Primary和
Mirror的状态变为:
初始化角色
preferred_role
role
mode
status
Primary
p(Primary)
m(Mirror)
r(重新同步中)
u(Up)
Mirror
m(Mirror)
p(Primary)
r(重新同步中)
u(Up)
在完成gprecoverseg命令的执行之后,恢复操作进入后台执行,文件复制进程
开始从Primary向Mirror复制文件中的数据内容,此时,通过gpstate -e可以查看
复制的进度情况,包括复制对象的数量,尺寸以及预计的完成时间等,完成时间是预估
版权所有:Esena(陈淼 ) 编写:陈淼 - 313 -
Greenplum Database 管理员指南 V6.2.1
值,随着进度的增长,预计的完成时间会更有参考性。在这个时间内,数据库可以进行
任何正常的访问和操作。这个时间内的同步包含如下步骤:
1. 数据同步(全量恢复和增量恢复都有该操作)。在确保所有文件已经创建好之后,
后台复制进程,继续根据persistent表的信息找到需要被复制数据的文件,并将
数据从Primary复制到Mirror。
2. 在此期间,数据事务引起的文件修改和增删,都会直接被同步到Mirror上。
3. 在数据同步期间,有些数据库操作可能会导致一些文件对象需要被重新同步,比如
正在同步的文件被修改。在完成所有数据文件的同步之后,Primary的状态在共
享内存中被置为"InSync"。
在Primary被置为"InSync"状态后,执行gpstate -e将会看到对应的Primary
和Mirror的状态将会是:
Sync complete; awaiting config change
在完成数据文件同步之后,恢复操作进入下一次的IO挂起时间,在此期间,数据
库的系统文件将从Primary复制到Mirror上。包括如下目录的数据:
pg_xlog/*
pg_clog/*
pg_distributedlog/*
pg_distributedxidmap/*
pg_multixact/members
pg_multixact/offsets
pg_twophase/*
global/pg_database
global/pg_auth
global/pg_auth_time_constraint
在完成这些之后,Primary和Mirror的状态将会被FTS修改为已同步的状态:
初始化角色
preferred_role
role
mode
status
版权所有:Esena(陈淼 ) 编写:陈淼 - 314 -
Greenplum Database 管理员指南 V6.2.1
Primary
p(Primary)
m(Mirror)
s(已同步)
u(Up)
Mirror
m(Mirror)
p(Primary)
s(已同步)
u(Up)
此时执行gpstate -e将不会再显示同步的进度信息,而是显示如下信息:
----------------------------------------------------
Segment Mirroring Status Report
----------------------------------------------------
Segments with Primary and Mirror Roles Switched
Current Primary Port
Mirror
Port
sdw001
50000 sdw002
40000
注意:影响恢复时间的因素主要有,数据库中对象的数量,主要是表和索引,因为这些
对象都需要存储数据文件;Instance实例的数据文件数量,列存储会增加文件数量;
数据同步期间的数据库负载情况;数据的尺寸。数据库系统文件的尺寸。编者想说,影
响最大的还是小文件的数量,大文件的复制性能很高,而小文件的复制性能很低,再次
强调,不要滥用分区和列存储。
FTS 相关参数
FTS的行为受以下参数控制:
gp_fts_probe_interval
FTS检测的间隔周期,缺省值为60,单位是秒。比如,设置的周期为60秒,如果
一次检测花费了50秒的时间,FTS进程将sleep 10秒,然后开始下一次检测,如
果一次检测花费的时间超过了60秒,FTS进程将sleep 0秒。可以设置的最大值
为3600,即,一个小时。
gp_fts_probe_timeout
Master的FTS进程检测Instance的超时时间,缺省为20秒,可以设置的最大值
为3600,即,一个小时。
gp_fts_probe_retries
FTS无法连接到Instance或者连接超时后的重试次数,缺省为5。如果设置为5,
第一次尝试失败之后,最多再尝试4次。
gp_log_fts
版权所有:Esena(陈淼 ) 编写:陈淼 - 315 -
Greenplum Database 管理员指南 V6.2.1
FTS进程的日志级别,可选级别有: off、terse、verbose和debug,缺省为
terse,verbose可用于故障排查,debug不建议在生产环境中使用。
gp_segment_connect_timeout
等待Mirror响应的最长时间,缺省为600,单位是秒。
在FTS检测之外,gp_segment_connect_timeout参数限制的是Primary等待
Mirror响应的时间,在Primary向Mirror发送数据时,超过该参数设置的时间仍无
法成功,Primary将会报告Master修改Mirror的状态为down,然后Primary将会持
续记录WAL日志,对于6之前的版本,Primary将进入change tracking状态。不过,
对于该参数,至少在6之前的版本,真正的超时时间是设定值的75%。
检查 Instance 故障
1. 可以在Master上执行gpstate -e命令来查看Primary和Mirror的健康情况,
如果所有Primary和Mirror都完全正常,会输出如下信息:
[INFO]:-Segment Mirroring Status Report
[INFO]:-----------------------------------------------------
[INFO]:-All segments are running normally
否则,会输出Primary和Mirror的异常情况,比如Mirror Down或者Mirror切换等。
2. 还可以通过查询gp_segment_configuration系统表来获取具体的Instance
故障信息。例如:
=# SELECT * FROM gp_segment_configuration
WHERE role <> preferred_role OR status <> 'u';
对于6之前的版本应该这样查询:
=# SELECT * FROM gp_segment_configuration
WHERE role <> preferred_role OR mode <> 's' OR status <> 'u';
在6版本中,没有配置Mirror时,Primary的mode是n,Master的mode永远是n。
3. 需要注意主机名,端口,初始化角色,当前角色等信息,根据这些信息可以确定到
哪些位置去排查故障原因。
版权所有:Esena(陈淼 ) 编写:陈淼 - 316 -
Greenplum Database 管理员指南 V6.2.1
4. 使用gpstate -f命令来检查Standby的同步情况:
$ gpstate -m
检查故障 Instance 的日志文件
在发生Instance故障时,日志文件将有助于排查异常的原因,每个Master、
Standby、Primary和Mirror的运行日志都在其工作目录的pg_log子目录下。
Master上的日志内容最丰富,所以,应该首先检查Master的日志。缺省情况下,
Primary和Mirror只有在出现异常时才会记录日志信息。
可以使用gplogfile命令对日志文件进行过滤,还可以结合gpssh命令对
Instance的日志进行过滤。
这里只是介绍如何查看日志,无法介绍如何从日志中发现问题,至少编者认为,
GP数据库的日志还是非常友好的,对于常见的报错,都会给出报错原因,而对于一些
没有很好的捕获的PANIC之类的信息也会输出堆栈信息,有助于定位问题原因。
使用gplogfilter命令来检查ERROR、FATAL和PANIC级别的日志:
$ gplogfilter -t gpdb-%Y-%m-%d_%H%M%S.csv
使用gplogfilter命令结合gpssh命令检查所有实例的ERROR、FATAL和PANIC
级别的日志:
$ gpssh -f seg_hosts -e '. /usr/local/greenplum-db/greenplum_path.sh;
gplogfilter -t /data*/primary/*/pg_log/gpdb*.log' > seglog.out
还可以通过-f参数查找指定的字符串:
$ gplogfilter -f 'find_string'
恢复 Instance
如果Master无法连接到某个Instance,就会在系统表中将其表记为Down状态。
版权所有:Esena(陈淼 ) 编写:陈淼 - 317 -
Greenplum Database 管理员指南 V6.2.1
直到采取恢复措施之前,被标记为Down状态的Instance将一直处于离线状态。恢复
Instance的具体流程取决于故障发生的原因和是否启用了镜像。Instance失败的原
因有很多种可能:
主机不可访问。比如,网络故障,硬件故障,文件系统故障等。
Instance进程没有启动。比如,postgres进程异常退出。
数据目录异常。比如,目录无法访问,文件系统崩溃,磁盘故障等。
下图解释了Instance故障恢复的大概流程:
注意:从上述流程可以看出,配置Mirror非常重要,Mirror是保证实例故障能快速
恢复的最有效的保障。对于没有Mirror的GP集群来说,一旦出现不可恢复的数据丢失
故障,就必须通过备份等其他手段来恢复数据,否则,数据就无法找回了。
主机故障,通常可能会导致很多个Instance故障,故障主机上的所有Primary
和Mirror都会发生故障并在系统表中被标记为Down状态(仅当集群还可以继续服务
时)。此时,如果是没有Mirror的GP数据库集群,集群将进入无法操作的状态,数据
库不能响应任何常规的查询访问,因为数据的完整性丢失。需要注意的是,对于没有配
置Mirror的GP集群来说,发生Instance故障时,并不会将故障的Instance在系统
表中标记为Down状态,因为数据库已经不可用了,此时是否标记为Down状态已经没有
意义,对于配置了Mirror的GP集群来说,出现Double Fault时,最后出现故障导致
Double Fault的Instance也不会被标记为Down。
在有Mirror的GP集群,当发生了Instance故障时,配对的Mirror或者Primary
版权所有:Esena(陈淼 ) 编写:陈淼 - 318 -
Greenplum Database 管理员指南 V6.2.1
将进入change tracking状态,要想恢复故障Instance,首先需要解决导致
Instance故障的问题,然后通过执行gprecoverseg命令来恢复故障的Instance。
主机健康时从 Mirror 恢复
1. 首先要确保Instance所在的主机可以访问。例如:
$ ping failed_instance_address
或者
$ ssh failed_instance_address -T "date"
2. 解决可能的连接故障,确保Master可以连接故障Instance所在的主机。有时,
故障Instance甚至需要重启,比如出现文件系统故障,操作系统故障等。
3. 在Instance所在主机恢复健康之后,执行gprecoverseg命令来恢复失败
Instance。例如:
$ gprecoverseg
4. 恢复进程,会尝试启动故障的Instance,之后,对于6版本来说,需要在故障
Instance上重放配对Instance记录的WAL日志,对于6之前的版本来说,需要根
据配对Instance的change tracking的信息确定需要同步哪些文件。这个过程
需要花费一些时间来完成数据的同步。
5. 在gprecoverseg命令执行完成后,可以通过gpstate -e命令来查看实例的恢
复状态,也可以通过gpstate -m来查看Mirror的同步同步状态,直到所有
Mirror的状态都是Synchronized,同步就完成了。
注意:gprecoverseg不是一定能够成功恢复故障实例的,有时,因为故障原因没有
完全排除,或者数据在故障期间发生损毁等,都可能导致恢复失败。此时,可能需要进
一步排查故障原因,或者需要进行全量恢复操作,可以联系专业技术支持。
恢复角色初始状态
当Primary发生故障并切换到Mirror之后,被激活的Mirror,其角色就变成了
版权所有:Esena(陈淼 ) 编写:陈淼 - 319 -
Greenplum Database 管理员指南 V6.2.1
Primary,而发生故障的Primary就变成了Mirror。虽然,gprecoverseg可以将
失败的Primary与配对的Instance重新同步,但其角色仍是Mirror,要将其角色恢
复到初始状态,需要执行gprecoverseg -r命令来进行切换。
在执行gprecoverseg -r恢复角色到初始状态之前,必须确保所有Instance都
处于同步状态。另外,gprecoverseg -r操作,虽然不会断开客户端的连接,但是会
导致正在执行的SQL被中断并失败回滚,所以,何时执行gprecoverseg -r,需要寻
找一个合适的时间。
注意:编者建议,6之前的版本,不要采用gprecoverseg -r的操作来恢复角色初始
状态,要采用gpstop和gpstart的方式来实现。而对于6版本,因为重启数据库不会
恢复角色的初始状态,要么执行gprecoverseg -r,要么把当前角色不对的Primary
给停掉,然后触发角色切换,这是仅有的两种选择,当然,对于6之前的版本,也可以
这样做。
1. 执行gpstate -m查看Mirror的同步状态,确保所有Mirror都处于
Synchronized状态。
$ gpstate -m
2. 如果有Resynchronizing(6之前的版本)状态的Mirror存在,则需要等待所有
状态变为Synchronized。或者,等到Mirror同步失败,总之,必须等待同步结
束。
3. 执行gprecoverseg -r命令来恢复角色的初始状态。
$ gprecoverseg -r
4. 执行gpstate -e确认角色的切换情况,以及确认切换后的Primary和Mirror重
新达到Synchronized状态。
$ gpstate -e
注意:不要在Primary和Mirror处于重新同步期间重启数据库,否则,重新启动时,
数据库仍需要恢复到同步状态,可能需要很长的时间来恢复这一状态,如果确有需要停
止数据库,应先采取相关手段让同步失败,然后再停止数据库。
恢复双宕(double fault)
双宕,就是成对的Primary和Mirror都发生了故障,发生这种情况,一般可能是
因为硬件同时出现故障。不过,这个概率极低,更多的时候,是因为维护人员没有及时
版权所有:Esena(陈淼 ) 编写:陈淼 - 320 -
Greenplum Database 管理员指南 V6.2.1
发现和处理Instance故障,放任不管,很久之后故障的Instance的配对Instance
也出现了故障,这种情况必须要杜绝。一旦出现双宕,GP数据库将不可用,而且,最
后发生故障的Instance不会在系统表中被标记为Down状态,因为那样做毫无意义。
要从双宕中恢复,可以尝试如下步骤:
1. 找到双宕的故障原因,解决所有可能的问题,确保主机恢复健康状况,并确保
Master可以访问这些主机。
2. 尝试重新启动GP数据库集群。
$ gpstop -af
数据库停止之后,尝试重新启动:
$ gpstart -a
注意:这里介绍的是尝试的步骤,不等于说这样一定可以恢复数据库,对于一般性的故
障,比如,网络故障,操作系统故障等,通过重启机器,更换故障配件等方式,主机可
以恢复到故障之前的健康状态,但对于发生数据损毁的情况,是无法恢复的。
3. 如果解决了所有的主机故障之后,数据库可以启动成功,之后,将需要使用
gprecoverseg命令来恢复其他失败的Instance。
$ gprecoverseg
注意:如果增量gprecoverseg失败,可能需要使用-F参数来进行全量恢复,或者联
系专业技术支持。
4. 在执行完成gprecoverseg命令之后,通过执行gpstate -m来确认Mirror的状
态全部为Synchronized。
$ gpstate -m
5. 如果仍有处于Down状态的Instance,那么意味着,可能之前的故障排除不够完
全,或者需要使用gprecoverseg -F来完成全量恢复。
注意:全量恢复,会先删除故障实例的数据目录,之后才会开始恢复操作,所以,在执
行全量恢复之前,一定要确保所有相关的主机都没有磁盘故障,也应该尽量找到增量恢
复失败的原因并解决相关故障,否则,即便使用全量恢复,也有可能会失败。
$ gprecoverseg -F
6. 如果有必要,根据具体的业务情况,安排空闲时间,恢复角色的初始状态。
版权所有:Esena(陈淼 ) 编写:陈淼 - 321 -
Greenplum Database 管理员指南 V6.2.1
无 Mirror 集群恢复
对于没有Mirror的集群,唯一的恢复手段,就是排除所有的操作系统故障和硬件
设备故障之后,尝试对数据库进行重启,当然数据库本身也可能需要采取必要的拯救措
施,比如重置事务日志等。
1. 确保发生故障的主机已经恢复健康,且Master可以访问该主机。例如:
$ ping failed_instance_address
或者
$ ssh failed_instance_address -T "date"
2. 解决可能的连接故障,确保Master可以连接故障Instance所在的主机。有时,
故障Instance甚至需要重启,比如出现文件系统故障,操作系统故障等。
3. 尝试重新启动GP数据库集群。
$ gpstop -af
数据库停止之后,尝试重新启动:
$ gpstart -a
注意:对于无Mirror的集群,gprecoverseg命令永远无法执行,gprecoverseg
命令,只有配置了Mirror的集群才有意义,对于配对的Primary和Mirror来说,
gprecoverseg命令的作用是,使用健康的Instance去恢复发生了故障的Instance。
主机丢失的恢复
对于硬件设备来说,并不是每种故障都是可以修复的,当主机发生不可修复的故障
时,可以选择将失败的Instance恢复到一台备用的主机上。例如:
$ gprecoverseg -o recover_config_file
版权所有:Esena(陈淼 ) 编写:陈淼 - 322 -
Greenplum Database 管理员指南 V6.2.1
通过执行该命令,会生成一个恢复的配置文件,格式如下:
<failed_host>|<port>|<data_dir>
例如:
sdw002|50000|/data/default/mgpseg0
sdw002|40000|/data/default/pgpseg1
生成上述配置文件不需要故障主机可访问,之后,将上述文件按照如下格式进行修改:
<failed_host>|<port>|<data_dir> <new_host>|<port>|<new_data_dir>
例如:
sdw002|50000|/data/default/mgpseg0 sdw003|50000|/data/default/mgpseg0
sdw002|40000|/data/default/pgpseg1 sdw003|40000|/data/default/pgpseg1
然后执行gprecoverseg -i命令,参数为修改后的文件,这样即可将故障实例恢
复到备用主机上。例如:
$ gprecoverseg -i recover_config_file
注意:对于6以前的版本来说,配置文件的格式有所不同,首先,分隔符不是管道符(|),
而是冒号(:),另外,除了有port属性之外,还有replication_port属性,即,
Primary和Mirror之间数据同步复制所需要的端口。对于6版本来说,由于
tablespace不需要在系统表中存储任何信息,所以不需要tablespace的配置文件,
而6之前的版本,配置文件中,除了缺省filespace需要修改外,其他filespace也
需要修改。例如:
filespaceOrder=gpfs:gpfs2
sdw002:50000:/data/mirror/default/mgpseg0 \
sdw002:50000:51000:/data/mirror/default/mgpseg0\
:/data/mirror/gpfs/mgpseg0:/data/mirror/gpfs2/mgpseg0
sdw002:40000:/data/primary/default/pgpseg1 \
sdw002:40001:41001:/data/primary/default/pgpseg1\
:/data/primary/gpfs/pgpseg1:/data/primary/gpfs2/pgpseg1
注意:反斜杠(\)的含义是,下一行与当前行应该是一行,这里仅仅是为了在手册中便
于排版和阅读,在真实的配置文件中,不能使用这种格式,一行记录不能换行。
版权所有:Esena(陈淼 ) 编写:陈淼 - 323 -
Greenplum Database 管理员指南 V6.2.1
恢复 Master
如果Master发生故障,GP数据库将无法继续提供服务,也将不能访问,同时,
Master到Standby的WAL同步也会停止。此时,可以在Standby上使用
gpactivatestandby命令来激活Standby成为新的Master。在激活了Standby之
后,集群将恢复到最后一个事务被提交时的状态。
激活 Standby
在Master发生故障之后,在Standby主机上,使用gpadmin用户登录,并执行
gpactivatestandby命令来激活Standby。例如:
$ gpactivatestandby -d /data/master/gpseg-1
通过-d参数来执行Master的工作目录,在5版本以后,配置了
MASTER_DATA_DIRECTORY环境变量的情况下,可以不指定-d参数,而5之前的版本,
必须指定-d参数。
在成功执行了gpactivatestandby命令之后,Standby就变成了整个GP集群的
新的Master。此时,之前发生故障的Master就退出了集群,不再属于当前集群,在
gp_segment_configuration系统表中,之前发生故障的Master的信息被清除。
注意:如果gpactivatestandby命令发现Standby没有与Master保持一致,将会报
错失败,虽然可以通过-f参数强制激活Standby,但是,除非可以确保Standby与
Master是一致的,否则,这种操作,很容易导致系统表不一致的后果。
在激活Standy为新的Master之后,可以通过执行gpstate命令来查看集群的健
康状态。此时,因为刚发生了Master到Standby的切换,集群中已经没有了Standby,
所以,gpstate的输出中,Master的状态为Active,Standby的状态为:
No master standby configured
在成功激活Standby成为新的Master之后,应该尽快初始化一个新的Standby,
比如,之前发生故障的Master,在找到故障的原因并解决了问题之后,可以作为新的
Standby加入集群中。例如:
$ gpinitstandby -s mdw001
注意:如果不及时初始化一个新的Standby,则Master将处于单点状态,没有高可用
版权所有:Esena(陈淼 ) 编写:陈淼 - 324 -
Greenplum Database 管理员指南 V6.2.1
的保护,所以,尽快初始化一个新的Standy非常重要。
恢复 Master 的高可用
恢复Master的高可用,就是再初始化一个新的Standby,对于生产环境来说,这
不应该是作为一个可选项,应该作为一个必选项。详情请参考"为现有集群配置
Standby"章节。
恢复 Master 和 Standby 到初始主机
比如,最初的Master在mdw001上,Standby在mdw002上,发生Master到
Standby的切换之后,现在的Master在mdw002上,而mdw001已经脱离集群。有时,
因为种种原因,并不希望mdw002长期以Master的角色运行,而是希望把Master回切
到mdw001。可以按照如下步骤,将Master回切到mdw001:
1. 确保发生故障的Master主机已经修复了导致故障的问题,使得其满足运行
Master的需求。对于发生重大硬件故障的主机,甚至可能需要重装系统以及重新
安装GP数据库软件等操作。
2. 在mdw002上,将原有的Master工作目录修改名称以做备份,切记不要轻易删除
目录,万一Standby的激活有问题,删除旧的目录将使得回退的可能性彻底消失。
例如:
$ mv /data/master/gpseg-1 /data/master/backup_gpseg-1
在确保不会有问题之后,可以在晚些时候删除备份的目录,不过,编者建议,如果
空间允许,应该尽量推迟删除备份目录的时间。
3. 在新的Master主机上,将旧的Master初始化为新的Standby。例如,在mdw002
上将mdw001初始化为新的Standby:
$ gpinitstandby -s mdw001
4. 在完成初始化新的Standby之后,在Master上执行gpstate -f命令,查看
Standby的同步状态。确保Sync state为sync。
$ gpstate -f
版权所有:Esena(陈淼 ) 编写:陈淼 - 325 -
Greenplum Database 管理员指南 V6.2.1
5. 在合适的时间,停掉当前的Master(mdw002主机上),因为该操作会导致正在执
行的SQL全部中断回滚,所有的客户端连接被断开,所以,应该安排一个合适的时
间来执行。例如:
$ gpstop -afm
6. 在Standby(mdw001)上执行gpactivatestandby命令来激活Standby为
Master。例如:
$ gpactivatestandby -d $MASTER_DATA_DIRECTORY
7. 在激活Standy为新的Master之后,可以通过执行gpstate命令来查看集群的健
康状态。gpstate的输出中,Master的状态为Active,Standby的状态为:
No master standby configured
8. 在原始的Standby(mdw002)主机上,将原有的Master工作目录修改名称以做备
份,切记不要轻易删除目录,万一Standby的激活有问题,删除旧的目录将使得
回退的可能性彻底消失。例如:
$ mv /data/master/gpseg-1 /data/master/backup_gpseg-1
9. 在新的Master主机上,将旧的Master初始化为新的Standby。例如,在mdw001
上将mdw002初始化为新的Standby:
$ gpinitstandby -s mdw002
10. 在完成初始化新的Standby之后,在Master上执行gpstate -f命令,查看
Standby的同步状态。确保Sync state为sync。
$ gpstate -f
实际上,整个过程就是不断的切换Master和Standby,只是需要在每个步骤,务必做
到确认集群的健康状态和Master与Standby的同步状态。另外,还务必规划好操作的
时间,尽可能减少切换过程对上层应用的影响。
版权所有:Esena(陈淼 ) 编写:陈淼 - 326 -
Greenplum Database 管理员指南 V6.2.1
第十五章:备份与恢复
关于备份恢复,这是一个很大的话题,首先,GP目前还不支持物理备份,对于MPP
数据库来说,在线物理备份是极大的挑战,首先要确保备份的时间点,所有修改刷到磁
盘文件,然后做全局分布式快照,之后再进行物理文件的复制,才能确保数据库可以使
用这些备份的文件恢复到备份的时间点。
目前所有的备份命令,实质上,都是将数据库中的数据导出为平面文件。在需要恢
复时,再将这些数据文件重新加载到数据库中。
关于备份的重要性,前面的章节也介绍了很多,备份,可以确保数据一定可以恢复
到某个备份的时间点,当然,这个时间点是相对的,不是说,在某年某月某日,几时几
分几秒开始备份,之后做恢复,数据库就和这个时间点的状态完全一样,因为,备份是
在线的,为了尽可能的降低对业务的影响,不可能做到绝对的一致性保证,如果要这么
做,会付出极大的代价。
在实现gpbackup之前,不管是gp_dump命令还是gpcrondump命令,都是先对所
有业务表进行显式的LOCK,之后再进行并行数据COPY OUT,这是为了确保在备份期
间,数据不会被其他事务修改,然而,即便如此,在逐个表LOCK期间,仍可能有尚未
被LOCK的表数据被修改,所以,这也不能提供绝对的一致性保证,除非直接对系统表
加ACCESS EXCLUSIVE锁,或者开启可重复读事务隔离级别,然而,如果这样做,注
定会和其他任意的操作产生冲突。
并行系统的备份,总是要在可用性和一致性之间做出平衡,经过多年的摸索,终于
有了gpbackup,相比之前的gp_dump或者gpcrondump,有了极大的改善,降低了锁
级别的要求,同时,允许每个表备份为单独的文件,从而可以隔离单个表的备份失败。
备份与恢复概述
GP支持并行备份恢复,同时,仍支持串行备份恢复,串行备份,主要是继承了
PostgreSQL的原生的COPY命令。并行备份的性能,与计算节点主机的数量是无关的,
因为每个计算实例,是同时将数据导出到所在主机的本地磁盘的,当然,如果数据直接
备份到共享文件系统,那么备份的性能可能会受到共享文件系统的影响。如果使用串行
备份和恢复,那么,所有的数据都需要经过Master来处理,所以,所有的备份数据会
集中存储,备份存储的容量将是一个很大的挑战,同时,对Master的计算资源和网络
带宽也会是极大的占用,而且,性能远不如并行备份恢复,可能是数量级的差异。
除非经过专业技术支持的评估确认,否则,不要在大容量生产环境尝试串行备份恢
复操作,因为其影响可能是难以接受的。
版权所有:Esena(陈淼 ) 编写:陈淼 - 327 -
Greenplum Database 管理员指南 V6.2.1
串行备份 pg_dump
使用PostgreSQL的pg_dump或者pg_dumpall命令可以将集群的数据备份到
Master主机上,这对于一个尺寸较大的集群来说,可能是无法承受的,无论是性能还
是备份的容量,都会是极大的挑战。如下图所示,所有的数据都需要传输给Master并
导出到Master的本地文件。
串行备份,应该只在一些极其特殊的场景下使用,往往,Master不可能有足够的
存储空间来存放全部的备份数据。需要注意的是,pg_dump不能备份包含外部表的分
区表,备份时会报错:
pg_dump: [archiver (db)] query failed: ERROR: cannot copy from relation
"tablename" which has external partition(s)
HINT: Try the COPY (SELECT ...) TO variant.
pg_dump: [archiver (db)] query was: COPY tablename (a, b, c, d, e) TO stdout;
用外部表做分区,看起来很美好,然而,使用中一定会有很多的限制,编者认为,
如无必要,还是要少用或者不用。
pg_restore命令只能恢复由pg_dump命令或者pg_dumpall命令备份出来的压
缩格式,所以,使用缺省参数通过pg_dump命令和pg_dumpall命令备份出来的平面
版权所有:Esena(陈淼 ) 编写:陈淼 - 328 -
Greenplum Database 管理员指南 V6.2.1
文件是无法通过pg_restore来恢复的。例如:
$ pg_dump postgres -f postgres.bak -Fc
$ pg_restore -d restore postgres.bak
如果要恢复从PostgreSQL的备份,最好将DDL和数据分开备份,这样便于修改表
的分布键和压缩等属性,否则,分布键将按照缺省规律进行自动选择,表的存储选项也
按照缺省值进行自动选择。可以参见如下参数来修改缺省行为:
gp_create_table_random_default_distribution
gp_default_storage_options
对于以前的gp_dump和gpcrondump并行备份出来的文件,如果确有必要,可以
拷贝到Master上来串行恢复,当然恢复的方式不一定是pg_restore,可能是psql
直接执行备份文件,对于压缩文件,也可以边解压边执行,或者先解压再执行。不过,
串行恢复的性能和并行恢复可能是数量级的差异,对于大规模集群来说,无实际意义。
还可以使用COPY命令将集群中的数据,从Master导出到文件,以实现串行的数
据备份,这同样有性能受限和过度消耗Master资源的问题,不适合操作大量数据。
并行备份 gpbackup 与 gprestore
虽然编者不用gpbackup和gprestore,但是,编者没有更合适的关于并行备份
恢复的工具可以讲解(虽然编者有一套备份恢复的工具,但不适合作为通用技术来讲
述),所以,那就按照gpbackup和gprestore的文档来介绍一下。实际上,不管是现
在的gpbackup还是以前的gp_dump和gpcrondump,都是所有Primary并行将数据
从数据库中进行COPY OUT操作,原理是没有任何区别的,差异在于命令的具体实现和
包装控制。
编者曾经给gpbackup提出过建议,通过全量备份和增量备份来滚动合并形成新的
全量,这样,可以在只有一份全量备份的情况下,动态合并出新的全量,并清理过期的
备份数据,可以保证有一份全量和指定数量的增量,从而可以长期稳定控制总体的备份
尺寸,同时,不需要多次进行全量备份。不过,编者的建议没有被gpbackup的研发采
纳,目前这一功能仅在编者自己编写的备份命令中被实现,所以,从这个角度来说,编
者一直吹牛说自己的备份命令是目前最先进的。
gpbackup会将一些备份操作本身的元数据信息和数据库的DDL信息存储在
Master上,而业务表中的数据,会通过COPY . . . ON SEGMENT命令将数据备份
到每个Primary所在的主机上,采用的是压缩CSV格式。编者认为,CSV格式并没有特
别的优势,采用gzip压缩也没有特别的优势,首先CSV格式输出也是需要转义的,因
为数据库中的数据总是有各种可能,使用缺省的TAB分割的文本格式输出没有什么不好,
版权所有:Esena(陈淼 ) 编写:陈淼 - 329 -
Greenplum Database 管理员指南 V6.2.1
而且不管是对于外部表加载还是COPY加载,都不需要指定格式,因为TAB分割的文本
格式是缺省格式,这也许是最好的,再说gzip压缩,已经引入zstd压缩算法了,应该
考虑使用zstd压缩,不管是压缩解压的效率还是尺寸,对gzip都是碾压性的优势。
gpbackup将数据表中的数据备份为文件时,使用的是TABLE的oid作为文件名,
这肯定是为了解决表名中包含各种特殊字符的问题,不过,如果后续需要查找数据文件,
需要稍微麻烦一点。gpbackup会在Master上存储oid与表名之间的对应关系。
目前,gpbackup缺省情况下,会将每个表在每个Primary上备份为一个单独的文
件,这样可以便于对单表进行恢复操作,同时,也为使用其他加载数据的方式来恢复数
据提供了可能性,想想以前的备份命令,整个Primary的备份被压缩为一个gz文件,
想要只恢复一个文件是何等的困难。另外,还可以通过--leaf-partition-data参
数来控制,将不同的叶子分区备份为单独的文件,从而可以针对叶子分区进行单独的备
份和恢复。相较于以前的本分命令,gpbackup无疑是有了巨大的进步。
条件与限制
gpbackup与gprestore命令,并不适用任意版本,仅适用如下版本:
GPDB 4.3版本中,4.3.22及以后的版本
GPDB 5版本中,5.5.0及以后的版本
GPDB 6版本中,6.0.0及以后的版本
gpbackup和gprestore还有如下的限制:
gpbackup不会为子分区备份索引,如果ROOT分区有索引,在恢复DDL时,在ROOT
分区创建索引时,会自动在叶子分区也创建索引,这样将难以避免叶子分区创建索
引时会有索引已存在的报错。还有就是,如果分区表的叶子分区中有外部表,同时
分区表上又有索引,在恢复DDL时,同样会遭遇报错,因为在外部表上是无法创建
索引的。又是一个外部表作为叶子分区的坑。
gpbackup允许同时执行多个gpbackup命令,但是每个命令执行的时候,不能有
相同的时间戳。编者看到这一条真的笑了,这个是个糟糕的设计,绝对不应该允许
一个集群中同时有多个gpbackup命令在执行,要解决这个问题并不复杂,只需要
在开始命令时加一个文件锁即可,编者的备份命令绝对不会允许同时有多个在执行。
数据库对象的过滤功能,目前仅支持Schema和Table的筛选。编者觉得这个不能
叫限制,不然,除了这些,还能筛选啥呢,关键就是选择Table的范围,因为只有
Table中存储有业务数据。
版权所有:Esena(陈淼 ) 编写:陈淼 - 330 -
Greenplum Database 管理员指南 V6.2.1
当被备份的分区表中,包含不同Schema的叶子分区时(编者觉得这种操作就是闲
的),只要有叶子分区,其Schema被包含在备份范围,则,其DDL信息就会被备份,
哪怕还同时指定了其他叶子分区所属的Schema被排除,DDL信息依然会被备份。
其实简单的来说就是,分区表是一个整体,只要有一个叶子分区需要被备份,那么
DDL就要整体备份,不能只备份一个叶子分区的DDL,因为叶子分区不能独立存在。
如果在执行gpbackup命令的时候,指定了--single-data-file参数,每个实
例上的备份文件将会是一个整体大文件,而不是每个表一个备份文件,这样的话,
在执行gprestore命令时,将不能进行多表并行恢复,--jobs参数不能大于1,
因为gpbackup使用的压缩算法不是并行压缩算法,也不可能实现并行解压。
--exclude-table-file参数不能与--leaf-partition-data参数一同使
用?这个有待改进啊,虽然可以通过--exclude-table-file参数来排除叶子分
区,但是感觉怪怪的。编者的备份命令就很好的处理了这些关系,排除的表可以是
ROOT分区也可以是叶子分区,希望gpbackup以后可以改进这一块的逻辑关系,
虽然感觉逻辑上有点绕。
gpbackup命令和DDL命令一起执行可能会导致gpbackup失败报错,比如,在备
份期间删除了某张表,会遭遇如下的报错信息:
ERROR: relation <schema.table> does not exist
编者也不想过多解释这个问题,因为编者的备份命令遇到这个情况时,将会直接
跳过这个表,认为其已经成功,不做任何处理,因为备份本身不能做到绝对的一致
性,所以,必须要有所妥协。
gpbackup命令生成的备份数据,只能在相同规模的集群使用gprestore来恢复。
实际上,因为使用的是COPY ON SEGMENT命令来完成的数据导出和导入,如果使
用的是外部表,就可以不受这个限制。
gpbackup 和 gprestore 包含的对象类型
这里介绍gpbackup备份哪些数据库对象,这是根据官方文档翻译整理的内容,编
者没有逐个确认,如有出入或者变更,请以官方文档或者实际的备份结果为准。
备份恢复的根本目的是为了能够做到灾难恢复,但是,备份并不能将数据库在某个
时间点的所有状态完全保存,备份的主要范围还是对象的定义和业务数据,并不包含各
种配置文件等信息。
备份的对象定义信息,包括指定的数据库内的对象信息,还有全局对象信息。例如,
版权所有:Esena(陈淼 ) 编写:陈淼 - 331 -
Greenplum Database 管理员指南 V6.2.1
角色,资源组,资源队列等定义是全局信息,表定义,索引,视图,表中的数据等属于
指定数据库内的信息。gpbackup备份的对象类型如下:
数据库内的对象
全局对象
编者认为,会备份角色和数据库级别的参数设置
Tablespace--表空间
Schema--模式定义
Database--数据库
Language--过程语言定义
Database级别的GUC参数
Sequence--序列定义
资源组的定义
Comment--注释信息
资源队列的定义
Table--表定义和数据
角色定义
Index--索引定义
角色访问Database的权限
Owner--对象的所有者信息
Writable External Table--可写外部表的DDL
Readable External Table--可读外部表的DDL
Function--函数定义
Aggregate--聚合函数定义
Cast--类型转换
Type--自定义类型
View--视图定义
Materialized View--物化视图定义(6.2.1+版本)
Protocol--外部表的协议
Trigger--似乎没有什么意义,因为GP不支持自定义触发器
Rule--规则定义
Domain--Type的别名定义
Operator--操作符
Conversion--编码转换
Extension--扩展
全文检索的相关信息
注:官方文档说会备份Session级别的GUC参数设置,编者认为这一定是笔误。系统
Schema的信息不会被备份,因为不需要,任何一个空的Database都会包含这些系统
自带的Schema。
执行一个 gpbackup 备份
要执行一个gpbackup备份,只需要执行gpbackup命令并配合适当的参数即可。例如:
$ gpbackup --dbname gpmagic --jobs 6 --leaf-partition-data --backup-dir
/data
版权所有:Esena(陈淼 ) 编写:陈淼 - 332 -
Greenplum Database 管理员指南 V6.2.1
--jobs参数指定了同时进行备份的表的数量,也可以理解为并发数,通常应该考
虑选择合适的并发数以充分利用系统的计算资源。--leaf-partition-data参数指
定了如何处理分区表,即,将每个叶子分区单独进行备份,而不是将这个分区表进行整
体备份,这往往是更合适的选择。例如:
$ gpbackup --dbname gpmagic --jobs 6 --leaf-partition-data --backup-dir
/data
[INFO]:-Starting backup of database gpmagic
[INFO]:-Backup Timestamp = 20200811135758
[INFO]:-Backup Database = gpmagic
[INFO]:-Gathering table state information
[INFO]:-Acquiring ACCESS SHARE locks on tables
Locks acquired:
95 / 95
[=================================================] 100.00% 0s
[INFO]:-Gathering additional table metadata
[INFO]:-Getting partition definitions
[INFO]:-Getting storage information
[INFO]:-Getting child partitions with altered schema
[INFO]:-Metadata will be written to ${backdir}/gpbackup_xx_metadata.sql
[INFO]:-Writing global database metadata
[INFO]:-Global database metadata backup complete
[INFO]:-Writing pre-data metadata
[INFO]:-Pre-data metadata metadata backup complete
[INFO]:-Writing post-data metadata
[INFO]:-Post-data metadata backup complete
[INFO]:-Writing data to file
Tables backed up:
67 / 67
[=================================================] 100.00% 0s
[INFO]:-Skipped data backup of 17 external/foreign table(s).
[INFO]:-See ${logdir}/gpbackup_xx.log for a complete list of skipped tables.
[INFO]:-Data backup complete
[INFO]:-Found neither
${cmddir}/gp_email_contacts.yaml nor ${cmddir}/gp_email_contacts.yaml
[INFO]:-Email containing gpbackup report ${backdir}/gpbackup_xxx_report
will not be sent
[INFO]:-Backup completed successfully
备份命令在Master上产生了4个信息文件。例如:
$ ls -1
${backdir}/xx/xxxx/
gpbackup_xxxx_config.yaml
gpbackup_xxxx_metadata.sql
gpbackup_xxxx_report
gpbackup_xxxx_toc.yaml
版权所有:Esena(陈淼 ) 编写:陈淼 - 333 -
Greenplum Database 管理员指南 V6.2.1
gpbackup_xxx_config.yaml是备份配置文件,记录着命令的参数和备份的表
的范围情况。gpbackup_xxx_metadata.sql是数据库的DDL备份文件,当然也包含
了Global对象的DDL信息。gpbackup_xxx_report是备份命令的执行报告,主要包
括执行的起止时间,备份的对象数量,尺寸等。gpbackup_xxx_toc.yaml是备份命
令记录数据库对象属性和增量状态等信息的文件,其中非常重要的信息是,表名对应的
oid的值,真实的数据备份出来的文件名称使用的是oid的值,而不是表名本身,当我
们需要查找某个表备出的文件时,这个信息是必须的,一旦丢失该文件,备份将失去意
义。
注意:缺省不指定--backup-dir参数时,备份生成的数据文件会存储到每个Primary
的工作目录的backups子目录下,如果指定了--backup-dir参数,备份生成的数据
文件会统一存储到指定的目录,当然,实际存储时仍然会按照不同的实例分成不同的子
目录。
注意:在有了物化视图之后(从6.2.1版本开始支持),物化视图的备份,只是备份了
DDL信息,并不会备份物化视图中的数据,因为,即便备份了物化视图的数据,也无法
使用这些数据来恢复物化视图,物化视图的数据只能通过REFRESH MATERIALIZED
VIEW命令来修改。
使用 gprestore 恢复一个备份
要执行gprestore来恢复一个已有的备份到数据库中,首先要确定备份所在的目
录和备份的时间戳。如果数据库不存在,可能需要先创建好数据库或者用
--create-db参数,如果自动创建的Database各方面的设置不满足要求,还是应该
先创建好数据库对象。例如:
$ gprestore --backup-dir /data --jobs 6 --redirect-db restore --timestamp
xxxx
其中与gpbackup不同的参数有--redirect-db和--timestamp,
--redirect-db指定了要将备份数据恢复到另一个不同名称的数据库中,
--timestamp指定了恢复哪一个备份。
$ gprestore --backup-dir /data --jobs 6 --redirect-db restore --timestamp
xxxx
[INFO]:-Restore Key = xxxx
[INFO]:-Restoring pre-data metadata
Pre-data objects restored:
270 / 270
[=================================================] 100.00% 1s
版权所有:Esena(陈淼 ) 编写:陈淼 - 334 -
Greenplum Database 管理员指南 V6.2.1
[INFO]:-Pre-data metadata restore complete
Tables restored:
67 / 67
[=============================================================] 100.00%
2s
[INFO]:-Data restore complete
[INFO]:-Restoring post-data metadata
Post-data objects restored:
5 / 5
[====================================================] 100.00% 0s
[INFO]:-Post-data metadata restore complete
[INFO]:-Found neither ${cmddir}/gp_email_contacts.yaml nor
${cmddir}/gp_email_contacts.yaml
[INFO]:-Email containing gprestore report ${backdir}/gprestore_xxx_report
will not be sent
[INFO]:-Restore completed successfully
对于增量备份来说,--timestamp应该指定要恢复到哪个增量备份,这样,
gprestore会自动判断恢复每张表的最新备份数据。
注意:如果有物化视图,在gprestore恢复完成表中的数据之后,还需要手动刷新物
化视图才能使用物化视图,至少编者在GP 6.10.0版本和gprestore 1.18.1版本上
实测如此。
更多关于gpbackup和gprestore的信息,编者不再继续介绍,详情请参考命令的
help信息和对应的官方文档,因为编者觉得这实在没什么好说的。如果购买了编者的
专业售后服务,编者会提供一套更高效易用的备份恢复方案,包括更快速的DDL备份和
并行DDL恢复等。
版权所有:Esena(陈淼 ) 编写:陈淼 - 335 -
Greenplum Database 管理员指南 V6.2.1
第十六章:扩容
扩容,一般说的是增加计算节点主机的数量,以增加存储数据的空间和计算能力,
当然,为现有集群的计算节点主机增加Primary数量也是可以的,但是,对于生产系
统来说一般不会有这种操作,因为这将涉及到很多指标的重新评估。
一般来说,扩容会带来性能的提升,不过,这个问题不能简单的理解为性能与计算
节点主机的个数成正比,例如,主机的个数增加一倍,相同的SQL执行时间就缩短一半,
这种理解是不准确的,编者在很多年前就纠正过这个概念,准确的说,预期的结果是,
在单个Primary的数据量不变的情况下,N个主机环境对应的SQL性能和2N个主机环境
对应的SQL性能应该相当。不过,也并不是所有的SQL都能符合这种预期,因为任何环
境都难以避免数据倾斜和计算倾斜的情况,一旦存在倾斜的情况,扩容将无法线性提升
这种SQL的性能。
通常,数据仓库和数据集市的数据量会随着时间持续增长,一方面,业务本身在增
长,另一方面,因为数据保存周期一般较长,在建设初期,存量数据也会持续增长,直
到运行时间接近数据最长保存周期。随着项目的运行,可能还会有不断的新业务的接入,
这也需要更多的数据容量和计算能力。不过,编者想提醒的是,不应该只关心容量的问
题,也要考虑到计算能力的平衡,一味的追求容量,而不考虑计算能力也是不妥的,随
着集群的运行,新的业务和更大数据量的计算场景也将需要更多的计算资源。
虽然,可以在建设的初期阶段就考虑长期的业务和数据的增长情况,而且,这也是
很好的规划,但是,这样的规划往往可能会带来难以接受的单次投资代价,所以,保持
合理的扩容周期可能更现实。
由于GP是MPP数据库,当向现有集群加入新的计算节点主机资源时,需要注意资源
的均衡和对等,因为Instance之间是互相平等的,所以,新扩展的Instance和原有
的Instance应该拥有等量的存储空间和计算能力,避免出现短板效应。
当进行增加计算节点主机数量的扩容操作时,扩容后的可用容量和计算能力,与直
接建设相同规模的集群是一样的,如果扩容前后没有感受到显著的性能提升,那一定是
在其他方面出了问题,比如,计算能力的不平衡等。
GP在扩容期间,并不需要很长的业务中断时间,在数据重分布期间,常规的批处
理操作和即席查询仍然可以继续使用。因此,DBA可以根据数据库的负载情况来灵活的
安排数据重分布的时间窗口,随时可以开始和停止数据重分布操作,也可以根据数据表
的重要性来调整数据重分布的顺序,让需要先做数据重分布的表先做重分布,或者先重
分布尺寸较小的表,为尺寸大的表腾出足够的磁盘空间以满足数据重分布的可用容量要
求。
数据重分布的过程,采用的是标准的SQL操作,且有事务保证,所以,DBA可以很
方便的来管理数据重分布的过程。随时中断数据重分布的操作,并不会导致正在进行数
版权所有:Esena(陈淼 ) 编写:陈淼 - 336 -
Greenplum Database 管理员指南 V6.2.1
据重分布的表的数据记录发生任何的损坏或者丢失,因为,中断的是一个标准的数据库
事务,表的状态将回到重分布之前。数据重分布期间,Primary和Mirror的同步机制
不受影响,因此,高可用功能不受影响。
扩容概述
当需要进行扩容时,下面的目标是可预期的:
容量和性能的提升。扩容后的可用容量和计算能力,与直接建设相同规模的集群是
一样的。
扩容期间不会中断数据库对外服务的能力。
数据重分布操作具备事务保证。
扩容期间,数据库的高可用机制正常工作。
扩容期间,故障恢复功能依然正常工作。
扩容过程,采用GP数据库的标准操作,便于DBA排查和解决问题。
扩容是一个较长的过程,DBA可以灵活的安排数据重分布的阶段和顺序,可以随时
开始和停止数据重分布操作。
与扩容操作执行gpexpand命令相比,在这之前的硬件和环境的准备工作显得更为
重要,工作量也更大,涉及的知识和内容也更复杂,往往需要多个团队的协同合作来完
成。比如,网络方面,会涉及到交换机的扩展,当现有的内部互联的交换机可用接口数
量不足时,会涉及到新的交换机如何扩展,是堆叠或级联,往往可能会带来很大的影响。
比如,现有的机柜,可用空间不足,需要重新规划新的机架位置,以及这些位置之间的
网络连接布局。比如,高密度堆放机器时的设备供电问题。比如,新的机器可能与现有
机器在详细的配置和品牌或者型号上有细微的差异,需要对机器的总体性能进行全新的
评估,即便相同型号配置的机器,也需要进行必要的性能评估和压力测试,以排除可能
导致扩容无法达到预期效果的隐患。
总之,扩容的准备工作,与新建集群相比,只会更复杂,所有新建集群的工作都需
要做,同时还需要与现有集群的情况进行横向对比,以确保用于扩容的机器符合扩容的
要求。
扩容前的准备工作,包括,新机器的配置和参数的确认,采购,上架,加电,安装
操作系统,配置网络,性能测试和评估,压力测试,与现有集群的计算节点主机进行对
比,不满足扩容要求的,还需要针对特定的问题进行整改,之后重新进行上述的操作,
版权所有:Esena(陈淼 ) 编写:陈淼 - 337 -
Greenplum Database 管理员指南 V6.2.1
直至满足扩容的要求。
在上述准备工作全部完成之后,就可以进行具体的扩容实施了,包括,数据库软件
的安装,操作系统参数的修改,hosts文件的修改,目录和用户的创建,权限的修改,
互信的建立等。所有这些准备工作,具体内容可以参考"安装部署与初始化"章节。
在完成了服务器的安装配置和测试之后,就可以进入数据库软件层面的扩容操作了,
数据库操作阶段,在6版本,已经做到尽可能的减少对业务的影响,扩容过程中可以保
证事务性和一致性,可以保证高可用正常工作,数据库的访问基本不受扩容的影响,只
是在扩容配置阶段可能会对系统表有短暂的加锁,以确保系统表数据的一致性,在数据
重分布阶段对正在进行重分布的表加访问排它锁,以确保ALTER TABLE操作的事务性
和一致性。对于6之前的版本来说,扩容还不能做到绝对的在线操作,扩容配置阶段,
数据库需要有重启操作,数据库的连接会被断开,一定会对业务产生影响。
第一阶段,将新的主机加入集群,在系统表中增加新的主机信息和Instance信息。
由于这一阶段需要对系统表上锁以确保一致性,所以,最好安排在数据库空闲时间
段来进行。在线扩容,不是绝对的无感知,只是影响很小,以至于不需要重启数据
库和中断客户端连接,也不需要取消正在执行的SQL语句。经过编者实际测试,扩
容过程中,数据库查询可以正常进行,连接不中断,查询无报错。第一阶段的工作
包括:
根据Master的数据目录,创建扩容Instance的模板压缩文件。
分发模板压缩文件到扩容的新主机上。
创建新的Instance并完成初始化和启动。
在新的Instance上创建数据库和其中的对象。
在postgres库中创建gpexpand模式,并将业务表的信息保存在gpexpand
模式下的扩容配置表中。在6之前的版本,需要通过-D参数来指定用于保存
gpexpand模式及相关业务表信息的数据库名称。gpexpand模式下的表和视
图,可以用于控制扩容过程和查看扩容进度。
在完成系统表的更新之后,新扩容的Instance就处于可用状态了,新的计算
节点主机的资源也已经加入集群之中。
新的Instance在成功加入集群配置中后,马上就会参与数据的查询和加载等
操作,此时,新扩展主机的计算资源可以被利用,新建的表,数据也会分布
到新扩展的主机上的Instance上。但是,原有的表,数据是倾斜的,依然只
存储在扩展前的主机和Instance上,必须通过数据的重分布,才能将原有的
表中的数据也分布到新的主机或Instance上。
在此期间,有些查询可能会有一定的性能影响,比如,有些表,按照新的集
版权所有:Esena(陈淼 ) 编写:陈淼 - 338 -
Greenplum Database 管理员指南 V6.2.1
群规模分布,有些表,按照原有的集群规模分布,在进行关联查询时,可能
会涉及到更多的数据重分布操作。
第二阶段,数据重分布。根据第一阶段操作,在gpexpand模式中生成的重分布的
表清单信息,第二阶段对这些表,进行数据重分布。对于每张表来说:
gpexpand命令,根据表的分布键信息,将数据在包含新增Instance在内的
所有Instance之间重分布数据。
在扩容配置表中,记录该表的状态,是否已经完成数据的重分布。
在完成数据重分布之后,将可以生成更符合扩容后集群规模的执行计划。
在所有表都完成了数据重分布操作之后,整个扩容操作就全部完成了。
重要:在扩容之前进行的gpbackup备份,在扩容之后,gprestore命令无法在新规
模的集群上,使用这些备份文件来进行恢复。所以,如果规划了备份,扩容之后,应该
尽快进行重新备份。
数据重分布过程,耗时的长短,与单个主机的数据规模正相关,不过,对于健康的
配置均衡的集群来说,可能是几个小时的时间,对于配置不均衡或者使用不当的集群来
说,也可能会花费几天的时间,在数据重分布期间,会有较大的资源消耗,包括CPU,
网络带宽和磁盘IO资源。为了尽可能的降低数据重分布对业务的影响,DBA可以灵活的
安排开始和中断数据重分布的操作,可以调整需要进行重分布的表之间的优先级顺序
(编者认为这个几乎没有太大的意义,因为往往难以界定这种顺序),还可以根据系统
的压力,控制每次数据重分布操作的并行度--即,同时有多少张表进行数据重分布。
在开始下一次的数据重分布时,可以根据之前操作的情况,结合集群的资源使用情
况,以及接下来的业务情况进行重新评估,选择更合适的参数,往往是调整并行度参数。
在使用gpexpand命令来完成数据库阶段的操作时,通常会分为下面4个步骤:
1. 创建扩容配置文件。可以不带任何参数的直接执行gpexpand命令,进入交互式操
作界面,根据提示信息,输入需要新增的主机的主机名(可以输入英文逗号分隔的
多个主机名),以及,需要在现有计算节点主机上增加的Primary的数量(虽然支
持,但是对于生产环境,需要谨慎评估)。完成交互式输入之后,将会自动生成一
个扩容配置文件。注意,如果有尚未完成或者尚未清理的gpexpand模式存在,新
的扩容操作将无法开始。例如:
$ gpexpand
Would you like to initiate a new System Expansion Yy|Nn (default=N):
> y
版权所有:Esena(陈淼 ) 编写:陈淼 - 339 -
Greenplum Database 管理员指南 V6.2.1
Enter a comma separated list of new hosts you want
to add to your array. Do not include interface hostnames.
**Enter a blank line to only add segments to existing hosts**[]:
> sdw003,sdw004
How many new primary segments per host do you want to add? (default=0):
>
Input configuration file was written to 'gpexpand_inputfile_%Y%m%d_%H%M%S'
如果有需要,在这一步,可能需要对已经生成的扩容配置文件进行手动编辑,修改
需要定制化的属性信息,之后再进行接下来的操作。编者的自动集群安装部署命令,
可以自动完成这一步,以及这一步之前的准备工作,包括且不限于,操作系统的参
数修改和配置,数据库软件的安装,hosts的修改,互信的建立等,把装好操作系
统和配置好网络之后的准备工作全部自动完成。
2. 执行Instance的安装初始化和启动以及完成扩容配置。gpexpand命令会根据
Master的目录创建模版压缩文件,根据输入的配置文件的信息,创建新Instance
的目录,初始化并启动新的Instance,在新的Instance上创建好所有需要的数
据表文件等信息,并将集群中所有Database中需要进行数据重分布的表的信息存
储到gpexpand模式中。在这一步操作完成之后,扩容操作就成功了,虽然数据还
没有完成重分布,但是,配置的修改已经成功完成,不能回退,所以,在进行这一
步操作之前,一定要确保扩容配置文件已经符合预期。这一步操作没有提示是否继
续的确认信息,如果扩容配置文件没有问题,则会自动完成扩容配置工作。
$ gpexpand -i gpexpand_inputfile_%Y%m%d_%H%M%S'
3. 数据重分布。在完成了新Instance的安装初始化和启动之后,要进一步完成全部
的扩容操作,还需要进行数据的重分布,哪些表需要被重分布,已经记录在
gpexpand模式中。根据集群规模和负载的情况,可以灵活安排数据重分布的时间
窗口,可以一次完成,也可以分多次完成,正在执行重分布操作时,可以随时中断
重分布操作。正在被重分布的表或者叶子分区(至少到目前为止,6版本还不能对
叶子分区单独执行EXPAND TABLE操作),任何的访问都会因为锁等待而不能立即
得到执行,需要等待该表的重分布完成之后,才能获取必要的锁。在数据重分布的
过程中,集群的性能,随着数据重分布的不断完成,会逐步得到提升,直到全部表
都完成重分布。实际上,数据的重分布操作也是普通的SQL命令。例如:
ALTER TABLE ONLY tablename EXPAND TABLE;
不过,EXPAND TABLE不再是简单的REORGANIZE,这与6之前的版本不同,6版
本开始,因为要支持真正意义上的在线扩容,通过gp_distribution_policy
系统表的numsegments字段来识别一张表是否已经完成扩容的数据重分布操作。
版权所有:Esena(陈淼 ) 编写:陈淼 - 340 -
Greenplum Database 管理员指南 V6.2.1
4. 清理用于扩容的gpexpand模式。
$ gpexpand -c
对于6版本来说,扩容操作不需要重启数据库,但是,对于使用者来说,进行扩容
的操作步骤与之前的版本相比,几乎没有差异。更多关于gpexpand命令的使用说明,
可以参考相关的帮助信息。
GP 数据库扩容规划
细致的规划,对GP集群的成功扩容,非常重要,否则,可能会在扩容过程中遭遇
各种不确定因素的困扰,比如,性能不符合预期,甚至扩容失败等。没有无缘无故的成
功,也没有无缘无故的失败,专业技术支持的最大价值,是让意外的概率降到最低。
扩容准备工作检查清单
下面的表格总结了GP数据库扩展的任务清单。
在线准备工作,该部分工作对现有 GP 数据库没有任何影响
原有 GP 集群正常使用
规划硬件配置和数量,采购用于扩容的新硬件设备,准备好扩容的网络环境,新设备上电,
□
安装操作系统,配置网络。
□
在用于扩容的新主机上安装 GP 数据库软件。
修改操作系统参数,挂载文件系统,创建用户,创建数据目录并修改权限。
□
规划扩容计划,每个主机的 Primary 的数量,磁盘目录的安排,Mirror 的策略。
□
□
在现有主机和用于扩容的新主机之间建立 ssh 互信。
使用 gpcheckperf 命令测试用于扩容的新主机的磁盘 IO 性能和网络性能。
□
检查 Master 的 pg_log 目录和 gpperfmon/data 目录,确保没有尺寸过大的文件,如
□
果有,应该备份转移到数据库工作目录以外的位置。
□
规划一个可接受的时间窗口,以便可以在该时间窗口内,进行扩容配置和数据重分布操作。
版权所有:Esena(陈淼 ) 编写:陈淼 - 341 -
Greenplum Database 管理员指南 V6.2.1
离线准备工作,该部分工作进行时,需要停止一切数据库访问
保持继续使用数据库将难以保证这部分工作的严谨性
使用 gpcheckcat 命令检查现有 GP 数据库中是否有 Catalog 问题,如果发现有
□
Catalog 问题,则需要先修复这些问题。
使用 gpcheckperf 命令测试所有主机的磁盘 IO 性能和网络性能,包括原有计算节点主
□
机和用于扩容的新主机。
在线扩容配置,该部分工作对现有 GP 数据库的可用性没有影响
原有 GP 集群可以正常使用,可能会有短时间的锁等待
□
使用 gpexpand 命令生成扩容配置文件。
使用上一步生成的扩容配置文件,执行gpexpand -i input_file命令,将新的主机加
□
入集群,并完成新Instance的初始化和启动,生成gpexpand模式及重分布信息。
在线数据重分布,该部分工作对现有 GP 数据库的可用性没有影响
整个 GP 集群可以正常使用,可能会有短时间的锁等待
在开始数据重分布之前,应该停止所有的备份,跨集群传输等操作,或者其他磁盘消耗太
□
高的操作。也可以选择在业务空闲时段进行数据重分布。
执行 gpexpand 命令来进行数据重分布。
□
在完成数据重分布之后,执行 gpexpand -c 来清除 gpexpand 模式。
□
在完成全部的扩容操作之后,应该执行 analyze 来更新统计信息。
□
也可以在重分布时,使用 gpexpand -a 参数来同步执行 analyze 操作。
数据库备份
GP 集群正常使用
如果使用了 gpbackup 备份数据库,那么,在库容之前进行的备份,gprestore 无法将
□
该备份在扩容后的集群进行恢复,因为 gprestore 不支持不同规模的集群进行恢复。
新硬件的规划
一个考究的硬件规划,对于成功的扩容,非常重要,否则,随意的搭配,可能会带
来无尽的麻烦。虽然,从软件层面来说,并没有对硬件有明确的限制,但是,考虑到短
板效应,新的主机,各方面的配置和计算能力,要与现有的计算节点主机相匹配,否则,
必然会造成资源的倾斜或者浪费。如果新增的主机,所有指标都高于现有的计算节点主
机,扩容,将无法完全利用新主机的能力,会造成资源的浪费,但仍会得到性能的提升。
如果新增的主机,有一些关键指标低于现有的计算节点主机,那么,扩容,可能会导致
新主机成为新的瓶颈点,甚至可能会导致,扩容后的性能反而更差了。理想情况下,这
些情况都是不应该发生的,所以,建议在购买设备之前,确保与专业技术支持进行沟通,
确认如何购买新的硬件设备,这一点非常重要。
版权所有:Esena(陈淼 ) 编写:陈淼 - 342 -
Greenplum Database 管理员指南 V6.2.1
规划和配置新的硬件设备,一般涉及如下事项:
CPU型号的选择,内存容量的选择,磁盘规格的选择,Raid卡型号的选择,Raid
模式和参数的选择,万兆网卡的选择,万兆光纤线,万兆交换机的选择,多交换机
的连接问题。
机柜的位置,主机的摆放,制冷问题,供电问题,网络铺设问题,与现有设备的连
接问题。
IP地址的分配,需要充分考虑到与现有设备的组网问题。
现有设备的系统配置信息,包括,网络设置,操作系统的配置文件,用户,权限等,
应确保新设备保持与现有设备一致。如果采用标准安装,可以通过自动化脚本自动
完成标准化设置。
因特定的设备和使用环境,涉及的其他工作。
规划新 Instance 的初始化
当一切准备工作就绪,就可以进行GP数据库层面在线扩容操作了,执行gpexpand
命令来初始化和启动新的Instance,生成gpexpand模式及重分布信息。
执行gpexpand来完成新Instance的初始化和启动,生成gpexpand模式和重分
布信息,这个过程的耗时,完全取决于现有集群中的对象数量,Master工作目录的尺
寸,网络的性能,新扩容主机的性能,扩容主机的数量。比如,在生成模板压缩文件时,
耗时取决于Master工作目录的尺寸,在分发模板压缩文件时,耗时取决于新扩容主机
的数量,网络的性能。在清理Master Only系统表时,以前的代码是串行的,当扩容
几十个新主机时,可能会耗时几个小时,这个问题,在目前的几乎所有版本中都存在,
最初是由编者发现并修改的,编者自己改好了4、5、6每个版本的gpexpand代码,用
于解决扩容操作中的诸多瓶颈问题,目前最新的6版本代码也修改了此问题。
在执行gpexpand命令进行新Instance初始化时,下列命令不能被执行:
gpbackup
gpcheckcat
gpconfig
gppkg
版权所有:Esena(陈淼 ) 编写:陈淼 - 343 -
Greenplum Database 管理员指南 V6.2.1
gprestore
在执行新Instance初始化时,最好选择业务空闲时期,而不仅仅是按照文档要求,
只是避免以上命令的执行,因为,扩容初始化操作一定会与其他业务查询发生锁冲突。
规划 Mirror 策略
如果现有GP集群配置了Mirror,那么,新扩容的主机也必须配置Mirror。如果
现有GP集群没有配置Mirror,那么,新扩容的主机也不能配置Mirror。也就是说,
Mirror,要么配置,要么不配置,不能只有部分Primary配置,因为这样毫无意义。
对于配置Mirror来说,不同的Mirror策略,对新主机的数量有不同的要求:
Group镜像策略--最少需要添加2个新扩容的主机,因为Mirror不能与配对的
Primary放在一个主机上,所以,最少需要2个新扩容的主机。缺省情况下,第一
台主机的Mirror放在第二台主机上,依次类推,最后一台主机的Mirror放在第
一台主机上。
Spread镜像策略--新主机的数量,必须大于每台主机上Primary的数量。因为,
Spread策略,是将一台主机上的Primary配对的Mirror挨个分别放置到后续的
主机上,所以,当一台主机上有N个Primary时,必须至少再有N个其他主机用于
分别放置N个Mirror,所以,当一台主机上有N个Primary,Spread策略,至少
要新增N+1台主机。
自定义镜像策略--Group和Spread两种镜像策略,是缺省支持的镜像策略,会自
动检查是否满足主机数量的要求。而自定义的镜像策略,可以不受主机数量的限制,
至少,数据库本身允许任何形式的镜像策略,哪怕把Mirror和配对的Primary放
在同一台主机上,所以,只要按照合理的方式进行规划和设计即可。编者的自动安
装部署命令,可以满足绝大多数的对称镜像策略的需求。
为现有主机增加 Instance 数量
缺省情况下,新扩容主机上新增的Primary数量与现有集群中计算节点主机上
Primary的数量保持一致,然而,gpexpand命令允许为现有集群,增加每台计算节点
主机上Primary的数量,虽然这是一个可选项,但是,请谨慎对待,增加现有每台主
机上Primary的数量,集群的并发数承载能力需要重新评估,否则,可能会导致严重
的资源争抢。
版权所有:Esena(陈淼 ) 编写:陈淼 - 344 -
Greenplum Database 管理员指南 V6.2.1
$ gpexpand
How many new primary segments per host do you want to add? (default=0):
>
编者的自动化安装部署命令,允许为新扩容的主机指定完全不同数量的Primary
数量,允许设置全新的镜像策略,为配置差异较大的设备之间的性能平衡提供了更多选
择。不过,编者提醒,虽然允许Primary数量的差异化扩容,但是,请谨慎对待这个
问题,最好与专业技术支持保持沟通,获得专业的建议之后再采取行动,否则,会有很
大的概率陷入短板效应的陷阱,导致扩容无法达到预期的目标。
关于 gpexpand 模式
在执行gpexpand对新的主机进行新Instance的初始化阶段,会在postgres数
据库中创建一个名为gpexpand的模式,对6之前的版本,需要预先创建一个空数据库,
并通过gpexpand的-D参数来指定该数据库,这样,gpexpand模式将会在指定的数据
库中被创建。
在gpexpand模式中,会创建一些数据表,用于管理需要被重分布的表的信息,以
便于后续的数据重分布操作对每张表的重分布状态进行管理。包括了两张数据表和一个
视图:
gpexpand.status
gpexpand.status_detail
gpexpand.expansion_progress
编者在修改gpexpand命令时,引入了新的表gpexpand.status_finish,在6
版本中,还引入了新的表gpexpand.status_process。
gpexpand.status表中记录的是gpexpand操作的开始和结束,以及是否已经全
部完成了所有的数据重分布任务。gpexpand.status_detail表中记录了所有需要
重分布的业务表的信息,在6版本之前,该表还需要记录每张表的分布键的情况,因为
在6版本之前,gpexpand命令会先将所有表的分布策略修改为RANDOMLY,之后通过
重分布操作来恢复正确的分布键以及对数据进行重分布,而在6版本,不再需要将表的
分布策略修改为RANDOMLY,而是通过gp_distribution_policy系统表的
numsegments字段来标识表的数据分布情况,在未进行重分布之前,numsegments
字段的值与原有集群的Primary数量相等,完成重分布之后,numsegments字段的值
与扩容后的Primary数量相等。
版权所有:Esena(陈淼 ) 编写:陈淼 - 345 -
Greenplum Database 管理员指南 V6.2.1
gpexpand.expansion_progress是一个视图,用于查看数据重分布的进度。
在6版本之前,所有的表的UPDATE和DELETE操作都是EXCLUSIVE锁,所以,在
进行并发数据重分布时,很多小表的数据重分布时间很短,而更多的时间消耗在更新表
的重分布状态上,因为UPDATE操作需要EXCLUSIVE锁,只能串行执行,在6版本,如
果没有打开全局死锁检测,同样会有这个问题。编者引入了新的表,用于管理数据重分
布的状态,避免了使用UPDATE命令,从而可以从根本上避免UPDATE的锁冲突问题,
编者目前已经在4、5、6各个版本完成了gpexpand的修改,让数据重分布真正的并行
起来。
规划数据重分布
数据重分布是在线进行的,即便在6之前的版本也是如此。往往,很多GP集群的扩
容操作,数据重分布过程,可能是通过执行一次gpexpand命令来完成,对于超级集群,
可能需要多次运行gpexpand命令来完成数据重分布的操作。如果有可能,应该尽快完
成数据重分布的操作。
注意:对于磁盘空间有限的集群来说,可能需要规划好重分布的顺序,因为,数据的重
分布,实质上是在底层重新生成一份数据文件,当原有计算节点主机的剩余可用空间较
少时,可能需要先对尺寸小的表进行重分布,等到可用容量增加之后,再对大表进行数
据重分布。
影响数据重分布性能的因素有很多,包括表的尺寸,表的数量,以及分区的情况,
对于特定的一张表来说,重分布的效果与CREATE TABLE AS SELECT的效果相似,
需要消耗较多的资源,而且,至少到编者目前看到的版本为止,6版本的gpexpand不
支持对分区表进行并行重分布,需要直接对整个表进行重分布操作,这可能会是一个比
较大的影响。另外,表的数量会是一个很大的因素,由于gpexpand使用UPDATE来更
新表的重分布状态,多表之间的并行重分布,在更新每张表的重分布状态时,会发生
UPDATE锁冲突,尤其对于很多小表的集群,这可能会是灾难性的,在6版本中,可以
通过打开全局死锁检测功能,来解决该问题。
使用编者修改的gpexpand命令来进行扩容操作,可以从根本上避免UPDATE锁的问题。
管理大规模集群的数据重分布
在规划数据重分布操作时,需要考虑ACCESS EXCLUSIVE锁的影响,在对一张表
版权所有:Esena(陈淼 ) 编写:陈淼 - 346 -
Greenplum Database 管理员指南 V6.2.1
进行重分布操作时,需要获取访问排它锁,这个锁,与这张表上的其他任何访问都会有
冲突,如果在开始重分布之前,有其他事务在访问同一张表,则,重分布操作需要一直
等到所有访问的事务结束之后才能真正的开始,同样,在数据重分布操作获取了一张表
的访问排它锁之后,这张表上的其他任何访问都需要等到重分布操作完成之后才能获取
必要的锁。
可以通过调整需要重分布的表的优先级来缓解业务冲突,或者避免在可用磁盘空间
不足的集群中,因磁盘空间不足导致大表重分布失败。编者认为,不应该出现因磁盘空
间不足而导致的大表重分布失败的可能性,因为这说明,系统的可用容量已经很低,磁
盘使用率早已超过最佳实践要求的70%的红线,这样的风险很高,切记不可超过70%。
可用磁盘空间充足的系统
对于可用磁盘空间充足的系统,可用容量完全足够大表复制一份的情况下,可以把
数据重分布的重点放在业务方面,首先将业务中可能会大量使用的表,先进行数据的重
分布。
对于不需要立即进行数据数据重分布的表,可以将gpexpand.status_detail
表的rank字段设置为更大的值,从而使得其在数据重分布操作中排在后面被执行,这
样,执行gpexpand重分布数据时,重要的表将会先被执行数据重分布操作。
可用磁盘空间不足的系统
如果现有计算节点主机的可用磁盘空间不足,无法满足大表重分布的时候存储一份
重复的数据,此时,需要先将小表进行数据重分布,在较小的表,完成数据重分布之后,
有足够的可用磁盘空间时,再对大表进行数据重分布。随着很多表陆续的完成数据重分
布,在现有计算节点主机上的可用磁盘空间将会逐渐增加。
对大表进行数据重分布的时间较长,所以,占有访问排它锁的时间也会较长,因此,
应该安排在业务空闲时段对大表进行数据重分布。所以,可以在业务空闲时段,使用大
并发(gpexpand -n参数指定并发度)来提高系统资源的利用率,以加速数据重分布的
进度,同时,应该控制数据库为业务提供服务的连接数或者并发事务的数量,为数据重
分布操作保留必要的资源。
版权所有:Esena(陈淼 ) 编写:陈淼 - 347 -
Greenplum Database 管理员指南 V6.2.1
重分布 AO 表和压缩表
在对非压缩AO表和压缩AO表进行重分布时,重分布的速度与Heap表是有区别的,
编者觉得,没人会不知道这是有区别的。压缩AO表在进行数据重分布时会需要更多的
CPU资源来完成数据的压缩和解压缩计算。对于相同尺寸的相似数据的表来说,非压缩
AO表的重分布性能会比Heap表要好一些,官方文档说会高10%左右的性能,编者认为
这个可以忽略,而且,一般来说,不会有人使用非压缩的AO表,因为那样做几乎没有
任何实际意义。压缩AO表的重分布性能,比非压缩AO表的重分布性能要差一些,因为
会有更多的CPU消耗,但是,具体差异多大,这取决于压缩算法和压缩级别的选择,编
者建议,在6版本,应该选择ZSTD压缩算法,而压缩级别,不应该考虑6以上的级别,
对于ZSTD压缩算法的测试发现,ZSTD命令,缺省的压缩级别是3级,而且,在有些时
候,1级压缩也可能会获得更好的压缩效果,且CPU的消耗最低,压缩的耗时最短。
注意:如果使用的是压缩文件系统,再使用压缩AO表的话,日常的数据插入和查询,
扩容时的数据重分布都会消耗更多的计算资源,而且不会得到更好的压缩效果,因为,
通常来说,对压缩后的文件再进行压缩,不会得到更好的压缩效果。
重分布分区表
至少到编者编写这一段为止,目前最新的6.10.0版本,和github上的master主
线,gpexpand命令无法处理分区表的并行重分布,编者也做了测试,6版本,在进行
数据重分布时,必须将整个分区表作为一个整体来操作。这一点,与官方文档的介绍完
全不一致。
在6之前的版本,由于扩容操作的数据重分布的实现方式不同,允许在数据重分布
时,叶子分区并行执行数据重分布,即,同一个分区表的不同叶子分区可以同时进行数
据重分布操作。
关于6版本无法处理同一张分区表叶子分区并行重分布的问题,源码里是这样写的:
population of status_detail for partitioned tables, leaf partition cannot
has different numsegments with root partition, we need to expand root
partition in one shot, so just populate root partition for now.
TODO:
We used to use a tricky but effective way to expand leaf partition
in parallel, that way is still under discussion. Keep the old method
here in case we need bring it back someday.
版权所有:Esena(陈淼 ) 编写:陈淼 - 348 -
Greenplum Database 管理员指南 V6.2.1
Step1:
BEGIN;
Lock all root/interior/leaf partitions
Change all numsegments of root/interior/leaf partitions to size of cluster;
Change all leaf partition to random distributed;
COMMIT;
Step2:
Change all leaf partition's policy back to old policy with a mandatory
data movement.
实际上,这里提到的方法,与6之前的版本的做法是一致的,先将每张表的分布键
信息,记录在gpexpand.status_detail表中,再将系统表
gp_distribution_policy中的分布键字段UPDATE为RANDOMLY。在进行数据重分
布阶段,再将分布键修改为正确的值,这样,需要对gp_distribution_policy系
统表获取访问排它锁,以避免正在执行的查询获取错误的分布策略。
实际上,在完成新Instance初始化之后,由于gp_distribution_policy表的
numsegments字段值的不同,优化器会根据numsegments字段的值来确定该如何生
成更合理的执行计划,所以,很多时候,这种方式还是比简单粗暴的设置为RANDOMLY
要更有优势。
重分布有索引的表
虽然gpexpand没有明确的删除索引和重建索引,但是,执行数据重分布操作,也
是相当于重建索引(与带索引INSERT不同,效果应是,等同于INSERT后CREATE
INDEX),所以,对于重度索引的GP系统,数据重分布的性能还与重建索引的耗时有关,
数据重分布的速度,与同等状况,但没有索引的GP系统相比,肯定要更慢一些。
准备并添加新的计算节点主机
首先,要确保用于扩容的新主机,已经安装好了操作系统,操作系统版本必须与现
有集群完全一致,否则,会有无法预料的风险,配置好合适的网络,配置好Raid或者
其他用于存储数据库数据的磁盘,按照GP数据库安装运行的要求,修改好操作系统参
数。详情,请参考"安装部署与初始化"章节。
将用于扩容的新主机加入集群中,使得这些新的主机,符合初始化新增Instance
的要求。这些仍是准备工作,还没有真正的开始扩容操作,只是让新的主机融入现有集
版权所有:Esena(陈淼 ) 编写:陈淼 - 349 -
|
||
|
|
|