步骤1 check configuration
- 不能root用户
- 有initdb
- 用 -c 或 -I 指定了config
- source 这个 config 中的变量
- 必须在 config 中指定 port_base
- 检查是否需要 mirror
- 检查 machine_list
- 检查 data 目录
- 检查 log 目录
- 检查自己是 master 节点对应 hostname
- 检查 master port
- 检查 master 的 data 位置,有写入权限
- 确定 database 的名字
- 检查 master 最大连接数
- 检查 mirror data 目录
步骤2 check multihome
-
ping hosts
-
source cluster_config 文件
-
检查各host上segment号连续
-
检查host数量可以整除segment数量(host数量要小于segment instances数量)
-
将host的数量复制成segment的数量,方便后面操作
步骤3 create QE array (生成每个节点配置)
-
source cluster_config 文件
-
递增得到每个qe的port,检查未被占用
(GP_PORT= P O R T B A S E + PORT_BASE+ PORTBASE+PORT_COUNT)(CTRL_PORT= S E G C T R L P O R T + SEG_CTRL_PORT+ SEGCTRLPORT+PORT_COUNT)
-
得到 SEG_DIR_VECTOR
-
根据 mirror 类型创建 mirror (生成每个节点的配置,这里在spread类型的mirror引入了acaleph的server地址,但group类型的没有引入)
步骤4 check qe (使用 ssh 来访问其它主机)
-
检查分配的 port 不冲突
-
master 目录必须为空
-
检查 port 上没有活的 pg 进程
-
检查每个 host 上的 pg 版本一样
-
检查 QE 的 data 目录存在
-
检查 QE 的 lib 目录存在
-
检查 gp 的目录在各 host 上不存在
-
检查 /etc/hosts 下的gp各节点的 hostname 不能为 localhost, 否则可能有segment与master当成同一个的风险
-
检查对 qe 有写权限
-
对 mirror 节点检查没有 segment 实例的文件夹,且有写文件的权限
-
检查 standby 节点,可 ping 可读写,且 standby 上 master 的目录在 standby 上也存在(data 目录可以不一样)
步骤5 create master database
- 执行 initdb
initdb
-E encoding
-D gp_dir
--locale=locale_setting
--max_connection=XXX
--shared_buffers=XXX
--data-checksums=XXX # 如果开启了 heap checksum
--backend_output=gp_dir/.initdb
-
修改master 上的变量
port listen_address log_statement=all checkpoint_segments gp_contentid acaleph_server_address # acaleph server ctrl_port gp_dbid创建 master 的 hba 文件
-
创建 gpssh 的配置文件
-
创建 perfmon 的目录和配置
-
Starting the Master in admin mode(这里的日志记在pg_log中)
export PGPORT=$GP_PORT; pg_ctl -w -l $GP_DIR/pg_log/startup.log -D $GP_DIR -o "-i -p $GP_PORT -c gp_role=utility -m" start # 内部会进入 backend/main/main.c -> postmasterMain 函数,会启动一些背景进程,然后进入serverloop,当有连接时,就fork一个进程对这个 socket 启动 postgreMain。
-
删除锁和log
/tmp/.s.PGSQL.${GP_PORT}* ${GP_DIR}.log
-
停下master
$EXPORT_LIB_PATH export PGPORT=$GP_PORT pg_ctl -D $GP_DIR stop
-
检查 ping hostname
步骤6 create segment
-
对每个primary segment
-
export PG_CONF_ADD_FILE export STANDBY_HOSTNAME export ENCODING export LOCALE_SETTING export LC_ALL_SETTINGS export BACKOUT_FILE export LOG_FILE export PARALLEL_STATUS_FILE export TOTAL_SEG export ARRAY_NAME export CHECK_POINT_SEGMENTS export QE_MAX_CONNECT export QE_SHARED_BUFFERS export SEG_PREFIX
-
执行创建
gpcreateseg.sh -p PG_CONF_ADD_FILE $$ # 当前pid is_primary host1~port1~data_dir~dbid1~contentid~ctrlport~acalephaddr # seg info host2~port2~data_dir~dbid2~contentid # mirror info parallel_script_count log_file heap_check_sum master_ip standby_ip parallel_count batch_limit
-
内部会在 ssh 远程调用 initdb 函数
initdb -E encoding -D gp_dir --locale=US_zh $LC_ALL_SETTING --max_connection --shared_buffers --data-checksums --backend_ouput=$gp_dir.initdb
-
删除远端的 gp_dir 目录(用于创建工作路径)
-
配置 segment
port listen_address gp_contentid gp_dbid ctrl_port acaleph_server # acaleph address # PG_CONF_ADD_FILE 中的其它配置
-
配置hba
master standby 本地 ipv4 mirror ipv4 本地 ipv6 mirror ipv6
-
-
kill掉 segments,统计kill 数量
-
删除 /tmp/gpsegcreate.sh_backout (可以查看之前过程的输出)
步骤7 restart QD
-
export MASTER_DATA_DIRECTORY=${MASTER_DIRECTORY}/${SEG_PREFIX}-1 gpstop -a -l /home/user/gpAdminLogs -m -d MASTER_DATA_DIRECTORY # /home/ac2/data/demo/master/gpseg-1 output_level
-
export MASTER_DATA_DIRECTORY=${MASTER_DIRECTORY}/${SEG_PREFIX}-1 gpstart -a -l /home/user/gpAdminLogs -d $MASTER_DATA_DIRECTORY output_level
- start 过程会启动 master + segment (都是python脚本,最终调用pg_ctl,走 start_postmaster 函数,进入main.c(最终编译成了 bin/postgre ),走PostmasterMain 或 PostgresMain 逻辑)
步骤8 create database
psql
-p port
-d database_name
-c create database "$database_name"
>> /home/user/gpAdminLogs
步骤9 创建用户密码
psql
-p port
-d database_name
-c "alter user $USER_NAME password '$GP_PASSWD';"
>> /home/user/gpAdminLogs
步骤9 mirror 节点
-
在 catalog 注册 mirror
psql -p port -d database_name -A -t -c "select pg_catalog.gp_add_segment_mirror(${GP_CONTENT}::int2, '${GP_HOSTADDRESS}', '${GP_HOSTADDRESS}', ${GP_PORT}, '${GP_DIR}');"
对于 mirror 的创建
-
复制segment的数据
-
简单添加hba
-
pg_ctl reload
-
source greenplum_path.sh
-
执行 pg_basebackup 命令
pg_basebackup --xlog-method=stream --slot='internal_wal_replication_slot' -R -c fast -E ./db_dumps -E ./gpperfmon/data -E ./gpperfmon/logs -D ${GP_DIR} -h ${PRIMARY_HOSTADDRESS} -p ${PRIMARY_PORT} --target-gp-dbid ${GP_DBID};
-
启动 QE
export PGPORT=${GP_PORT} pg_ctl $PG_CTL_WAIT -l $GP_DIR/pg_log/startup.log -D $GP_DIR -o \"-i -p ${GP_PORT}\" start
-
停止 QE
export PGPORT=${GP_PORT}; pg_ctl -w -D $GP_DIR -o \"-i -p ${GP_PORT}\" -m immediate stop
-
-
创建 mirror segment(与创建 primary segment 同)
gpcreateseg.sh -p PG_CONF_ADD_FILE $$ # 当前pid is_mirror # 这里不同 host1~port1~data_dir~dbid1~contentid~ctrlport~acalephaddr # seg info host2~port2~data_dir~dbid2~contentid # mirror info parallel_script_count log_file heap_check_sum master_ip standby_ip parallel_count batch_limit
-
故障检测 FTS
# 检查 psql -p port -d database_name -A -t -c "select count(*) > 0 from gp_segment_configuration where (mode = 'n' or status = 'd') and content != -1;" # d: down n: no # 触发轮询 psql -p port -d database_name -c "select gp_request_fts_probe_scan()" # 如果60次还没启动起来,写日志 psql -p port -d database_name -A -t -c "select * from gp_stat_replication where sync_error != 'none' or sync_state != 'sync';" >> $LOG_FILE 2>&1
步骤10 启动 standby
-
export MASTER_DATA_DIRECTORY=${MASTER_DIRECTORY}/${SEG_PREFIX}-1; gpstandby -s $STANDBY_HOSTNAME -p port -S data_dir --hba_hostnames # 可选 -a
-
删除 standby 目录 (ssh)
-
stop standby (ssh)
pg_ctl -w -D ${MASTER_DIRECTORY}/${SEG_PREFIX}-1 -o "-i -p master_port" -m immediate stop
步骤11 提示信息
- 提示信息把以下信息放在 /etc/profile 中
. greenplum_path.sh
export MASTER_DATA_DIRECTORY=${MASTER_DIRECTORY}/${SEG_PREFIX}-1
# 或者 gpstate -d ${MASTER_DIRECTORY}/${SEG_PREFIX}-1
-
如果指定 standby 提示可用 gpactivatestandby 激活它
-
提示可访问的用户在 master/gpseg-1/pg_hba.conf 文件中定义
-
提示可用 gpinitstandby 创建 standby
补充:
读代码时做的一些 shell 脚本的笔记
# 声名全局数组
declare -a XXX
XXX=($aa $bb $cc)
echo ${#XXX[@]} # 会打印有值变量的数量,@为全部元素,#为参数个数
# 定义函数
aa(){
...
$1 # 传入参数
}
# 以\n分割
echo 'aa\naa' | cut -d'\n' -f2 aa.txt # 指定按 \n 分隔,显示每行第二列
# 去掉所有出现的\r字符
echo 'aa\raa' | tr -d '\r'
# 显示时间
date +%Y%m%d":"%H":"%M":"%S
# 取下传入参数 1 2
a=$1;shift # 1
b=$1;shift # 2
# unset 删除变量
# 读入python执行结果
read -d '' HOSTNAME_SORTER <<"END_PYTHON_CODE"
...
END_PYTHON_CODE
python -c "$HOSTNAME_SORTER"
# shell 中临时变量可以命名为 fake 而不用 temp
# 数学计算
((a=1+1))
echo $a # 2