---
url: /v6.2/engine-upgrade.md
---
# Engine 升级 (GP5 -> GP6)

本文讲述如何将历史版本上 GP5 升级到 GP6 。

## 升级前环境准备

升级前请确保环境满足以下要求：

* 升级过程中引擎所有机器，包含 Master 和 Segment。每台机器都要预留当前节点所占数据容量的**2倍**空闲空间，备份原有数据需要1倍空间，另1倍空间用于 GP6存储。使用下面命令查看当前节点数据大小。
  ```shell
  HENGSHI_HOME=/opt/hengshi
  du ${HENGSHI_HOME}/engine-cluster -sch
  ```
* 升级时 Segment 的数量需要与升级前的节点数相同。
* 由于升级过程会依赖 SSH，所以最好配置 SSH 免密登录。

## 引擎升级流程

以下操作在引擎的 Master 机器执行，在 gpbackup 阶段，所有 Segment 会并行将数据写入其所在机器的 backup-dir 参数指定的本机目录。在 gprestore 也会使所有 Segment 在其所在机器上找备份的数据文件进行加载。

### 备份 GP5数据

1. 停掉所有服务，只启动引擎。
   ```shell
   HENGSHI_HOME=/opt/hengshi
   ${HENGSHI_HOME}/bin/hengshi-sense-bin stop all
   ${HENGSHI_HOME}/bin/hengshi-sense-bin start engine
   ```
2. 创建安装包解压目录，如 hengshi-\[version]。
3. 下载迁移工具。
   ```shell
   cd hengshi-[version]
   wget https://download.hengshi.com/3rd/pivotal_greenplum_backup_restore-1.15.0-1.tar.gz
   ```
4. 更新引擎相关配置。
   ```shell
   HENGSHI_HOME=/opt/hengshi
   cd ${HENGSHI_HOME}
   test -f conf/hengshi-sense-env.sh || cp conf/hengshi-sense-env.sh.sample conf/hengshi-sense-env.sh
   set_kv_config() {
       local config_file="$1"
       local param="$2"
       local val="$3"
       # edit param=val if exist or insert new param=val
       grep -E "^\s*${param}\s*=" "${config_file}" > /dev/null \
                   || sed -i "$ a ${param}=${val}" "${config_file}"
   }
   set_kv_config conf/hengshi-sense-env.sh HS_PG_DB postgres
   set_kv_config conf/hengshi-sense-env.sh HS_PG_USR postgres
   set_kv_config conf/hengshi-sense-env.sh HS_PG_PWD postgres
   set_kv_config conf/hengshi-sense-env.sh HS_ENGINE_DB postgres
   set_kv_config conf/hengshi-sense-env.sh HS_ENGINE_USR postgres
   set_kv_config conf/hengshi-sense-env.sh HS_ENGINE_PWD postgres
   ```
5. 导出 GP5数据，选定存放导出数据目录如: ${HENGSHI_HOME}/gpbackup， 该目录下的空闲空间大小必须大于当前数据大小。

   ```shell
   export HENGSHI_HOME=/opt/hengshi
   cd hengshi-[version]
   tar -xf pivotal_greenplum_backup_restore-1.15.0-1.tar.gz -C ${HENGSHI_HOME}/lib/gpdb/gpdb/ #必须执行，解压到当前的 GP5软链接目录
   bash #launch a new bash
   source ${HENGSHI_HOME}/engine-cluster/export-cluster.sh
   psql postgres -A -t -c "select 'drop view '|| viewname || ' cascade;' from pg_catalog.pg_views where schemaname NOT IN ('pg_catalog', 'information_schema', 'gp_toolkit') order by schemaname, viewname" > drop_views.sql
   cat drop_views.sql
   psql postgres -f drop_views.sql
   psql postgres -c "drop function if exists public.safe_to_number(text)"
   # backup
   gpbackup --dbname postgres --backup-dir ${HENGSHI_HOME}/gpbackup --compression-level 9
   exit #exit new bash
   ```

> \[!TIP] 提示
> 示例中库名为 postgres，操作时根据实际情况指定。如果有多个库，每个库都需要单独备份，并指定不同的`--backup-dir`。
> `--compression-level` 的值是1-9。 值越大， 压缩比例越高， 耗时也越长。自测时发现当 level 为6时，100G 耗时约1h，备份数据的大小将近 30G，该结果仅供参考。
> 命令 gpbackup 的其他参数可以参考[gpbackup](https://gpdb.docs.pivotal.io/backup-restore/1-15/utility_guide/ref/gpbackup.html)。

### 启动 GP6

1. 停掉 GP5，启动 GP6。
   ```shell
   HENGSHI_HOME=/opt/hengshi
   cd hengshi-[version]
   cp -r lib/gpdb-6* ${HENGSHI_HOME}/lib
   cd ${HENGSHI_HOME}
   bin/hengshi-sense-bin stop engine
   mv engine-cluster engine-cluster.gp5.bak
   gpdb_name=$(ls ${HENGSHI_HOME}/lib/gpdb-* -dvr --color=never| head -n 1)
   gpdb_name=${gpdb_name##*/}
   cd ${HENGSHI_HOME}/lib
   rm -f gpdb
   ln -s ${gpdb_name} gpdb
   cd ${HENGSHI_HOME}
   bin/hengshi-sense-bin init engine
   bin/hengshi-sense-bin start engine
   ```

2. GP6启动后，导入引擎数据。

   ```shell
   export HENGSHI_HOME=/opt/hengshi
   cd hengshi-[version]
   tar -xf pivotal_greenplum_backup_restore-1.15.0-1.tar.gz -C ${HENGSHI_HOME}/lib/gpdb/gpdb/ #必须执行,解压到当前的 GP6软链接目录
   bash #launch a new bash
   source ${HENGSHI_HOME}/engine-cluster/export-cluster.sh
   psql postgres -c 'create role dwguest'
   # find all timestamp (14chars)
   find ${HENGSHI_HOME}/gpbackup/SegDataDir-1/backups/ -maxdepth 2 | sort
   # restore with a timestamp
   gprestore --backup-dir ${HENGSHI_HOME}/gpbackup --timestamp xxxxxxxxxxxxxx
   exit #exit new bash
   ```

   **说明:**

   * 如果导入出现问题，需要重新导入，则可以执行下面的步骤，重新初始化并启动。
     ```bash
     cd ${HENGSHI_HOME}
     bin/hengshi-sense-bin stop engine
     rm -rf engine-cluster
     bin/hengshi-sense-bin init engine
     bin/hengshi-sense-bin start engine
     ```
   * 使用该方式导入引擎数据时不会导入全局对象，包括 Tablespaces、Databases、Database-wide configuration parameter settings (GUCs)、Resource group definitions、Resource queue definitions、Roles、GRANT assignments of roles to databases，参考[Parallel Backup with gpbackup and gprestore](https://gpdb.docs.pivotal.io/backup-restore/1-15/admin_guide/managing/backup-gpbackup.html#topic_x3s_lqj_tbb)。因此可能会出现角色或者队列不存在的情况，参考下面的方法进行解决。
     * 指定`--with-globals`选项， 但可能会提示角色或者队列等已经存在等问题， 需要导入前检查并删除或者通过指定`--on-error-continue`的方式忽略， 但选项会忽略所有的错误， 请谨慎使用。
     * 手动创建， 打开 ${HENGSHI_HOME}/gpbackup/SegDataDir-1/backups/YYYYMMDD/YYYYMMDDHHMMSS/gpbackup_YYYYMMDDHHMMSS_metadata.sql 文件， 查看创建了哪些角色、队列等， 然后手动执行， 存在的角色、队列可以忽略创建。如果有角色、队列等有授权操作， 也需执行相应的授权。请仔细检查不要遗漏。
   * 如果提示`safe_to_number`不存在，则手动创建一个。

   ```sql
   CREATE OR REPLACE FUNCTION SAFE_TO_NUMBER(text)
   RETURNS numeric IMMUTABLE STRICT AS
   $$
   BEGIN
     RETURN $1::numeric;
   EXCEPTION WHEN OTHERS THEN
     RETURN NULL;
   END
   $$ LANGUAGE plpgsql;
   ```

   * 如果数据库名不存在， 可以指定`--create-db` 选项自动创建数据库。如果已经存在，则不要指定，否则会报错。
   * 可以指定 `--metadata-only`只导入 meta 数据， 包括建表， 但不包含数据。
   * 可以指定 `--data-only`只导入数据， 不包括建表。
   * 根据自测结果， 在 compression-level 为 6 的情况下， 耗时基本上是备份的 1.5 倍。
   * 命令 gprestore 的相关说明请参考[链接](https://gpdb.docs.pivotal.io/backup-restore/1-15/utility_guide/ref/gprestore.html)。

3. 升级成功后清理数据。
   ```shell
   HENGSHI_HOME=/opt/hengshi
   cd ${HENGSHI_HOME}
   rm -rf engine-cluster.gp5.bak
   rm -rf lib/gpdb-5*
   ```

## 升级失败回滚

当升级过程出现问题时，请按下面指导进行回滚。

1. 停掉所有 HENGSHI SENSE 服务。
   ```shell
   HENGSHI_HOME=/opt/hengshi
   ${HENGSHI_HOME}/bin/hengshi-sense-bin stop all
   ```

2. 删除 GP6数据目录。
   ```shell
   HENGSHI_HOME=/opt/hengshi
   cd ${HENGSHI_HOME}
   test -d engine-cluster.gp5.bak && rm -rf engine-cluster
   ```

3. 恢复 GP5相关引擎数据。
   ```shell
   HENGSHI_HOME=/opt/hengshi
   cd ${HENGSHI_HOME}
   mv engine-cluster.gp5.bak engine-cluster
   gpdb_name=$(ls ${HENGSHI_HOME}/lib/gpdb-5* -dvr --color=never| head -n 1)
   gpdb_name=${gpdb_name##*/}
   rm -f ${HENGSHI_HOME}/lib/gpdb
   cd ${HENGSHI_HOME}/lib
   ln -sf ${gpdb_name} ${HENGSHI_HOME}/lib/gpdb
   ```
