|
|
Greenplum Database 管理员指南 V6.2.1
错误记录处理
可读外部表,通常用于将数据导入数据库内的常规数据表中。通过CREATE TABLE
AS SELECT或者INSERT INTO . . . SELECT语句来实现数据的导入。缺省情况下,
如果数据中包含了错误的记录格式,整个命令将会失败,不会有数据被导入目标表中。
SEGMENT REJECT LIMIT子句允许将可读外部表中格式错误的记录进行隔离,而
正确的记录可以正常的导入目标表中。通过该子句可以设置错误记录隔离的阈值,允许
按照百分比(PERCENT)或者记录数(ROWS)来限制,当格式错误的记录数量超过设置的
阈值,整个导入操作仍然会失败,这个阈值的设定可用于控制数据质量,确保在有大量
数据异常时可以失败报错。这个阈值,是针对每个Primary进行统计的,并不是全局
统计。
当格式错误的记录数量没有达到设置的阈值,对外部表的查询,整体是成功的,错
误的记录会被隔离,还可以选择是直接丢弃这些错误的记录,或者记录到日志信息中
(通过在SEGMENT REJECT LIMIT子句前加上LOG ERRORS子句实现)以便进一步的
处理(比如,找到错误的原因,可以有助于改善数据质量)。
当指定了SEGMENT REJECT LIMIT子句,GP读取可读外部表时,就开启了单行
错误隔离模式,对于多字段、少字段、字段数据类型不匹配、编码错误等,都可以进行
隔离,但不会对约束冲突进行隔离,数据违反目标表的约束,仍会导致数据导入的失败。
不过,这种情况,在导入时,可以进行必要的过滤处理。例如:
=# INSERT INTO table_with_pkeys
SELECT DISTINCT * FROM external_table;
定义一个错误记录隔离的外部表
用一个简单的例子来说明:
=# CREATE EXTERNAL WEB TABLE test_ext (a int, b int, c int)
EXECUTE E'for i in {1..9};do echo "$i|$((i+100))|$((i+200))a";done
版权所有:Esena(陈淼 ) 编写:陈淼 - 250 -
Greenplum Database 管理员指南 V6.2.1
echo "1|3|5"' ON ALL
FORMAT 'text' (delimiter E'\x7c')
LOG ERRORS SEGMENT REJECT LIMIT 10 ROWS;
SELECT * FROM test_ext;
NOTICE: found 18 data formatting errors (18 or more input rows), rejected
related input data
a | b | c
---+---+---
1 | 3 | 5
1 | 3 | 5
(2 rows)
该例中,SEGMENT REJECT LIMIT子句前使用了LOG ERRORS子句,错误记录将
会被记录到GP数据库的统一的错误记录日志中,如果没有LOG ERRORS子句,错误记
录将会被直接丢弃。
使用GP自带的函数gp_read_error_log('external_table')可以查看出错
记录的日志。从5版本开始,GP的可读外部表,不再使用ERROR表来记录错误记录,而
是使用统一的错误记录日志来记录,通过gp_read_error_log函数来查询错误记录
日志,通过gp_truncate_error_log函数来清除指定的错误记录日志。原因是,以
前的ERROR表无法保证事务的原子性,在多个外部表并发使用一张ERROR表时会报错。
将这个例子稍微改一下,用百分比来定义阈值:
=# CREATE EXTERNAL WEB TABLE test_ext (a int, b int, c int)
EXECUTE E'for i in {1..9};do echo "$i|$((i+100))|$((i+200))a";done
echo "1|3|5"' ON ALL
FORMAT 'text' (delimiter E'\x7c')
LOG ERRORS SEGMENT REJECT LIMIT 10 PERCENT;
SELECT * FROM test_ext;
NOTICE: found 18 data formatting errors (18 or more input rows), rejected
related input data
a | b | c
---+---+---
1 | 3 | 5
1 | 3 | 5
(2 rows)
定义的百分比阈值是10%,正确的记录是2条,错误的记录是18条,但是,查询依
然成功了。这里需要解释一下gp_reject_percent_threshold这个参数,该参数
定义了一个阈值(记为N,缺省值为300),在使用百分比设置时,对于每个Primary来
说,前N条记录不统计失败的百分比,这是一个无奈的方法,因为,如果不设置这样的
阈值,当第一条记录就是错误数据(或者前几条记录的错误记录数较多)时,就直接到
达了100%,无论后续的数据质量如何,都会整体失败。
版权所有:Esena(陈淼 ) 编写:陈淼 - 251 -
Greenplum Database 管理员指南 V6.2.1
还有一个参数gp_initial_bad_row_limit,该参数的缺省值为1000,当开始
的数据全部为错误记录,且达到了该参数设定的值,整个导入操作就失败了,如果有一
条正确的记录,整体操作不受该参数影响。
对于外部表,这两个参数都是对单个Primary作用的,因为Primary之间都是独
立工作的,无法在处理的过程中互相串通这种统计数据。如果能在处理完最后一条记录
时统计一下整体的成功率,是不是就不需要这两个参数了,编者觉得,设计有待改善。
查看错误记录日志
错误记录日志的格式为:
字段
类型
描述
cmdtime
timestamptz
查询外部表的 SQL 命令执行的时间。
relname
text
外部表的名称,或者 COPY 命令的目标表名称。
filename
text
错误记录所在的文件名称(可能是 URI 或者 URL)。
linenum
int
错误记录所在的文件中的行号。
bytenum
int
gpfdist 是按照 block 来分拆文件的,无法记录行号,可
以记录出错位置的字节数。
errmsg
text
错误记录的错误信息。
rawdata
text
错误记录的文本数据。
rawbytes
bytea
比如编码错误等,无法记录错误记录的文本,将记录错误记
录的八进制编码。
gpfdist 服务
在使用CREATE EXTERNAL TABLE命令创建外部表时,使用了gpfdist协议,可
以用gpfdist服务来提供数据。当使用gpfdist服务配合gpfdist协议的外部表时,
GP集群的Primary可以并行的读写外部数据。
本节主要包括以下内容:
关于gpfdist和外部表。
关于gpfdist的规划和性能。
控制Primary访问gpfdist的并发。
安装gpfdist。
版权所有:Esena(陈淼 ) 编写:陈淼 - 252 -
Greenplum Database 管理员指南 V6.2.1
启停gpfdist。
gpfdist的故障排查。
关于 gpfdist 和外部表
gpfdist服务的命令,在GP数据库集群的每台主机上自带安装了,在
$GPHOME/bin目录下,source了GP的path文件之后,就可以直接使用该命令了。当
启动gpfdist服务时,需要指定服务监听的端口和工作目录(该目录内的数据都可以被
访问)。例如,下面的命令是启动一个gpfdist服务,端口为8080,目录为/,并将服
务提交后台运行:
$ nohup gpfdist -p 8080 -d /../ &
此处说明一下,gpfdist不允许直接在/目录上启动服务,因此可以通过/../的
方式间接的从/上启动服务。
CREATE EXTERNAL TABLE命令的LOCATION子句,将外部表指向一个或者多个
gpfdist服务,如果是可读外部表,gpfdist服务将根据外部表的URI路径,在其工
作的相对路径下找到对应的文件,读取这些文件,并分拆为一个一个的block,分发给
GP数据库的Primary(根据Primary的请求情况)。Primary收到数据包之后,按照外
表定义的ROW类型进行处理,格式化为表的tuple,然后根据具体执行语句的情况决定
在哪里进一步处理这些tuple(实际上,这一步已经不属于外部表的职责,格式化为
tuple之后的操作都是因为实际任务的需要,优化器为执行计划增加的处理操作),比
如要将数据INSERT到一张常规的数据表中,Primary将会根据目标表的分布键来决定
将数据重新发送到哪个Primary。如果是可写外部表,Primary将会把表的tuple格
式化为文本然后打包发送给gpfdist服务,gpfdist再将这些数据包写到一个或多个
文件中,当写到多个文件时(LOCATION中会有多个URI选项),根据可写外部表指定的
分布键来决定发送给哪个gpfdist服务。
关于 gpfdist 的规划和性能
可以在不同的机器上运行多个gpfdist服务,也可以在一台机器上运行多个
gpfdist服务。从而可以充分利用文件服务器的IO性能和网络带宽,以配合GP外部表
高速的并行数据加载性能,获得更高的数据导入和导出的性能。
版权所有:Esena(陈淼 ) 编写:陈淼 - 253 -
Greenplum Database 管理员指南 V6.2.1
gpfdist服务,允许一个外部表,同时使用一台gpfdist文件服务器的多个网络
端口,以提升数据访问的性能。这是因为,gpfdist不通过网络地址来区分是否为,
对同一个资源的请求。而是通过X-GP-XID、X-GP-CID和X-GP-SN等Header信息来
区分的。如下图所示,一个gpfdist服务,GP外部表,经由多个网络端口来访问。
具体到URI来说,不同的URI,通过不同的主机名,指向相同的gpfdist服务的相
同目录和文件,实际上获取的是一份文件,利用了多个网络带宽,只有这种情况,才是
对同一份文件利用了多个网络带宽,如果gpfdist服务、文件路径或文件名称有任何
的不同,都不是同一份资源,在使用这一特性时需要注意避免重复加载数据。
可以将数据文件均匀的分散到多个gpfdist服务,同时为外部表提供数据,可以
提升外部数据源的供数性能。比如,将数据均分到两台文件服务器上,每台文件服务器
上启动一个gpfdist服务。例如:
版权所有:Esena(陈淼 ) 编写:陈淼 - 254 -
Greenplum Database 管理员指南 V6.2.1
对于性能很高的文件服务器来说,在多个端口(PORT)上启动gpfdist服务很有必
要,毕竟一个gpfdist服务使用的CPU资源有限,当需要处理压缩、多并发等场景时,
使用多个gpfdist服务可以提升高性能文件服务器的资源利用。
编者认为,分隔符对数据导出到gpfdist的性能几乎不会有任何影响,实际上,
对可写外部表性能影响最大的是,Primary每次向gpfdist服务发送的数据包的尺寸,
在4.3.7版本之前,Primary发送的数据包的缺省尺寸是32K,由于是HTTP协议的数
据传输,大量数据导出时,更多的时间浪费在反复的HTTP连接建立和断开,将这个尺
寸提升到比如16MB,导出的性能得到极大提升,可以瞬间占满gpfdist服务所在文件
服务器的所有网络端口,这个尺寸由writable_external_table_bufsize参数设
置,目前的版本,该参数的缺省值为64KB,还是太小了,建议直接设置到16MB。
控制 Primary 访问 gpfdist 的并发
通过gp_external_max_segs参数来控制同时访问一个gpfdist服务的
Primary的数量,这样可以减轻gpfdist所在服务器的网络压力,该参数的缺省值是
64,对于绝大部分的情况,不需增加这个参数,反而对于一些gpfdist所在服务器的
网络环境较差的情况,需要适当的减小这个参数,当然,对于网络环境好的情况,增加
这个参数是可以提升外部表导入的性能的。不过,这个参数仅对gpfdist外部表有效,
其他协议不受此影响。
版权所有:Esena(陈淼 ) 编写:陈淼 - 255 -
Greenplum Database 管理员指南 V6.2.1
安装 gpfdist
可以在所有安装了GP服务端软件的机器上运行gpfdist服务,也可以在需要运行
gpfdist服务的机器上复制一份GP服务端软件的安装目录。或者安装loaders客户端。
启停 gpfdist
可以在当前目录启动gpfdist服务,如果不使用-d参数指定工作目录,缺省的工
作目录,是当前执行命令的目录。如果不使用-p参数指定监听的端口,缺省的监听端
口为8080。例如,下面的命令是启动一个gpfdist服务,端口为8080,目录为/,并
将服务提交后台运行:
$ nohup gpfdist -p 8080 -d /../ &
可以通过-l参数来指定gpfdist服务的日志输出,如果不需要gpfdist的输出,
可以这样启动gpfdist服务:
$ nohup gpfdist -p 8080 -d /../ >/dev/null 2>&1 &
$ nohup gpfdist -p 8081 -d /../ >/dev/null 2>&1 &
正如上面的例子,可以在相同的目录上启动多个gpfdist服务,只要监听端口不
同即可。这样就可以为不同的外部表配置不同的gpfdist服务,更充分的利用CPU资源。
要停止后台运行的gpfdist服务,可以先找到gpfdist服务的进程ID:
$ ps ax|grep gpfdist
使用kill命令杀掉gpfdist的进程。例如(加入2345是gpfdist的进程ID):
$ kill 2345
gpfdist 的故障排查
Primary在外部表被访问时才会真正的访问LOCATION中的资源指向,在定义外部
版权所有:Esena(陈淼 ) 编写:陈淼 - 256 -
Greenplum Database 管理员指南 V6.2.1
表时,并不会检查资源是否存在或者是否可以访问。如果查询外部表时有访问方面的报
错信息,首先要确保gpfdist已经正确的启动,然后确定所有Primary所在的机器可
以正常的访问gpfdist服务。可以通过下面的步骤来测试gpfdist服务的可访问性:
1、 首先确定gpfdist已经启动:
$ ps ax|grep gpfdist
根据输出信息确定gpfdist的进程ID(pid),比如pid为5134。
2、 如果已经启动,确认服务的监听端口和工作目录(上一步输出中已经显示的信息,
可以不用确认)。
$ netstat -nltp|grep gpfdist
$ lsof -p 5134|grep cwd
根据输出信息确定gpfdist服务的监听端口和工作目录。
3、 确定工作目录下有一个小尺寸文件,用于测试可访问性,比如有个file0文件,监
听的端口为8080。先在gpfdist服务器本地执行如下测试命令:
$ wget --delete-after --header 'X-GP-PROTO:0' http://localhost:8080/file0
如果可以成功获取测试数据文件,再从GP集群的所有主机测试该命令,确保所有
主机都可以成功获取测试数据文件。这一步需要修改URL的主机名信息为真实的主机名
或者IP地址。
使用外部表导入数据
使用外部表导入数据到GP数据库中,涉及以下几方面的前期准备工作:
1、 启动gpfdist服务,或者配置PXF服务。
2、 确定数据文件所在的目录位置。
3、 根据文件的数据格式创建外部表。
在这些工作准备就绪之后,就可以直接通过外部表来查询外部数据了。剩下的事情,
就像使用常规的数据表一样来进行数据导入操作。例如,使用INSERT INTO命令实现
从外部表ext_expenses导入类型为'travel'的数据到expenses_travel数据表
中:
版权所有:Esena(陈淼 ) 编写:陈淼 - 257 -
Greenplum Database 管理员指南 V6.2.1
=# INSERT INTO expenses_travel
SELECT * from ext_expenses where category='travel';
正如该例中所示,在查询外部表时,可以像使用常规的数据表那样使用各种过滤条件。
再例如,新建一张表并将外部表的数据全部导入:
=# CREATE TABLE expenses AS SELECT * from ext_expenses;
使用外部表导出数据
可写外部表,用于将库内的数据导出。可以是文件,可以是命名管道,可以是其他
的应用程序(比如WEB服务),GP MapReduce已经毫无意义了,不提也罢。不过,如
果对性能和稳定性有很高的要求,导出到命令管道,可能会是一项极其复杂的工作,因
为命名管道的状态无法精确的控制和获取,这就导致,在编程时需要设计很多的迂回措
施来解决这些问题,最典型的场景就是以前的gptransfer命令,目前该命令已经废除,
不过,该命令从一开始出现就注定是失败的,可以欣赏一下这段代码注释:
# Make sure all named pipes get an EOF on them or empty tables
# will hang.
# TODO: currently no way to ensure gpfdist on the write side has
#
written all data available to the pipe. Closing the pipe
#
while data is remaining causes and EPIPE on the writable
#
gpfdist side. Need a better way to coordinate this.
time.sleep(self._wait_time)
在gptransfer的Python代码中,充斥着各种sleep操作,因为无法精确控制命
名管道的状态,导致的结果是,一个表中哪怕只有几条记录,也需要花费至少十多秒来
完成数据的传输。在不追求极致性能的场景,很多时候,命名管道是非常不错的方案,
这样就可以与其他程序进行无缝对接,实现不落地的数据导入和导出。
使用 gpfdist 协议外部表导出数据
使用gpfdist协议的可写外部表导出数据时,数据库的Primary将打包好的文本
数据发送给gpfdist服务,gpfdist服务将数据写入目标文件中。必须所有Primary
都可以访问gpfdist服务,数据是在Primary和gpfdist服务之间直接传输的,不经
过Master(断开Master和gpfdist之间的网络并不影响gpfdist外部表的使用)。
版权所有:Esena(陈淼 ) 编写:陈淼 - 258 -
Greenplum Database 管理员指南 V6.2.1
要将导出的数据分拆到多个文件中,需要指定多个URI属性,每个URI指定一个文
件,并结合可写外部表的DISTRIBUTED子句来决定数据的分布情况。URI中也可以使
用通配符,但是,不得匹配多个文件,所以,虽然可以用,实际无意义。URI的数量也
不能超过Primary的数量。关于DISTRIBUTED子句,缺省使用的是随机分布的策略,
这也是建议的最佳选项,如果一定要选择HASH分布的策略,建议选择需要导出数据的
表的分布键作为可写外部表的分布键,如果这样做了,再次使用这些文件导入同构的
GP集群时,也需要每个文件都列出来,否则会影响导入的性能,因为通配符匹配的文
件是一个一个读取的,这样会大致,实际匹配的Primary是一个一个匹配的。例如:
=# CREATE WRITABLE EXTERNAL TABLE test_ext
(a integer, b integer, c integer)
LOCATION (
'gpfdist://mdw:8080/tmp/file1.gz',
'gpfdist://mdw:8080/tmp/file2.gz'
)
FORMAT 'text' (delimiter '|');
=# INSERT INTO test_ext SELECT i+10,i+20,i+30
FROM generate_series(1,10) i;
使用基于命令的 WEB 型外部表导出数据
定义基于命令的WEB型外部表,将数据发送至脚本或命令。当向基于命令的可写
WEB型外部表INSERT数据时,数据将会以输入流的形式发送给这些脚本或命令。这些
脚本或命令将由GP集群内的所有Primary通过gpadmin用户来执行,这与基于命令的
可读WEB型外部表不同,基于命令的可读WEB型外部表可以指定执行脚本或命令的
Primary范围或HOST范围,基于命令的WEB型可写外部表,不行,哪怕Primary上没
有数据,脚本或命令也会被调用,因为每个Primary都有自己需要处理的任务,自己
的数据不能由其他Primary来处理。外部表中的脚本或命令是由数据库执行的,所以,
并不会source gpadmin用户的登录文件(.bashrc或.profile),在执行命令时,
可以手动source这些环境文件,也可以使用预先定义好的GP环境变量。例如:
=# CREATE WRITABLE EXTERNAL WEB TABLE test_ext
(a integer, b integer, c integer)
EXECUTE 'more > /tmp/test_ext.out'
FORMAT 'TEXT'
DISTRIBUTED RANDOMLY;
=# INSERT INTO test_ext SELECT i+10,i+20,i+30
FROM generate_series(1,10) i;
版权所有:Esena(陈淼 ) 编写:陈淼 - 259 -
Greenplum Database 管理员指南 V6.2.1
关于可用的GP环境变量,可参考"基于命令的WEB型外部表"章节的介绍。
使用 COPY 命令导入导出
COPY是PostgreSQL的命令,非常有用,可以实现非并行的数据导入与导出。通
过COPY命令,可以实现把数据从文件导入常规的数据库表中,或者将表中的数据或一
个查询的结果导出到文件中,不仅是文件,还可以是标准输入输出。COPY是很多工具
的功能基础,比如,备份恢复,集群之间的数据同步,基本上都是在COPY的功能基础
上构建的。虽然COPY命令本身是串行的(后来因为gpcopy和gpbackup的需要,引入
了ON SEGMENT子句,从命令的层面实现了并行,不过这种并行是针对所有Primary
实例的,操作的都是Primary实例的本地文件,与一般意义上的COPY不同),但如果
并行调用,那就是并行了,以前的备份恢复都是通过并行调用COPY命令来实现并行的。
COPY命令每次执行,不论是导入还是导出,都只能指定一个文件,不可以使用通
配符匹配多个文件 -- 不认通配符。
还需要注意6版本的语法差异,6版本中可以把格式选项放在WITH()中,在6版本
之前是不能这么写的,不过,6版本仍然可以省略WITH关键字,格式选项也可以按照之
前版本的格式,连着写。
COPY 导入
使用COPY FROM命令可以将数据从文件或者标准输入追加到目标表中。COPY不是
并行的,是串行的,每条数据都需要经过Master串行的处理和分发,因此,COPY应该
只用于数据量不大的导入导出的场景。
COPY的文件必须在Master的主服务进程可以访问的位置。文件路径必须是
Master工作目录的相对路径,或者绝对路径。
当COPY数据到STDOUT或从STDIN COPY数据数据时,实际上是GP的Master和客
户端之间的数据复制。这样就实现了远程流数据的复制,比如要从一个集群复制少量数
据到另一个集群,可以采用如下的命令:
$ psql -h src -d srcdb -c 'COPY test TO STDOUT'|psql -h des -d desdb -c 'COPY
test FROM STDIN'
版权所有:Esena(陈淼 ) 编写:陈淼 - 260 -
Greenplum Database 管理员指南 V6.2.1
COPY 导入文件
使用COPY导入文件,实际上是数据库的postgres主服务进程在服务器上打开了
指定的文件并完成数据的导入。所以,数据库的运行用户必须拥有该文件的读取权限,
文件路径必须是Master工作目录的相对路径,或者绝对路径。例如:
=# COPY test FROM '/tmp/file0' DELIMITER '|';
COPY 从 STDIN 导入
为了避免需要先将文件复制到Master主机上,使用COPY FROM STDIN命令通过
标准输入,将数据输送到Master服务。如果COPY FROM STDIN命令运行时还没有已
经就绪的标准输入(比如COPY命令是在其他命令的标准输出之后的匿名管道接着执
行),从COPY FROM STDIN命令执行开始,将会开始接受每行一条记录的数据输入,
直到接收到反斜杠和一个小数点(\.)结束。例如:
=# copy test from stdin;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself, or an EOF signal.
>> 1
2
3
>> \.
COPY 1
以前的gpcrondump类的备份命令,备份出来的数据就是这种格式的文件,数据
和SQL混合在一起,直接当做SQL文件执行即可。
\COPY 导入数据
\COPY是一个和COPY完全不同的命令,\COPY的工作原理和COPY FROM STDIN
一致的,数据通过psql客户端发送到服务器。因此,\COPY命令操作的是psql客户端
所在机器的本地文件,运行psql命令的OS用户必须拥有这些文件的访问权限。\COPY
可以理解为对COPY FROM STDIN的包装,也是为了避免将数据文件复制到Master主
机上。例如:
版权所有:Esena(陈淼 ) 编写:陈淼 - 261 -
Greenplum Database 管理员指南 V6.2.1
=# \COPY test FROM '/tmp/file0' DELIMITER '|';
可以在任意可以使用psql命令访问GP数据库的机器上运行\COPY命令,可以是任
意有文件访问权限的OS用户,甚至是root。
COPY 数据格式
COPY FROM允许使用FORMAT子句来指定输入的数据格式,可选的选项是TEXT、
CSV和BINARY(5版本和6版本支持该选项,4版本不支持)。例如:
=# COPY test FROM '/tmp/file0' WITH(FORMAT CSV);
缺省情况下,CSV格式的字段分隔符为逗号(,0x2C),TEXT格式的字段分隔符为
水平制表符(0x09),可以使用DELIMITER来指定不同的字段分隔符。例如:
=# COPY test FROM '/tmp/file0' WITH(FORMAT CSV, DELIMITER '|');
缺省情况下,文件的编码使用的是客户端的编码,可以通过ENCODING来指定文件
的编码。例如:
=# COPY test FROM '/tmp/file0' WITH(DELIMITER '|', ENCODING 'latin1');
COPY 的错误记录隔离
缺省请款下,如果导入的数据包含错误的记录,在第一条错误记录发生时,整个操
作就会失败退出,且不会有任何数据被导入。如果使用了错误记录隔离模式,数据库会
跳过包含错误的记录,并将正确的数据记录导入目标表中。错误记录隔离,仅对格式错
误的数据有效,违反约束(比如NOT NULL、CHECK和唯一性约束等)的数据仍会导致整
个导入失败,不会有任何数据被导入。
在使用COPY导入数据时,使用SEGMENT REJECT LIMIT子句对错误记录进行隔
离。通过该子句可以设置错误记录隔离的阈值,允许按照百分比(PERCENT)或者记录
数(ROWS)来限制,当格式错误的记录数量超过设置的阈值,整个导入操作仍然会失败,
这个阈值的设定可用于控制数据质量,确保在有大量数据异常时可以失败报错。这个阈
值是针全局统计的(编者实测,是全局的,不是每个Primary统计自己的,因为COPY
版权所有:Esena(陈淼 ) 编写:陈淼 - 262 -
Greenplum Database 管理员指南 V6.2.1
的数据处理是在Master上完成的,Primary根本不会收到错误的数据),跟外部表不
同,而且,如果设置为ROWS的限制,最小值是2,否则会报错。
另外,当使用PERCENT来控制错误记录的阈值时,和可读外部表一样,还通过
gp_reject_percent_threshold参数(缺省值为300)来控制最开始不统计失败百
分比的记录数,还有一个参数gp_initial_bad_row_limit,该参数的缺省值为
1000,当开始的数据全部为错误记录,且达到了该参数设定的值,整个导入操作就失
败了。这两个参数都是全局统计的。
和可读外部表一样,通过在SEGMENT REJECT LIMIT子句前加上LOG ERRORS
子句实现对错误记录的记录,如果没有指定LOG ERRORS子句,错误记录将直接被丢弃。
例如:
=# COPY test FROM '/tmp/file0' LOG ERRORS SEGMENT REJECT LIMIT 10;
=# SELECT * FROM gp_read_error_log('test');
=# SELECT gp_truncate_error_log('test');
跟可读外部表类似,使用gp_read_error_log()函数来查看隔离的错误记录,
使用gp_truncate_error_log()函数来清除隔离的错误记录。不同的是,可读外部
表使用外部表的名称作为函数的参数,COPY命令隔离的错误记录,使用目标表的名称
作为函数的参数。
COPY 导出
使用COPY TO命令,将一张表,或者一个查询语句,导出到一个文件,或者标准
输出。COPY TO的数据也全部需要通过Master处理。例如:
=# COPY (SELECT * FROM test WHERE a < 100) TO '/tmp/file100';
在导出数据是同样可以使用\COPY命令,其工作原理与使用COPY导入是一样的。例如:
=# \COPY (SELECT * FROM test WHERE a < 100) TO '/tmp/file100';
与数据导入相关的优化
关于数据加载的性能优化,和数据加载后的查询性能,可以参考如下因素:
版权所有:Esena(陈淼 ) 编写:陈淼 - 263 -
Greenplum Database 管理员指南 V6.2.1
在加载数据之前,先删除目标表上的索引。
在已经有数据的表上创建索引的性能,可能比带索引增量导入数据的性能,要高很
多,因为带索引导入是,每条数据的导入都需要更新索引信息。可以临时增加
maintenance_work_mem参数的值,来提升CREATE INDEX命令的的性能。重
建索引,应该在没有用户会用到该索引时进行。
当需要在一张新表上创建索引时,应该在最后一步来创建索引,在导入所有的数据
之后,再创建必要的索引。
导入数据后,应该考虑在目标表上是否应该执行ANALYZE操作收集统计信息。当
表中有大比例的数据发生变化时,应该考虑执行ANALYZE操作,以更新统计信息,
保持统计信息反映了最新的数据情况,有助于优化器生成正确的执行计划。当然,
如果不收集统计信息也能生成最优的执行计划,可以不收集。
在加载失败之后,应该考虑是否需要执行VACUUM操作。如果目标表不是空表,加
载失败之后,垃圾记录和有用的记录混在一起,需要考虑在合适的时间执行
VACUUM操作来回收垃圾空间。如果目标表每次加载都是空表,可以通过TRUNCATE
来清空目标表。更多关于VACUUM的信息,可以参见"回收空间"章节。
版权所有:Esena(陈淼 ) 编写:陈淼 - 264 -
Greenplum Database 管理员指南 V6.2.1
第十二章:安装部署与初始化
GP是一个纯软件的MPP解决方案,可以运行在多种环境,比如,物理机、虚拟机、
公有云、私有云、一体机,等等。甚至一个1 Core 1GB的虚拟机中都可以安装运行,
执行正常的数据计算和分析。但是,任何的性能都是由硬件保证的,所以,要获得一个
计算能力超强的GP集群,一套计算能力超强的硬件是最基础的条件,没有无源之水。
本章节,会从硬件开始介绍,包括硬件的配置指标,预期的性能指标,硬件的搭配
平衡,以及整体的物理架构,甚至如何规划机房的摆放等。然后是如何安装操作系统,
如何配置操作系统参数,如何安装GP数据库软件,如何初始化一套符合各种安全和指
标要求的GP数据库集群。
对于安装好操作系统,配置好网络之后的操作,本章节主要是为了解说相关的知识,
编者不再使用这种纯手工的方法,因为效率太低,编者有一个自动化脚本来完成这些重
复且容易出错的工作,目前仅在编者为客户提供实施时使用,暂不公开传播。
硬件选型
GP是一个分布式数据库软件,整体数据库的性能依赖于硬件的性能和各种硬件资
源的均衡。如果过度强调某一方面硬件资源,会造成资源的不均衡,也是对资源的浪费,
同时也是投资的浪费。对于OLAP应用来说,最大的瓶颈是磁盘性能(而不是磁盘容量),
因此,所有其他资源都应该围绕磁盘性能来均衡配置。这些资源包括CPU主频与Core
数量、内存容量、网络带宽、Raid性能等,但基本宗旨是,IO资源必须绝对富余,CPU
资源永远是被充分利用的资源,内存和网络带宽也必须有富余。
CPU 主频与 Core 数量
CPU主频,理论上来说肯定是越高越好,目前GP还不支持并行度的概念,随着PG
版本的进一步合并,未来可能会支持,所以,就目前来说,一个SQL语句的执行性能,
取决于单个Core的计算能力和有多少个Primary参与计算,通常,对于一个Primary
来说,在执行一个任务时,只能利用一个CPU Core的计算能力。不过,主频这个事情,
基本上没有太多的选择,服务器级别的CPU,相同Core数量的情况下,追求很高的主
频需要很高的成本,性价比很低。
目前,主流的两路X86服务器,CPU一般都配置64 Core甚至更高的Core数量。
主频基本上没有什么选择的空间,所以,要提升集群的整体计算能力,Core的数量是
版权所有:Esena(陈淼 ) 编写:陈淼 - 265 -
Greenplum Database 管理员指南 V6.2.1
个非常重要的因素。如果有可能,配置96 Core甚至128 Core以上的CPU,将会带来
更好的计算能力。本章介绍的硬件搭配,是均衡的搭配,磁盘的性能是有充分保障的,
所以,很多时候,CPU是最先到达瓶颈的资源,因此,如有可能,尽可能的增加CPU Core
的数量,越多越好。
内存容量
目前的主流配置,单机内存至少256GB,很多已经到512GB甚至更高,因为这些
年来,数据量在不断增长,超大规模数据的关联分析需求上升。GP的很多算子,比如
Hash、AGG、Sort都属于内存密集型算子,可能需要消耗大量的内存。
配置了很多的内存,不等于说,所有时间段,活跃内存的比例都能达到很高,活跃
内存的消耗量与计算的数据量,计算的类型,并发数,都有关系。只能说,内存多,
GP在处理内存需求量很大的场景时会更高效,但不能保证活跃内存的使用率就一定能
很高。因此,如果极少有内存密集型计算,可以适当的降低内存的配置。不过,编者建
议一个Primary的最低内存配置不要低于30GB。
内存多,是一种能力的体现,在真正的生产运行之前,无法评估真实的活跃内存使
用率。也无法根据一个生产系统的情况来评估另一个生产系统的规划,当前的情况也不
代表未来的情况。总体来说,内存富余,是好事情,只是用不完而已。在GP集群中,
IO资源是最珍贵的资源,如果内存不够用,就要从内存溢出到磁盘文件,把压力转移
到磁盘上,这种情况是不应该出现的。
内联网络
内联网络的带宽,是极其重要的。GP是MPP架构,目的是为了解决IO问题,在MPP
架构下,IO问题解决了,但带来了一个新的问题,数据的移动,这是无法避免的。但
好在现在的网络能力已经足够强,万兆网卡和万兆交换机已经不再昂贵。使用24块全
机械盘的主流配置,IO已经可以达到3GB左右的连续读写能力。虽然数据移动不是总会
发生,但如果发生,带宽尤其重要,否则数据移动操作就会卡在网络层。
一定要选择万兆网络作为内联网络,要坚决杜绝用千兆网络作为内联网络的想法。
另外,为了实现网络的高可用,最少使用两个万兆网口。如果可以选择,要采用mode4
的bond,而不是mode1,从安全性角度来说,mode4与mode1是完全一样的,都有多
个通道,只要不是全部通道故障,不影响连通性,而从带宽角度考虑,正常情况下,
mode4的带宽更高,而mode1的带宽就相当于故障了的mode4,当然,如果循规蹈矩,
就要用mode1,这是自由,但是理论和事实就是如此。
版权所有:Esena(陈淼 ) 编写:陈淼 - 266 -
Greenplum Database 管理员指南 V6.2.1
一定要确保网络的健康,长期大量的错包丢包,必定会导致非常严重的后果,影响
集群的稳定性甚至是性能。
对于超大规模的集群,应该考虑为Master服务器配置更多的网口做链路聚合,因
为随着Master管理的机器增多,Master本身的网络压力会跟着上升,100台以上的集
群,可以考虑增加Master的网络带宽为4个万兆口做mode4的链路聚合。
Raid 卡性能
这个是常常不被引起重视的问题,如果使用的是机械磁盘,Raid卡非常重要,Raid
卡是缓解磁盘压力的关键,Raid卡的最大作用是,将不连续的IO操作缓存并合并为连
续的IO操作。
使用Raid卡的最关键原因是,普通的机械盘的随机读写能力很差,一个10K/Min
转速的机械盘,连续的磁盘读写性能不会超过200MB/S,大多数情况下就100多MB/S。
随机读写的性能就更差了,一般IOPS能力都到不了200,这还是磁盘厂商给的指标,
实际测试可能更低。
对于OLAP型的应用,主要是大尺寸的连续读写,如果Raid卡有Cache功能,不管
是读还是写,都可以经过Raid卡的Cache进行IO合并,充分发挥机械盘的连续读写性
能。
一般要求,24块盘机械盘,起码要配置2GB以上Cache的双通道Raid卡,否则Raid
卡的性能可能会成为充分发挥磁盘性能的障碍。根据经验,24块机械盘,一般采用12
块一组的Raid 5方案,条带一般选择256KB的尺寸。
磁盘配置
GP主要是为了解决IO瓶颈而设计的,所以,磁盘性能尤其重要。对OLAP型的应用,
目前主流的配置方案是,计算节点主机,配置24块机械盘,Master节点主机一般配置
8到12块机械硬盘。如果选择SSD或者NVMe,可以根据容量和性能来评估磁盘数量。
不能只是单纯的追求容量,要综合考虑性能指标,单块磁盘的容量越大,故障恢复
的时间就越久。一般来说,如果选择机械盘,目前主流的选择是单盘不超过1.8TB。
版权所有:Esena(陈淼 ) 编写:陈淼 - 267 -
Greenplum Database 管理员指南 V6.2.1
容量评估
在规划GP集群时,评估可用容量至关重要,这决定了需要部署什么样规模的集群。
对于使用Raid 5的磁盘,需要扣除一块磁盘的容量,如果有Hotspare磁盘,该盘容
量也不属于可用容量,对于Raid 10的磁盘,需要扣除50%的磁盘容量。比如有24块
磁盘,做成2个Raid 5的盘阵,在没有Hotspare的情况下,实际可用容量是22块磁
盘提供的,如果有2块Hotspare,则,实际可用容量是20块磁盘提供的。由于进制换
算折损,操作系统中实际显示的磁盘可用容量大约是标称容量的90%。所以:
对于Raid 5来说:
有效磁盘数量 = 磁盘总数 - Raid数量 - Hotspare磁盘数量
对于Raid 10来说:
有效磁盘数量 = (磁盘总数 - Hotspare磁盘数量) / 2
操作系统中看到的存储裸容量为:
裸容量 = 单盘容量 * 有效磁盘数量 * 90%(进制换算率)
由于磁盘不能使用100%的可用空间,GP建议,为了性能保障,磁盘使用量不能超
过70%,所以,数据库可用的磁盘空间为:
可用磁盘空间 = 裸容量 * 70%
GP还建议为每个Primary预留25%的可用空间用作查询的工作空间,这可能会涉
及,临时表,溢出文件等,为了简化计算,可以简单的将数据库可用空间按照裸容量的
60%来计算(这里考虑了Mirror的因素,为了便于计算的粗略评估):
数据库可用空间 = 裸容量 * 60%
如果集群启用了Mirror,Mirror占用的空间与Primary相同,所以,可存储的
数据容量还要之前所有计算的基础上,再折损50%:
可存储数据容量 = 裸容量 * 60% * (有Mirror ? 50% : 100%)
举个例子来说,24块1.2TB的磁盘,做成两组Raid 5,没有Hotspare,有Mirror
的情况下,单机可存储的数据容量为:
单机可存储数据容量 = 1.2TB * (24 - 2 - 0) * 90% * 60% * 50% ≈ 7TB
注意:这里得到的[单机可存储数据容量],没有考虑库内数据压缩问题,当按照入库
版权所有:Esena(陈淼 ) 编写:陈淼 - 268 -
Greenplum Database 管理员指南 V6.2.1
前的未压缩平面文件尺寸进行评估时,一般可以考虑1:3的压缩比。
机房规划
机房规划会涉及网络和供电等问题,同时还应该考虑高可用的影响。例如下图,这
是一个典型的机房摆放参考图。
建议将Master和Standby分别放置在不同的机柜,将计算节点主机分组放到不同
的机柜,因为这些机器可以形成机柜之间的备份关系。如果有条件,可以将有镜像关系
的机柜分开供电,可以确保单个机柜出现断电的情况下,GP数据库可以继续提供服务,
这回涉及到镜像策略问题,可以参考"Instance镜像"章节的介绍。
安装操作系统
建议按照推荐的模式安装操作系统,避免在之后安装部署GP集群时带来不必要的
麻烦。GP对SWAP和数据盘的划分都有一定的讲究,但这些不是硬性规范,只是建议遵
循,也可以咨询专业服务人员的意见。
版权所有:Esena(陈淼 ) 编写:陈淼 - 269 -
Greenplum Database 管理员指南 V6.2.1
开启超线程
根据实测经验,开启超线程,计算能力有几乎翻倍的提升,所以,一定要开启超线
程,否则是对CPU资源的极大浪费。
Raid 划分最佳实践
机械盘,建议做Raid 5,一方面可以提高安全级别,另一方面,可以缓解倾斜的
影响,如果不在乎成本,Raid 10也是可以的。对于机械盘的Raid 5,一般采取如下
方式配置:
StripSize -- Master建议32K ~ 128K,准确的选择可以根据测试情况来确
定。如果无法确定,可以选择128K。计算节点,建议256K,这是经验值,具体设
备的最优值可以根据测试来确定。
WritePolicy -- 根据最佳实践的经验,需要选择[Always Write Back]或
者称为[Force Write Back]。
ReadPolicy -- 根据最佳实践的经验,需要选择[Read Ahead]。
Raid Cache比例 -- 根据最佳实践的经验,不建议调整,因为调整了反而综合
性能往往会下降。
Drive Cache -- 根据最佳实践的经验,需要选择[Disable]。
IO Policy -- 根据最佳实践的经验,需要选择[Direct]。
系统盘 -- 操作系统建议安装在单独的两块盘的Raid1上。
Hotspare -- 如果需要,建议做Global Hotspare。如果更换磁盘的流程不
是很长,比如一两天就能更换故障磁盘,建议可以不配置Hotspare。Hotspare
不是一定会带来好处,因为出现故障切换时,Raid的性能会有很大下降,且这个
过程是自动的,无法根据业务情况灵活安排,而更换磁盘是可以灵活安排的。
Master类主机的Raid划分参考示例:
磁盘
Raid 类型
磁盘数量
设备号
可用容量
挂载点
用途
本
2048MB
/boot
Raid 1
2
/dev/sda
操作系统
地
剩余尺寸
/
版权所有:Esena(陈淼 ) 编写:陈淼 - 270 -
Greenplum Database 管理员指南 V6.2.1
盘
/dev/sdb
内存尺寸
swap
SWAP
Raid 5
X+1+1
/dev/sdc
剩余尺寸
/data
GP 数据盘
计算节点类主机的Raid划分参考示例:
磁盘
Raid 类型
磁盘数量
设备号
可用容量
挂载点
用途
2048MB
/boot
Raid 1
2
/dev/sda
操作系统
剩余尺寸
/
本
/dev/sdb
内存尺寸/2
swap
SWAP
地
Y+1+1
/dev/sdc
剩余尺寸
/data1
GP 数据盘
盘
Raid 5
/dev/sdd
内存尺寸/2
swap
SWAP
Y+1+1
/dev/sde
剩余尺寸
/data2
GP 数据盘
生产环境一般都需要有个Mirror的保护,一旦出现故障切换,Mirror被激活的
主机将会消耗更多的内存资源,因此,SWAP是对故障切换的一种保护。
在配置GP数据库时,在健康状态下不应该使用SWAP,如果镜像模式是一一镜像,
即,一台主机的镜像全部在另外一台主机,SWAP尺寸应该与物理内存相同,如果一台
主机的镜像均分在另外的N台主机,一般可以设置SWAP尺寸为物理内存的1/N。
由于SWAP的性能会极大影响计算效率,Greenplum要求将SWAP设置在性能最好
的磁盘上,2块盘组成的Raid1用作OS安装,其性能与数据数据盘的Raid 5相比差很
多,因此,不可以将SWAP设置在OS磁盘上。
对于SSD或者NVMe的磁盘来说,以上关于性能的问题需要重新衡量,比如SWAP放
在哪里,比如是否要做Raid,一般来说,在不考虑Raid 5安全要求的情况下,建议不
做Raid 5,因为Raid 5的校验计算对于Raid卡的计算能力来说,会约束磁盘的性能
发挥。如果条件允许,可能SSD或者NVMe会是更好的选择,这也是磁盘技术的未来趋
势。机械盘在长期高压力下,故障率会高很多,而SSD技术则会稳定很多。
GP 安装条件
本节主要按照6版本的情况来介绍,不过,除了GP软件包的安装方式有变化外,其
他内容基本上没有太大差异。
支持的操作系统
6版本的GP Server,支持RHEL6.x_x86_64、RHEL7.x_x86_64、
版权所有:Esena(陈淼 ) 编写:陈淼 - 271 -
Greenplum Database 管理员指南 V6.2.1
CentOS6.x_x86_64、CentOS7.x_x86_64和Ubuntu18.04LTS。
5版本的GP Server,支持RHEL6.x_x86_64、RHEL7.x_x86_64、
CentOS6.x_x86_64、CentOS7.x_x86_64、SuSE12SP2、SuSE12SP3、SuSE11SP4。
注意:在RedHat6和CentOS6中使用资源组是有问题的,这是因为早期的cgroup有缺
陷,最好将Kernel升级到2.6.32-696或者更高的版本以修复已知问题,从而可以更
好的使用资源组功能。这些问题在Redhat7和CentOS7中已经修复。
注意:Redhat7和CentOS7中,7.3之前的版本,因为有Kernel BUG会导致GP运行
大负载任务时出现进程被hang,所以,建议使用7.3及之后版本,7.3及之后的版本解
决了这个问题。
软件依赖
在使用rpm安装6版本GP时,下列的软件包是自动检查依赖关系的:
apr,apr-util,bash,bzip2,curl,krb5,libcurl,libevent,libxml2,
libyaml,zlib,openldap,openssh,openssl,openssl-libs,perl,
readline,rsync,R,sed,tar,zip
这个清单是根据最新的官方文档罗列的,具体的情况以实际安装时的报错提示信息
为准。5版本和4版本也都有不完全相同的依赖包,而且安装的模式也各不相同。最好
为GP数据库的操作系统配置yum源,在部署GP集群时,缺少的rpm包可以随时补上,不
过,不建议通过yum命令来安装GP,yum难以修改安装目录,直接使用rpm命令安装即
可,可以方便的修改安装目录(通过--prefix参数指定)。
硬件与网络最低要求
下面列出生产环境中,Linux系统中GP数据库服务器的最低配置要求。GP数据库
中所有计算节点的服务器应该具有相同的硬件配置和软件环境。建议由GP工程师检查
GP的运行环境,确保其适合GP数据库的生产运行。
最低 CPU 配置
x86_64 兼容的 CPU
最低内存配置
官方文档说每台机器 16GB,编者建议,每个 Primary 30GB
GP 软件安装 2GB 空间
磁盘空间要求
GP 的数据盘需要保持使用量不超过 70%
版权所有:Esena(陈淼 ) 编写:陈淼 - 272 -
Greenplum Database 管理员指南 V6.2.1
必须是万兆以太网,建议多个网口做 bond
网络要求
如果坚持使用千以太兆网,后果请自负
文件系统要求
GP数据库运行要求使用XFS文件系统,原厂未明确支持其他文件系统。所以,GP
数据库的数据目录,应该使用XFS文件系统。
对于网络文件系统或者共享存储,也必须挂载为本地XFS文件系统。非本地磁盘的
文件系统,虽然支持,但不推荐,对于GP来说,都是本地目录,不会区分对待不同的
存储。网络文件系统或者共享存储,虽然可以运行,但性能和可靠性无法保证。
安装 RHEL 的介绍
根据实践总结,建议按照如下方式安装RHEL7操作系统,这也是目前的主流选择:
选项
要求
操作系统版本
rhel-server-7.4-x86_64
挂载点
设备名
文件系统格式
尺寸
/boot
/sda1
XFS
2048MB
目录及尺寸要求
/
/sda2
XFS
剩余全部
SWAP
/sdb
SWAP
内存尺寸/2
SWAP
/sdd
SWAP
内存尺寸/2
语言选择
English(United States)
时区选择
Asia/Shanghai
软件选择
File and Print Server
附加组件选择
Development Tools
初始 root 密码
123456
如果在安装操作系统时,图形化引导界面中无法配置超过128GB的SWAP,可以先
不配置,留在操作系统装好之后再做配置。
GP数据库使用的数据盘,不需要在安装操作系统时配置(上述表格中未列出数据
盘),可以在装好操作系统之后,在准备安装部署GP数据库时再统一按照GP数据库的文
件系统挂载要求进行配置。
版权所有:Esena(陈淼 ) 编写:陈淼 - 273 -
Greenplum Database 管理员指南 V6.2.1
最好为GP数据库的操作系统配置yum源,在部署GP集群时,可能会有少量的软件
包需要安装,对于未按照建议安装的操作系统,可能会有大量的软件包需要安装。
修改操作系统配置
在正式开始安装和部署及初始化GP数据库集群之前,要先对操作系统进行配置修
改,以满足GP的运行需要,否则,直接安装多机集群时会有各种失败报错。
需要注意的是,GP数据库的运行是依靠主机名来区分不同主机的,主机名
(hostname)在整个集群中必须是唯一的。
禁用 SELinux 和防火墙
以root身份登录,或者获得root权限,比如sudo权限,执行如下命令,禁用SELinux。
RHEL6:
# sed s/^SELINUX=.*$/SELINUX=disabled/ -i /etc/selinux/config
# setenforce 0
# service iptables stop
# chkconfig iptables off
RHEL7:
# sed s/^SELINUX=.*$/SELINUX=disabled/ -i /etc/selinux/config
# setenforce 0
# systemctl stop firewalld.service
# systemctl disable firewalld.service
如果安装SuSE支持的版本,SuSE上的操作为:
# yast runlevel delete service=boot.apparmor runlevels=B
# yast runlevel delete service=SuSEfirewall2_init runlevels=B
# yast runlevel delete service=SuSEfirewall2_setup runlevels=B
版权所有:Esena(陈淼 ) 编写:陈淼 - 274 -
Greenplum Database 管理员指南 V6.2.1
修改 hostname
根据不同操作系统的配置方式,修改相应的配置文件,确保主机名被永久修改。可
能会涉及如下几个文件:
/etc/sysconfig/network
/etc/hostname
/etc/HOSTNAME
修改 hosts 文件
修改/etc/hosts文件确保GP集群用到的所有主机名都进行了正确的配置,确保
所有GP数据库集群会使用到的网络接口都配置了正确的名称。将修改好的文件覆盖到
GP集群中的所有主机上。
修改 sysctl.conf 文件
将 GP 集群中所有主机的/etc/sysctl.conf 文件修改为如下内容:
kernel.shmmax = 5000000000000
kernel.shmmni = 32768
kernel.shmall = 40000000000
kernel.sem = 1000 32768000 1000 32768
kernel.sysrq = 1
kernel.core_uses_pid = 1
kernel.msgmnb = 1048576
kernel.msgmax = 1048576
kernel.msgmni = 32768
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.tcp_max_syn_backlog = 32768
net.ipv4.tcp_syn_retries = 3
版权所有:Esena(陈淼 ) 编写:陈淼 - 275 -
Greenplum Database 管理员指南 V6.2.1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.conf.all.arp_filter = 1
net.ipv4.ip_local_port_range = 1025 65535
net.ipv4.ip_local_reserved_ports =
5432,40000-40127,41000-41127,50000-50127,51000-51127
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.core.netdev_max_backlog = 80000
net.core.rmem_default = 2097152
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
vm.overcommit_memory = 2
vm.overcommit_ratio = 95
vm.swappiness = 0
vm.zone_reclaim_mode = 0
vm.dirty_expire_centisecs = 200
vm.dirty_writeback_centisecs = 100
vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 5
vm.dirty_bytes = 0
vm.dirty_ratio = 10
这里就不对每一项做解释了,这个配置是编者一直使用的版本,有兴趣可以对其中
的配置项深入研究一下,也欢迎反馈给编者。有些配置设置的比推荐值大了很多,主要
目的是为了使用多种硬件配置环境,比如共享内存等,实际上,真实的内存使用量,数
据库本身仍会有限制参数。
修改 limits 文件
将 GP 集群中所有主机的/etc/security/limits.conf 文件进行如下修改:
# sed -e s/^ulimit/#ulimit/ -i /etc/profile
# sed -e /^[^#]/d -e /^[[:space:]]*$/d -i /etc/security/limits.conf
# echo '' >> /etc/security/limits.conf
# echo '* soft nofile 1048576' >> /etc/security/limits.conf
# echo '* hard nofile 1048576' >> /etc/security/limits.conf
# echo '* soft nproc
1048576' >> /etc/security/limits.conf
# echo '* hard nproc
1048576' >> /etc/security/limits.conf
# nprocname="/etc/security/limits.d/90-nproc.conf"
# if [ -f "/etc/security/limits.d/20-nproc.conf" ];then
版权所有:Esena(陈淼 ) 编写:陈淼 - 276 -
Greenplum Database 管理员指南 V6.2.1
#
nprocname="/etc/security/limits.d/20-nproc.conf"
# fi
# if [ -f $nprocname ];then
#
sed -e /^[^#]/d -e /^[[:space:]]*$/d -i $nprocname
#
echo '' >> $nprocname
#
echo '*
soft nproc
1048576' >> $nprocname
#
echo 'root soft nproc
1048576' >> $nprocname
# fi
确认 XFS 挂载参数
RHEL和CentOS的XFS挂载参数为:
rw,nodev,noatime,nobarrier,inode64
Ubuntu不支持nobarrier参数,因此,其XFS挂载参数为:
rw,nodev,noatime,inode64
比如在/etc/fstab文件中的挂载配置为:
/dev/sdc /data xfs nodev,noatime,nobarrier,inode64 0 0
确认 IO 参数和 Huge Page 设置
执行如下命令来修改IO参数和Huge Page设置:
# localfile="/etc/rc.d/rc.local"
# if [ -f "/etc/init.d/boot.local" ];then
#
localfile="/etc/init.d/boot.local"
# fi
# chmod +x $localfile
# sed -e "/^####GP_BEGIN/,/^####GP_END/d" -i $localfile
# cat <<'END_OF_CMD'
>> $localfile
> ####GP_BEGIN'
版权所有:Esena(陈淼 ) 编写:陈淼 - 277 -
Greenplum Database 管理员指南 V6.2.1
> for i in /dev/sd*;do blockdev --setra 16384
$i;done
> for i in /sys/block/sd*/queue/scheduler;do echo deadline > $i;done
> echo never > /sys/kernel/mm/transparent_hugepage/enabled
> ####GP_END
> END_OF_CMD
# sed -n "/^####GP_BEGIN/,/^####GP_END/p" $localfile|bash
确认 ssh 设置
由于GP的集群操作是使用ssh来实现的,在实例多的集群中,可能会同时向一个机
器发起多个ssh访问,缺省的ssh设置,可能会遭遇如下报错:
ssh_exchange_identification: Connection closed by remote host
执行如下命令来修改ssh的MaxStartups参数:
# sed s/.*MaxStartups.*/'MaxStartups 400:30:500'/ -i /etc/ssh/sshd_config
根据不同的系统,使用不同的命令来生效修改:
# ##RHEL7
# systemctl reload sshd.service
# ##RHEL6
# service sshd reload
# ##SuSE
# service ssh reload
时钟同步
请根据具体的操作系统,配置时钟同步。GP数据库要求所有机器的时间要保持同步。
版权所有:Esena(陈淼 ) 编写:陈淼 - 278 -
Greenplum Database 管理员指南 V6.2.1
创建 GP 数据库的管理员用户
一般,根据惯例,GP数据库的管理员用户使用gpadmin(例如uid为300)这个名
称,例如:
创建gpadmin用户组:
# groupadd -r -g 300 gpadmin
创建gpadmin用户:
# useradd -r -m -g gpadmin -u 300 gpadmin
为gpadmin用户设置密码:
# echo gpadmin | passwd gpadmin --stdin
安装 GP 软件
获取安装包,根据安装包的类型,选择合适的安装方式。比如在6版本,只有rpm
包可选,建议使用rpm命令来安装,在5版本和4版本,有zip包的情况下,可以通过解
压后使用bash命令执行bin文件安装,开源版本,则需要通过源码编译来安装。例如:
$ sudo rpm -ivh greenplum-db-<version>-<platform>.rpm
$ sudo chown -R gpadmin:gpadmin /usr/local/greenplum*
建立 ssh 互信
GP要求所有主机之间,gpadmin用户可以免密ssh访问,在6版本之前,通过命令
gpssh-exkeys,可以自动完成所有步骤,而6版本,该命令有了变化,必须先确保
Master和其他主机之间已经建立了互信关系,才能完成全局互信。例如:
$ ssh-copy-id -i ~/.ssh/id_rsa.pub gpadmin@sdw01
在完成Master和其他主机的互信之后,可以使用gpssh-exkeys命令建立全局互信:
版权所有:Esena(陈淼 ) 编写:陈淼 - 279 -
Greenplum Database 管理员指南 V6.2.1
$ gpssh-exkeys -f hostfile_exkeys
其中hostfile_exkeys文件中包含GP集群中所有会被GP数据库使用到的主机名
和子网端口名称。例如:
mdw
mdw-1
mdw-2
smdw
smdw-1
smdw-2
sdw1
sdw1-1
sdw1-2
sdw2
sdw2-1
sdw2-2
注意:主机名不能有下划线,下划线属于非法字符,在有些系统中可能会带来麻烦。
安装确认
在所有主机上安装完GP数据库软件之后,有必要检查一下所有主机上都已经正确
的安装。可以通过如下步骤来验证。
1、 使用gpadmin用户登录Master服务器:
# su - gpadmin
2、 使用gpssh工具批量检查所有主机上的安装目录:
# gpssh -f hostfile_exkeys -e 'ls -l /usr/local/greenplum-db/bin/gpstart'
如果安装成功了,该命令将会自动登录所有主机,并列出gpstart命令的文件。
版权所有:Esena(陈淼 ) 编写:陈淼 - 280 -
Greenplum Database 管理员指南 V6.2.1
GP 软件目录结构
greenplum_path.sh -- GP数据库运行需要的环境变量文件。
bin -- GP数据库的管理命令所在的目录。
docs/cli_help -- GP数据库命令的帮助信息。
docs/cli_help/gpconfigs -- gpinitsystem命令的示例文件目录。
ext -- GP数据库命令所需的一些依赖软件,比如Python。
include -- GP数据库的一些C语言头文件。
lib -- GP数据库以及PostgreSQL的库文件。
sbin -- 内部脚本和命令。
share -- GP数据库的共享文件。
创建数据库工作目录
GP的所有PostgreSQL实例工作在独立的监听端口,同时,需要工作在独立的文
件系统目录,所以,需要在每台主机上为Primary和Mirror创建工作目录。
创建 Master 的工作目录
通常,Master和Standby的工作目录与计算节点不同,一般来说,Master的工
作目录会有一层目录叫做master,以明确的界定这是Master的工作目录,在以后的
日常维护工作中,可以更直观和快速的找到Master的工作目录。
Master不存储用户数据,只存储系统表信息,和一些全局信息,不过,这不等于
说Master的磁盘指标就不重要。一般来说,Master目录的容量不需要像计算节点那
么大,但最好还是要有一定的保障,比如1TB的尺寸还是有必要的,因为会有日志等信
息的累积。另外,Master磁盘的性能也不能太差,毕竟系统表的性能影响也不能忽略。
如果条件允许,可以考虑为Master目录配置NVMe,保证系统表的性能。
版权所有:Esena(陈淼 ) 编写:陈淼 - 281 -
Greenplum Database 管理员指南 V6.2.1
例如,同时在Master(mdw001)和Standby(mdw002)两台主机的/data目录下
创建一个子目录master,并将owner改为gpadmin:
# ./usr/local/greenplum-db/greenplum_path.sh
# gpssh -h mdw001 -h mdw002 -e 'mkdir -p /data/master/default'
# gpssh -h mdw001 -h mdw002 -e 'chown gpadmin. /data/master'
# gpssh -h mdw001 -h mdw002 -e 'chown gpadmin. /data/master/default'
创建 Instance 的工作目录
在6版本之前,tablespace不是一个独立的概念,其必须基于filespace来创建,
而filespace在创建时,允许为Primary和Mirror创建不同的路径,所以,按照惯
例,为了区分Primary和Mirror,初始化路径也使用primary和mirror子目录来做
区分,这也是很容易实现的。
然而,在6版本中,filespace的概念没有了,取而代之的是,在CREATE
TABLESPACE时直接指定统一的路径,或者为每个content值的Instance指定一个路
径,但不能为Primary和Mirror指定不同的路径。虽然,在初始化安装时,仍然可以
按照惯例为Primary和Mirror设置不同的路径,但是,如果再创建tablespace,两
者将会遵从不同的路径规则,可能会带来不必要的困扰,因此,编者建议不再遵从这个
惯例,在6版本中,Primary和Mirror完全可以使用相同的目录路径(接下来的示例为
了便于理解,有些示例可能仍会使用不同的目录路径,但这只是为了示例)。例如,在
sdw001 ~ sdw004上,在/data1和/data2目录下,创建初始化缺省的工作路径:
# ./usr/local/greenplum-db/greenplum_path.sh
# gpssh -hsdw{001..004} -e 'mkdir -p /data{1,2}/{default,gpfs}'
# gpssh -hsdw{001..004} -e 'chown gpadmin. /data{1,2}/{default,gpfs}'
对于5版本和4版本,可以按照惯例来创建Instance的工作目录:
# ./usr/local/greenplum-db/greenplum_path.sh
# gpssh -hsdw{001..004} -e 'mkdir -p
/data{1,2}/{primary,mirror}/{default,gpfs}'
# gpssh -hsdw{001..004} -e 'chown gpadmin. /data{1,2}/{primary,mirror}'
# gpssh -hsdw{001..004} -e 'chown gpadmin.
/data{1,2}/{primary,mirror}/{default,gpfs}'
版权所有:Esena(陈淼 ) 编写:陈淼 - 282 -
Greenplum Database 管理员指南 V6.2.1
系统性能检查
在真正使用GP数据库集群用于生产应用之前,应该使用GP提供的性能测试命令
gpcheckperf对集群中所有主机的硬件性能进行评估检查,确保性能符合预期。
检查网络性能
通过gpcheckperf命令的-r n、-r N或-r M参数来测试网络性能,结果以MB
为单位来显示。-r n是进行串行一对一测试,-r N是进行并行一对一测试,-r M是
进行全矩阵交叉测试。
从指定的参与测试的网络端口列表,按照顺序进行配对,比如,-r n,按照顺序,
第一个向第二个发包,发包完成后,第二个向第一个发包,然后,第三个和第四个配对,
顺序相互发包,然后依次测试剩下的网络端口,直到所有的网络端口测试完。如果是
-r N,匹配的顺序与-r n一致,不同的是,所有的分组测试同时开始相互发包。对于
-r n和-r N的情况,如果是奇数个网络端口,最后一个会和第一个再组成一组,对于
-r N的测试,可能会影响最终的显示结果。-r M则是每个网络端口都向其他网络端口
发包,形成全矩阵式交叉测试。
-r n和-r N能够体现网卡之间的独立性能,而-r M则更能体现实际生产使用时
的网络负载能力,是真实的工作模式。
如果一台机器上有多个网卡,会有不同的子网端口(也可以称为hostname),在测
试时,应该避免同一台机器的不同子网端口之间配对测试,因为这种情况体现的是主机
内的本地网络速度,性能很高,对测试结果会是很大的混淆,如果网络有跨交换机的情
况,为了测试交换机之间的性能,应该避免同一交换机内的配对,可以使用-r N模式,
配置不同交换机的网络端口进行配对测试。
例如,下面是4个计算节点的子网端口情况:
主机名
一号子网端口
二号子网端口
sdw001
sdw001-1
sdw001-2
sdw002
sdw002-1
sdw002-2
sdw003
sdw003-1
sdw003-2
sdw004
sdw004-1
sdw004-2
可以根据子网端口创建两个主机名文件。例如:
hostfile_gpchecknet_ic1
hostfile_gpchecknet_ic1
版权所有:Esena(陈淼 ) 编写:陈淼 - 283 -
Greenplum Database 管理员指南 V6.2.1
sdw001-1
sdw001-2
sdw002-1
sdw002-2
sdw003-1
sdw003-2
sdw004-1
sdw004-2
例如,根据创建的主机名文件,分别进行并行配对测试:
# ./usr/local/greenplum-db/greenplum_path.sh
# gpcheckperf -f hostfile_gpchecknet_ic1 -r N -d /tmp
# gpcheckperf -f hostfile_gpchecknet_ic2 -r N -d /tmp
缺省情况下,数据包发送时间为15秒,可以通过--duration参数来自定义发送
的时间长度,单位可以是秒(s)、分钟(m)、小时(h)或天(d)。一般来说,对于-r n
和-r N没有必要修改时间长度,而-r M,测试几分钟就差不多了。
检查磁盘性能
通过gpcheckperf命令的-r d参数对磁盘性能做测试,结果以MB为单位来显示。。
磁盘性能测试,实际上是使用Linux的dd命令在指定的目录中进行连续的大文件读写
测试。
进行磁盘性能测试之前,要确定需要测试的目录,需要测试的主机名称列表,比如
hostfile_gpcheckperf文件中包含了需要进行磁盘性能测试的节点的主机名:
sdw001
sdw002
sdw003
sdw004
例如,要对hostfile_gpcheckperf文件中列出的主机进行测试,测试的目录为
/data1和/data2:
$ gpcheckperf -f hostfile_gpcheckperf -r d -d /data1 -d /data2 -D
缺省情况下,按照当前运行命令主机的物理内存的2倍进行磁盘性能测试,命令会
根据指定的目录的数量进行均匀分割尺寸,如果磁盘性能很高,可能会出现dd命令的
CPU资源100%的情况,这种情况下,可以通过指定更多的子目录,分拆更多的dd命令
来进行测试,切记不要指定完全相同的-d参数,这样会导致测试结果严重失真。有时
候会有用户选择使用fio命令来测试磁盘性能,fio是直接对磁盘设备进行操作的,不
经过文件系统,所以,会对文件系统产生破坏,如果确实需要使用fio来测试,需要确
版权所有:Esena(陈淼 ) 编写:陈淼 - 284 -
Greenplum Database 管理员指南 V6.2.1
保设备没有被文件系统使用,或者可以接受损坏的后果。另外,fio的测试结果并不能
真实反映文件系统的性能,和gpcheckperf的测试结果不具有直接的可比性。
注意:对于磁盘性能完全未知的情况下,为了避免直接运行大尺寸的性能测试耗时太久,
可以先进行小尺寸的磁盘性能测试,确保磁盘性能不是太差,之后在增加测试尺寸,最
终使用缺省尺寸进行测试。如有必要,还是应该指定尺寸,比如Master主机的内存尺
寸与计算节点主机不一致,或者gpcheckperf计算尺寸出错等。通过-S参数来执行测
试尺寸,详情可以参考gpcheckperf命令的help信息。
初始化 GP 数据库集群
在前面的准备工作全部做完之后,就可以开始初始化GP集群了。接下来将逐步介
绍初始化一个GP集群的常规方法,定制化方案不会过多提及。实际上,编者对这一章
的内容不太感兴趣,因为编者早就不这样安装部署和初始化GP数据库集群了,因为这
样太费劲了,完全就是体力活,完全可以自动完成,所以,编者一直致力于优化一个更
好的自动化脚本来完成本章的工作。但对于学习来说,这部分内容还是很有价值的,因
为这非常有助于了解如何一步一步初始化一个GP集群,熟悉GP集群的架构关系,对日
常的开发使用和运维都会有很大的帮助。
创建初始化网络端口文件
gpinitsystem命令可以通过一个网络端口清单文件来指定,在哪些主机上初始
化GP集群,该文件指定的是计算节点,不包含Master和Standby主机。初始化命令根
据gpinitsystem_config配置文件中指定的目录个数来决定在一个计算节点的主机
上初始化多少个Instance。当一个主机上有多个子网端口时,多个Instance将会均
分到所有的子网端口上。文件的格式为,每个网络端口一行。
比如,主机名如下所示:
sdw001
sdw002
sdw003
sdw004
子网端口可以采用-1、-2这种加后缀的方式来命名。要在GP集群中使用这些子网
端口,需要在初始化网络端口文件中,使用这些子网端口(可以不使用主机名,
gpinitsystem会自动获取主机名来分析各个子网端口属于哪个主机),初始化时,
Instance将会分散到不同的子网端口上。例如,网络端口文件
版权所有:Esena(陈淼 ) 编写:陈淼 - 285 -
Greenplum Database 管理员指南 V6.2.1
hostfile_gpinitsystem中包含如下信息:
sdw001-1
sdw001-2
sdw002-1
sdw002-2
sdw003-1
sdw003-2
sdw004-1
sdw004-2
注意:不管是主机名还是子网端口,都必须已经在所有主机的/etc/hosts文件中配置
好,否则gpinitsystem命令会报错说主机名无法识别,通过DNS配置也是可以的。
创建初始化配置文件
初始化配置文件,决定了gpinitsystem创建一个什么样的集群。数据库软件安
装好之后,在安装目录下已经有一个初始化配置文件模板:
$GPHOME/docs/cli_help/gpconfigs/gpinitsystem_config
可以通过拷贝模板的方式来创建初始化配置文件。例如:
$ cat $GPHOME/docs/cli_help/gpconfigs/gpinitsystem_config >
~/gpinitsystem_config
根据环境的情况修改刚刚复制的文件。一个GP系统,必须要有一个Master,也必
须要有Primary,如果有Mirror,一般至少需要两个计算节点主机。
通过DATA_DIRECTORY参数来指定一个主机上配置多少个Primary。当一个主机
上有多个子网端口时,多个Instance将会均分到所有的子网端口上。PORT_BASE指
定了端口的开始值,这些端口最好设置在/etc/sysctl.conf文件中
net.ipv4.ip_local_reserved_ports参数的范围内,这样的话,这些端口就不
会被作为动态端口分配给客户端程序。
ARRAY_NAME="Greenplum Data Platform"
SEG_PREFIX=gpseg
PORT_BASE=40000
declare -a DATA_DIRECTORY=(/data1/primary /data1/primary /data1/primary /
data2/primary /data2/primary /data2/primary)
版权所有:Esena(陈淼 ) 编写:陈淼 - 286 -
Greenplum Database 管理员指南 V6.2.1
MASTER_HOSTNAME=mdw001
MASTER_DIRECTORY=/data/master
MASTER_PORT=5432
TRUSTED_SHELL=ssh
CHECK_POINT_SEGMENTS=8
ENCODING=UNICODE
SEG_PREFIX指的是,在DATA_DIRECTORY声明的目录下创建的子目录的前缀,
后缀是Instance的Content(参考gp_segment_configuration系统表的
content字段)值。PORT_BASE指的是,在一个主机上,Primary的监听端口从多少
开始连续分配,比如上述的例子中,该参数的值为40000,而DATA_DIRECTORY参数
指定了6个目录,就会在一台主机上初始化6个Primary,这6个Primary的监听端口
就依次为40000 ~ 40005。DATA_DIRECTORY实际上是一个数组,指定了将在每个
主机的哪些目录下初始化Primary,上述的例子中,指定了6个目录,初始化命令将会
在这6个目录下初始化6个Primary,这里的目录是可以重复的,因为,真正的工作目
录是这些目录下再创建的子目录,由SEG_PREFIX参数指定了子目录的前缀,由
content值决定了子目录的后缀。MASTER_HOSTNAME参数指定了Master所在的主机
的主机名,初始化命令会将该主机作为Master。MASTER_DIRECTORY指定了Master
的工作目录,不过,Master的实际工作目录也是要创建一个子目录,规则与Primary
相同,content值为-1,所以,常见的名称为gpseg-1。MASTER_PORT指定了Master
的监听端口,这是整个GP集群的访问入口端口,客户端程序通过该端口来访问数据库
集群。TRUSTED_SHELL指的是使用什么命令来执行远程命令,之前准备的互信在这里
就开始用上了。CHECK_POINT_SEGMENTS指定了WAL检查点最多可以等待的WAL文件
个数,如无必要,建议不修改,增加该参数的值,checkpoint的频繁度会降低,但崩
溃后恢复的时间就会延长,数据库初始化之后,仍然可以通过checkpoint_segments
参数来修改这一配置。ENCODING参数指定了服务端的编码集,建议不要修改,对于中
文环境,没有更好的选择,与编码集相关的还有--locale、--lc-collate和
--lc-ctype参数,这几个是gpinitsystem的命令行参数,具体可以参考
PostgreSQL文档,值得注意的是,在6版本之前,CREATE DATABASE命令没有
LC_COLLATE选项,缺省的排序行为遵循UTF8编码集,这会导致,ascii字符串的排
序不是按照ascii编码进行排序的,很多时候不符合预期,可以通过--lc-collate
参数在初始化时指定排序特征。在6版本中,要创建一个LC_COLLATE属性与模板库不
同的Database是有限制的,模板库只能是template0,否则会报错失败。
如果在初始化时选择配置Mirror,还需要配置Mirror相关的参数,通过
MIRROR_PORT_BASE参数指定Mirror端口的开始值,该参数的特点与PORT_BASE完
全相同。例如:
#REPLICATION_PORT_BASE=41000
#MIRROR_REPLICATION_PORT_BASE=51000
MIRROR_PORT_BASE=50000
declare -a MIRROR_DATA_DIRECTORY=(/data1/mirror /data1/mirror /data1/
mirror /data2/mirror /data2/mirror /data2/mirror)
版权所有:Esena(陈淼 ) 编写:陈淼 - 287 -
Greenplum Database 管理员指南 V6.2.1
注释掉的两行,是6以前的版本需要用到的端口,REPLICATION_PORT_BASE是
Primary的复制端口,MIRROR_REPLICATION_PORT_BASE是Mirror的复制端口,
6版本已经不再需要这两个参数,6版本不再使用filerep进行Primary和Mirror之
间的同步复制,而是使用WAL复制。
MIRROR_PORT_BASE的特点可以参考前面讲到的PORT_BASE参数的解释,
MIRROR_DATA_DIRECTORY指定的是Mirror的工作目录信息,特点参考前面讲到的
DATA_DIRECTORY参数。
关于Primary的工作目录和Mirror工作目录是否要相同,参见"创建Instance
的工作目录"章节。
执行初始化操作
通过gpinitsystem命令,根据配置文件中设置的情况,初始化一个新的GP数据
库集群。该操作需要使用gpadmin用户来进行。例如:
$ ./usr/local/greenplum-db/greenplum_path.sh
$ gpinitsystem -c gpinitsystem_config -h hostfile_gpinitsystem
如果要在初始化的时候设置Standby,可以通过-s参数指定Standby的主机名来
实现,例如:
$ gpinitsystem -c gpinitsystem_config -h hostfile_gpinitsystem -s mdw002
如果在初始化时选择了设置Mirror,可以通过--mirror-mode参数来指定
Mirror的策略,自带的Mirror策略有两种,group和spread,缺省为group。根据
主机名的排序,所有的主机组成一个环,在环上的每个主机,其Primary对应的Mirror
会分布在后续的主机上。group的意思是,一个主机上所有Primary对应的Mirror都
在环中的下一个主机上。spread的意思是,一个主机上所有Primary对应的Mirror
一个一个分散到后面的多个主机上,当前主机上有多少个Primary,Mirror就分散到
多少个后续主机上。因此,group镜像策略,要求最少要有两台计算节点主机,spread
镜像策略,要求最少的计算节点主机的数量要大于一台主机上Primary的数量。
如果要定制镜像策略,可以在gpinitsystem时不配置Mirror,在初始化成功之
后,通过gpaddmirrors命令来创建Mirror,通过对Mirror配置文件进行定制化编
辑的方式实现任意的Mirror策略。编者的自动化命令实现了更复杂和优化的镜像策略,
可以参考"Instance镜像"章节。
在执行gpinitsystem命令过程中,命令会自动检查所有主机的环境,初始化参
数文件,确定可以继续初始化后,会提示确认是否继续,根据提示输入需要的信息后继
版权所有:Esena(陈淼 ) 编写:陈淼 - 288 -
Greenplum Database 管理员指南 V6.2.1
续初始化安装操作。例如:
Continue with Greenplum creation? Yy/Nn
gpinitsystem命令在确认输入[Yy]后,会继续进行并行的集群初始化操作,在
初始化成功之后,GP数据库集群就处于已启动状态,并会输出如下消息:
Greenplum Database instance successfully created
初始化异常排查
在初始化过程中,如果某个Instance创建或启动失败,都会导致初始化报错失败,
初始化操作的日志信息会存储在gpadmin用户的gpAdminLogs目录下,日志文件以命令
的名称和日期命名。例如:
gpinitsystem_20200705.log
通常,在初始化日志中会有相关的失败原因,比如操作系统参数没有正确的修改导
致内存分配不足,或者SELinux未禁用,或者防火墙未关闭等,SELinux和防火墙的
问题可能会表现为无法访问远程主机或数据库Instance。对于实例启动失败的情况,
还可以查看具体Instance的日志,日志中会详细显示为什么实例启动失败。应该根据
日志信息解决相关的问题,之后再重新初始化集群。
回退脚本
在gpinitsystem命令失败时,会给出一个回退脚本,位于gpadmin用户的
gpAdminLogs目录下。格式为:
~/gpAdminLogs/backout_gpinitsystem_<user>_<timestamp>
通过运行该回退脚本,将会清除由gpinitsystem命令产生的目录,文件和日志等信
息,关闭残余的postgres数据库进程,清理完成后,解决了失败的原因,就可以重新尝试
初始化GP集群了。例如:
$ sh backout_gpinitsystem_gpadmin_20200705_141658
版权所有:Esena(陈淼 ) 编写:陈淼 - 289 -
Greenplum Database 管理员指南 V6.2.1
为 gpadmin 用户配置环境变量
为了使得gpadmin用户每次登陆操作系统之后,能够直接对数据库进行操作,需
要为gpadmin用户配置好必要的环境变量。通常修改.bashrc配置文件,比如使用vi
命令修改。例如:
$ vi ~/.bashrc
加入如下环境变量设置信息:
####GP_BEGIN
if [ -e /usr/local/greenplum-db ];then
. /usr/local/greenplum-db/greenplum_path.sh
fi
export MASTER_DATA_DIRECTORY=/data/default/gpseg-1
export PGPORT=5432
export LD_PRELOAD=/lib64/libz.so.1 ps
####GP_END
如果有必要,还可以指定缺省的登录用户和登录的数据库名称,甚至指定登录密码。
例如:
export PGUSER=gpadmin
export PGDATABASE=postgres
export PGPASSWORD=gparray
版权所有:Esena(陈淼 ) 编写:陈淼 - 290 -
Greenplum Database 管理员指南 V6.2.1
第十三章:启动与停止 GP 数据库
在使用GP数据库时,常规的启动和停止数据库都是一个分布式操作。所有主机上
的Master、Standby、Primary和Mirror,共同组成了一个分布式系统的整体,表
现为一个统一的数据库系统,所以,启动,是所有实例都启动,停止,是所有实例都停
止。
既然是分布式系统,启动过程自然也就不同于一般的数据库系统。细心的用户可能
已经发现,整个启动过程大致可以分为5个阶段:
1. 启动Master,以Master Only的模式启动,其效果与gpstart -m一致。
2. 获取集群的配置信息。
3. 关闭Master,其效果与gpstop -m一致。
4. 启动所有的Primary和Mirror。
5. 正常启动Master。
这里需要解释一下,为什么会分为这么多阶段,因为这是一个分布式系统,整个系
统的信息是存储在数据库中的,我们在安装配置GP集群的时候,会涉及到Master的主
机名、目录和端口,Standby的主机名、目录和端口,所有Primary以及Mirror的主
机名、目录和端口,这些信息统一保存在gp_segment_configuration系统表中。
当然,这些信息不可能保存在Master的某个配置文件中(虽然表中存储数据的也是文
件),因为那样太容易被篡改了。
因此,启动命令需要根据MASTER_DATA_DIRECTORY环境变量或者-d参数来确定
Master的工作目录,读取postgresql.conf配置文件,获取port参数,启动Master
实例。gp_segment_configuration系统表其实是Master Only的系统表,Master
启动之后,启动命令就可以通过Utility模式获取整个集群的配置信息,然后关闭
Master(因为此时的Master的模式不能提供正常的连接和访问),然后根据获取的集
群配置信息来启动Primary和Mirror,一定要先启动Primary和Mirror,因为,只
有数据是完整的,数据库才能提供正常的服务,Primary和Mirror能否正常启动,直
接决定了集群启动的成败,如果有成对的Primary和Mirror启动失败,将会报出如下
错误,且数据库启动整体失败:
Do not have enough valid segments to start the array.
这种情况,一般称为double fault、double down,或者双宕。解决这种问题
并没有什么简单的方法,找到最后一个没有在gp_segment_configuration系统表
中被标记为down的启动失败的Instance,根据报错日志解决相关的问题,之后再尝
版权所有:Esena(陈淼 ) 编写:陈淼 - 291 -
Greenplum Database 管理员指南 V6.2.1
试重新启动集群。这种情况不是gprecoverseg命令能处理的,因为数据库已经不可
用了,所有依赖数据库可正常工作的命令都已经不能正常工作,gprecoverseg是根
据健康的Primary或Mirror来恢复与其对应的Mirror或Primary,所以该命令无法
处理双宕故障。
通过位于安装路径的bin目录下的gpstart和gpstop命令来启动和停止GP数据
库集群,这两个命令和PostgreSQL的pg_ctl命令的功能类似,区别是,gpstart和
gpstop提供了集群操作,对于单实例的操作,实际上仍然可以通过pg_ctl来完成,
编者提醒,pg_ctl命令应该仅在必要时刻使用。
注意:尽量不要使用OS的kill命令来终止Postgres进程,而是要使用
pg_cancel_backend函数或者pg_terminate_backend函数来完成。当然也不是
完全不可以用,除非有把握确保不会导致数据库损坏。通过kill -9或者kill -11
可能会导致数据库崩溃,且无法记录异常日志,以至于无法进行RCA(root cause
analysis)。另外,kill -9或者kill -11即便没有导致数据库宕机,也会导致所
有连接中断,这个副作用是必然会发生的。
启动 GP 数据库
在Master上,使用gpstart命令来启动一个已经存在的GP集群。GP数据库在初
始化成功时已经处于启动状态,不需要执行gpstart命令,对已经启动的集群执行
gpstart命令会收到如下报错:
Master instance process running
对于初始化成功之后的GP集群,已经处于停止状态的情况下,通过gpstart命令
来启动集群,gpstart命令会完成整个集群的启动,Primary和Mirror的启动是并行
的。gpstart命令应该在Master主机上,由gpadmin用户来执行:
$ gpstart
gpstart命令常见的参数有:
1.
-a,不提示确认,如果没有指定该参数,将会有确认继续的提示信息:
Continue with Greenplum instance startup Yy|Nn (default=N):
2.
-m,启动的只是Master实例,在运维的时候会经常用到。不过,对于Primary
实例来说,也可以使用gpstart -m的方式来单独启动,比如在处理故障时,可以
通过这种方式来测试某个Primary是否可以正常启动,虽然启动时会收到如下错
误,但这并不影响成功启动。
版权所有:Esena(陈淼 ) 编写:陈淼 - 292 -
Greenplum Database 管理员指南 V6.2.1
4版本和5版本的错误信息为:
gpstart failed. (Reason='Database does not contain gp_fault_strategy entry')
exiting...
6版本的错误信息为:
FATAL - no master dbs defined!
gpstart failed. (Reason='Error: GpArray() - no master dbs defined')
exiting...
3.
-R,限制模式启动数据库,在运维的时候会经常用到。限制模式,仅允许
SUPERUSER连接数据库,在进行系统表VACUUM FULL操作时,限制模式将可以确
保VACUUM FULL不受其他用户访问的影响,尽量命令执行的时间。
4.
-B,同时启动的实例数量,缺省值为64,最大值为128,一般不需要修改此参数。
5.
-y,启动集群时,忽略Standby。在Standby存在故障,影响集群的正常启动时,
可以通过该参数来跳过Standby的启动和检查,该参数只是跳过Standby,而不
会删除Standby,在特定的故障处理场景会很有帮助。
停止 GP 数据库
要停止一个GP数据库系统,使用gpstop命令来完成,只要Master是活着的,
gpstop会尝试停止集群中的所有实例,包括Standby、Primary和Mirror,哪怕这
些实例已经停止。缺省情况下,gpstop命令会一直等到所有连接都断开才停止数据库。
gpstop命令常见的参数有:
1.
-a,不提示确认,如果没有指定该参数,将会有确认继续的提示信息:
Continue with Greenplum instance shutdown Yy|Nn (default=N):
2.
-m,只关闭Master实例,在运维的时候会经常用到。与gpstart命令不同的是,
不能使用gpstop命令来单独停止Primary和Mirror实例,应该使用pg_ctl
stop的方式来停止。例如:
$ pg_ctl stop -D /data/primary/default/gpseg0
3.
-B,同时停止的实例数量,缺省值为64,最大值为128,一般不需要修改此参数。
4.
-u,在不停止数据库的情况下,使得pg_hba.conf配置文件的修改生效,使得
版权所有:Esena(陈淼 ) 编写:陈淼 - 293 -
Greenplum Database 管理员指南 V6.2.1
postgresql.conf配置文件中的运行时参数生效。类似于PostgreSQL的
pg_ctl reload命令,不同的是,gpstop -u是并行的,所有实例都会生效参
数的修改。需要注意的是,对于postgresql.conf配置文件中的参数,那些启动
参数不会立即生效,必须等到数据库重启时才能生效。
5.
-M,停止数据库的模式,可选值有:smart、fast、immediate,实际上,-M smart、
-M fast和-M immediate分别对应了三种缩写:-s、-f和-i,虽然help中没
有说明,但是命令是这样工作的,详情可以参考gpstop的Python源码。缺省情
况下,是smart模式,gpstop命令会一直等到所有连接都断开才停止数据库,一
般无法满足这个条件。最常使用的是fast模式,该模式会中断并回滚正在执行的
事务。immediate模式一般不建议使用,该模式有时可能会导致严重的数据损坏,
需要手动恢复数据库。
6.
--host,停止指定主机名上的所有实例。该参数主要用于将指定主机名的机器剥
离集群。
7.
-r,停止数据库并重新启动。该方式在重新启动数据库时不会在命令行输出日志
信息,所以,一般不建议这样操作,建议停止数据库之后通过执行gpstart命令
来启动数据库。
8.
-y,停止集群时,忽略Standby。该参数目前已知用处不多。
访问 Master Only 模式的 Master
通过gpstart -m启动的是Master Only模式,该模式下,启动的只有Master
实例,不会启动任何Primary和Mirror,也不会启动Standby。通常是为了进行特定
的维护操作。
注意:Master Only模式应该由专业服务人员进行操作。在该模式下,专业服务人员
将可以只对Master实例进行访问,以便进行Catalog的修改等操作。修改Catalog
的操作属于高风险操作,建议不要擅自尝试,否则后果自负。
使用gpstart的-m参数来启动Master Only模式:
$ gpstart -m
使用Utility模式连接Master实例。例如:
$ PGOPTIONS='-c gp_session_role=utility' psql postgres
在完成维护操作之后应该停止Master Only模式的Master实例。然后再正常启
动GP数据库集群。例如:
版权所有:Esena(陈淼 ) 编写:陈淼 - 294 -
Greenplum Database 管理员指南 V6.2.1
$ gpstop -m
注意:Master Only模式修改Catalog可能会导致集群状态不一致,甚至导致数据库
无法正常启动,这个操作应该由专业服务人员进行操作。通常Master Only模式修改
Catalog会导致Master和Standby的不一致,可能需要重建Standby,所以,正常
启动数据库之后,需要注意Standby的启动信息以及同步状态。
中断客户端进程
GP数据库会为每个客户端连接启动一个后台进程,计算实例上也会有相应的后台
进程。SUPERUSER可以取消查询或者中断客户端连接的后台进程。
通过pg_cancel_backend()函数来取消正在执行或者排队的SQL,通过
pg_terminate_backend()函数来中断客户端连接。
pg_cancel_backend()函数有两种参数模式(不过并不是所有版本都提供msg
参数选项,4版本没有msg参数,该参数从5版本开始提供):
pg_cancel_backend(pid int4)
pg_cancel_backend(pid int4, msg text)
pg_terminate_backend()函数也有两种参数模式(不过并不是所有版本都提供
msg参数选项,4版本没有msg参数,该参数从5版本开始提供):
pg_terminate_backend(pid int4)
pg_terminate_backend(pid int4, msg text)
pg_cancel_backend()函数,是取消正在执行或者排队的SQL,但不会中断客
户端的连接,客户端在SQL被取消之后,仍然可以继续执行其他SQL。
pg_terminate_backend()函数是中断客户端连接,客户端将无法继续使用被中断
的连接,要想继续访问数据库,必须重连建立数据库连接。
如果提供了msg参数,数据库在取消SQL或者中断客户端连接时,会将该信息发送
给客户端。消息的长度限制是128个字节,超出的部分会被截断,如果有中文被截断导
致半个中文,客户端将会收不到msg信息,而是收到如下的报错信息:
ERROR: Message skipped due to incorrect encoding.
如果pg_cancel_backend()函数和pg_terminate_backend()函数执行成
版权所有:Esena(陈淼 ) 编写:陈淼 - 295 -
Greenplum Database 管理员指南 V6.2.1
功了,将会返回true,否则会返回false,不过,返回true不等于说SQL就立即被取
消了,或者说连接就立即被中断了,有时,对于一些复杂事务,可能需要执行多次才能
达到取消和中断的目的。对于一些使用了外部资源的查询来说,还可能出现无法取消和
中断的情况,此时可能需要找到使用外部资源的子进程,先杀死这些子进程。
要取消查询或中断连接,要先找到后台的进程号。可通过pg_stat_activity系
统视图来查询,该视图在6版本有了较大的变化,在6版本中,进程号的字段为pid,在
6版本之前,进程号的字段为procpid。例如,查看所有正在执行和排队的SQL的信息:
=# SELECT usename, pid, waiting, state, query, datname FROM pg_stat_activity;
查询输出的示例:
可以根据查询的输出来确定需要取消或中断的后台进程号。比如,要中断查出来的
空闲连接,并通知客户端:"中断空闲连接",可以这样执行中断函数:
=# SELECT pg_terminate_backend(1542,'中断空闲连接');
FATAL: terminating connection due to administrator command: "中断空闲连接"
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
版权所有:Esena(陈淼 ) 编写:陈淼 - 296 -
Greenplum Database 管理员指南 V6.2.1
第十四章:开启高可用
GP数据库可以配置高可用,以使得GP数据库集群更可靠的运行。如果不能接受数
据丢失,GP数据库要求Master和Primary实例都必须开启高可用配置。也就是说,高
可用配置,不仅仅是系统可靠性的保证,也是数据安全的保证,GP支持为Master配置
Standby,为Primary配置Mirror,以确保GP数据库中的每个角色都有两份(互为备
份)。关于Master和Primary的镜像的更多介绍,可以参考"冗余与故障切换"章节。
GP 数据库高可用概述
要获得一个高可用的GP数据库集群,涉及多方面的因素,除了GP数据库本身提供
的,软件层面的冗余设置外,磁盘Raid,网络冗余,双集群等,也是重要的手段。同
时,还需要配合日常监控和维护,及时发现故障并解决,才能确保GP数据库集群长期
稳定运行。
硬件设备总是无法绝对避免出故障,尤其是一些比较低端或者价格低廉的X86设备,
根据编者的经验来看,购买配置良好,架构成熟,配件稳定的X86设备,是GP数据库集
群运行稳定的坚实基础。任何设备都有发生故障的可能,所以,GP数据库建议所有组
件都做冗余配置。对于有些用户来说,冗余的成本已经超过了故障恢复时间的容忍程度,
也可以考虑其他的数据安全方案,比如备份恢复,但是,如果数据只有一份,一旦出现
重大故障,官方技术支持也不能保证一定可以恢复数据,当然,对于一些极端故障,即
便有镜像,也存在无法恢复的可能性,但是,这种概率要低很多。
在使用GP数据库时,可以从以下几个方面考虑高可用的保护:
硬件层面的Raid保护
数据块的checksum校验
计算实例的Mirror镜像
Master的镜像
双集群灾备
逻辑备份与恢复
硬件层面的Raid保护
GP的最佳实践通常建议在生产环境配置Raid保护,比如Raid 5,可以将单盘失
版权所有:Esena(陈淼 ) 编写:陈淼 - 297 -
Greenplum Database 管理员指南 V6.2.1
败的故障隔离在GP数据库之外,而完全不会影响到数据库的运行状态。有很多生产环
境有这方面的安全要求,而且可能是硬性要求,这样可以为数据库提供多一层的保障,
如果条件允许,GP建议这样做,因为这样可以将故障隔离在硬件层面。
不过,对于是否应该做Raid,以及应该选择什么级别的Raid,GP数据库软件本身
并没有限制,毕竟用户的硬件环境也是各不相同的。不过,从性能角度来说,校验计算
越复杂,对Raid卡的性能要求也就越高,正如"Raid卡性能"章节中提到的,配置24
块机械盘的主机,Raid卡需要很高的配置,否则,磁盘的性能将得不到充分的发挥,
那是极大的浪费(如果可以接受这样的性能折损,也是可行的)。对Raid卡的要求是以
性能为导向的,比如使用NVMe,单盘的连续读写性能可以轻松超过1GB/S,甚至有些
可以到3GB/S左右,此时如果有多块NVMe,目前的常规Raid卡性能可能都无法满足多
块高性能NVMe磁盘的Raid 5策略,不仅如此,目前,还很少有Raid卡能直接支持NVMe
协议,如果用SATA口转接NVMe磁盘的话,还不如直接少花点钱用SATA口的SSD。如果
不那么在乎磁盘失效带来的影响,通过PCIE接口直连NVMe也许更能发挥磁盘的性能优
势。另外,Raid 5在出现单盘故障时的性能损失也是一个需要考虑的因素,虽然这种
故障的概率一般很低。
关于性能,是一个复杂的系统性问题,之前的章节已经解释过,GP诞生的最初目
标,是要解决共享存储的IO瓶颈,按照目前主流的X86配置,OLAP场景的IO问题其实
已经解决,24块10K转速的SAS机械盘,配合主流的Raid卡,划分为2组Raid 5,连
续读写能力已经可以达到3GB/S甚至更高,再配合库内压缩,这样的IO吞吐能力,80
Core的CPU配置也能常常跑满CPU资源,所以,仅从IO性能的角度来说,OLAP场景,
24块10K转速的SAS机械盘已经完全能够胜任。如果要考虑OLTP场景的IOPS能力和磁
盘的可靠性和稳定性,编者相信,在未来,SSD一定是更好的选择。
数据块的checksum校验
GP数据库在从磁盘读取数据到内存时,会检查数据文件是否已经发生损坏(前提时,
写入数据是计算了校验值并和Header一同写入磁盘)。这种损坏,可能是机械盘出现
坏道,Raid卡的程序有BUG等。不少个人计算机用户也曾遭遇过,长期存储的文件,
突然有一天,发现打开报错了。GP会为每个数据块存储一个checksum值,在读取数据
时,会校验数据块与checksum的值是否吻合,一旦发现不吻合,则相应的查询会报错
失败。
GP数据库内部的常规数据表,大体上可以分为两种类型:heap表(或者叫堆表)和
AO表(或者叫追加优化表)。在4.3版本之前,AO表实际上是Append-Only的缩写,意
思是,这种表是只能追加记录的,不能修改记录,虽然从4.3版本开始AO表的真实含义
已经是Append-Optimized,但为了保持语法的一致,AppendOnly这个关键字一直
延续和保留着,这并不影响对AO表数据的修改操作。在GP数据库内,这两种表都使用
了checksum来进行数据块的校验。AO表从诞生时就自带checksum支持,而且缺省是
打开的,而heap表的checksum是从5版本才开始支持。
在4版本时,heap表没有checksum检查,在5版本,heap表有了checksum检查。
然而,无论是heap表还是AO表,Mirror在收到同步的page时,缺省不会做checksum
版权所有:Esena(陈淼 ) 编写:陈淼 - 298 -
Greenplum Database 管理员指南 V6.2.1
检查,这将无法从根本上避免page损毁被同步到Mirror的情况发生。而6版本完全放
弃了filerep的机制,使用了WAL同步策略,这将从根本上避免了损毁page被同步到
Mirror的情况发生。
GP数据库对数据的修改操作是在内存中完成的,之后,数据会被刷入磁盘,在将
数据刷入磁盘时,数据库会自动计算checksum的值,并与数据一同保存到page中,
checksum的值将会作为page的header被一同存储到磁盘上。当从磁盘读取page时,
会根据checksum的值进行校验,如果校验不通过,数据库会报错,并导致事务失败。
所以,checksum是一个非常重要的保护,可以防止未被系统检测到的磁盘文件损
坏影响数据库的正常运行,因为并不是所有的异常都能够被磁盘管理系统或者操作系统
检测到。尤其是机械盘这种机械原理的硬件设备,异常是时有发生的,所以,厂商都会
设置一个经验性的阈值,只有异常比例超过预设的阈值时才被认为设备有故障,而在此
之前,可能已经有很多的异常发生,且已经影响到操作系统和数据库的正常运行。
目前的5版本和6版本,在使用gpinitsystem初始化数据库集群时,都是缺省打
开了heap表的checksum检查,虽然可以关闭,但这显然是不推荐的选择,可以通过
在gpinitsystem的初始化配置文件中,设置参数HEAP_CHECKSUM为off来关闭
heap表的checksum检查。实际上对应的是initdb命令的--data-checksums参数,
需要注意的是,这是初始化参数,在集群被初始化之后,无法修改此参数,因为这与数
据文件的结构相关,如果要修改此参数,只有重新初始化集群,所以,保持缺省打开是
最好的选择。虽然不能修改,但仍可以通过gpconfig命令和show来查看该只读参数
的值。例如:
$ gpconfig -s data_checksums
或者:
=# show data_checksums;
在执行gpstart命令来启动GP集群时,gpstart也会检查Master以及所有
Instance的heap表checksum设置是否一致。如果该参数的设置存在不一致,启动会
报错退出。虽然可以通过--skip-heap-checksum-validation参数来忽略启动时
的heap表checksum参数的一致性检查,但是,除非确有必要,否则不要使用。
在确实需要忽略checksum检查,以便恢复数据时,可以修改postgresql.conf
文件中的ignore_checksum_failure参数为on,这样,数据库在发现checksum校
验异常时,只是输出警告信息,而不会中断事务,并继续将磁盘上的数据读取到内存中。
之后,如果损毁的数据被再次修改,修改后的数据会被刷入磁盘,并且一定会被扩散到
Mirror(虽然在6版本是基于WAL同步,但由于更新的是错误的数据,WAL同步的也是
错误的更新结果),这可能会导致更严重的数据损坏或者数据丢失,所以,仅应该在进
行数据的灾难性恢复时考虑开启该参数。
对于AO表,可以针对每个表,甚至每个叶子分区来设置是否打开checksum校验,
版权所有:Esena(陈淼 ) 编写:陈淼 - 299 -
|
||
|
|
|