前言


  Greenplum 作为OLAP 系统,通过在多个服务器或主机逐渐分配负载来存储和处理大规模业务数据。组成 Greenplum 数据库集群中的每一个计算节点是由独立的 PostgreSQL 实例构成。节点之间的通过 interconnect 相互通信来流转数据。Greenplum 数据库可以运行在多种 X86 架构的平台上,性能取决于安装平台的硬件。由于数据库数据分布在每一个 PostgreSQL 实例中,因此,单个 PostgreSQL 实例的配置性能会影响整个集群的性能。

为什么要构建该脚本

  考虑到某些环境中的服务器配置可能采用的是虚拟机,而虚拟机的硬件由于虚拟化可能被多个其他系统中的环境共享,因此,尽管和物理环境的配置一样,但是性能却不能达到和物理环境的性能,因此,在恢复过程中,可能会碰到这样或那样的问题,所以对于一个可备份恢复的系统来说,如何将备份的数据恢复到整个集群中非常重要。当然,除了恢复数据以外, Greenplum 本身也提供数据同步工具,但是类似的这种工具需要不同集群中间的网络能够通信,否则,只能进行物理恢复的方式来将不同平台或者同平台数据库中的数据恢复到目标服务器上。

备份脚本设计

    备份通过采用 gp_dump 命令来进行备份数据,尽管 gp_dump 已经在当前的所有版本中被丢弃,由 gpcrondump 来代替,而 gpcrondump 实际上是对 gp_dump 命令的封装重构,为了保证4.x 版本以前的兼容性,所以该命令依旧被保留。同时,gpbackup 和 gprestore 也是用来备份和恢复数据的工具,但是仅仅使用于非开发 5.0 以上的版本。

gp_dump 如果对于数据备份到一个文件中,那么会面临两个问题,一是恢复时间长,另一个是如果在恢复期间出现问题,那么意味着需要重新恢复,浪费时间。那么采用 schema 备份的就可以处理该问题。

当然,可能有同学会问, gp_dump 本身可以来备份 schema,写一个简单的备份脚本不就行了吗?答案却是如此,但是需要考略到一个问题,如果经过多次备份,那么恢复的时间戳需要独立去寻找,那么这个对于我们来说,就不是很方便了,而通过脚本,只需要在时间戳目录下找到指定的备份日期,就可以实现对任意时间段备份的数据进行恢复。而此脚本正是通过时间戳目录中记录的时间戳备份文件来进行备份数据,恢复的时候可以使用该时间戳目录。


 


#!/bin/bash
  ####################################################
  #Description: Backup schema for specifying database#
  #Author:sungsasong                                 #
  #Purpose:Backup database                           #
  #Version: 1.0                                      #
  #Date:2021-12-08                                   #
  ####################################################

  #Defining relative directory

  #Current Directory 
  CURRENT_DIR=$(cd "$(dirname $0)";pwd)

  #Top Level Directory
  TOP_DIR=$(cd ${CURRENT_DIR}/..;pwd)

  #Defining relative log files
  LOG=${TOP_DIR}/log/log
  SUCCESS_LOG=${TOP_DIR}/log/success_log
  ERRLOG=${TOP_DIR}/log/error_log

  >${LOG}
  >${ERRLOG}

  #Loading configuration file
  source ${TOP_DIR}/conf/backup.conf
  source ${TOP_DIR}/lib/funclib

  #Defining init Timestamp
  TS=`date '+%Y%m%d%H%M%S'`

  #Defining timestamp file
  TSFILE=${TOP_DIR}/tsdir/timestamp_${BAKDATE}

  #Defining save timstamp directory
  TSDIR=${TOP_DIR}/tsdir

  #Define Database connection string
  CONNINFO="psql -d ${DATABASE} -U ${USERNAME} -p ${DBPORT} -Atq -c"


  check_dir_valid()
  {
      if [ ! -d ${TSDIR} ];then
          print_success_log "The ${TSDIR} will be created"
          mkdir -p ${TSDIR}
      else 
          print_log "The directory has been exists !"
      fi
  }


  #Defining fetch schema sql
  FETCH_SCHEMA_SQL="
  SELECT nspname
  FROM pg_catalog.pg_namespace
  WHERE nspname !~ '^pg|gp_toolkit|information_schema' "

  #Fetching schema from database
  SCHEMALIST=`${CONNINFO} "${FETCH_SCHEMA_SQL}"`


  function backup_task()
  {
      for sname in ${SCHEMALIST};do
          TS=`date '+%Y%m%d%H%M%S'`
          #The file will be used to save timestamp and schema name when we start this scripts
          echo "${TS} ${sname}" >>${TSFILE}
          gp_dump --gp-c --gp-d=${BACKUPDIR} --gp-k=${TS} --gp-r=${REPORTDIR} -n ${sname} ${DATABASE} 1>>${SUCCESS_LOG} 2>&1
      done
      ERROR=$(grep -i -c -E 'ERROR' ${SUCCESS_LOG})
      if [ ${ERROR} -ge 1 ];then
          print_error_log "Backup data failed,please check error info  from ${SUCCESS_LOG}"
          exit 88
      fi     
  }

  print_log ">>>>>>>>>>>>>>>>>>>>>>>>Starting backup"

  check_dir_valid

  print_success_log ">>>>>>>>>>>>>>>>>>>>>>>>Schema `echo ${SCHEMALIST}` will be dump"

  backup_task

  print_success_log ">>>>>>>>>>>>>>>>>>>>>>>>Finished backup,Please checking the relative directory"

恢复脚本

默认恢复脚本使用最新的一个备份文件用来恢复数据。


#!/bin/bash
  ####################################################
  #Description: Restoring schema for specifying database#
  #Author:sungsasong                                 #
  #Purpose:Restoring data                            #
  #Version: 1.0                                      #
  #Date:2021-12-08                                   #
  ####################################################

  #Defining relative directory

  #Current Directory 
  CURRENT_DIR=$(cd "$(dirname $0)";pwd)

  #Top Level Directory
  TOP_DIR=$(cd ${CURRENT_DIR}/..;pwd)

  #Define Database connection string
  CONNINFO="psql -d ${DATABASE} -U ${USERNAME} -p ${DBPORT} -Atq -c"

  #Defining relative log files
  RESTORELOG=${TOP_DIR}/log/restore_log
  RESTOREERRLOG=${TOP_DIR}/log/restore_error_log
  TSDIR=${TOP_DIR}/tsdir
  >${RESTORELOG}
  >${RESTOREERRLOG}
  #Loading configuration file
  source ${TOP_DIR}/conf/backup.conf
  source ${TOP_DIR}/lib/funclib

  #Getting restore timestamp
  LASTESTFILE=`ls -rth ${TSDIR}/ | tail -1`

  #Loading restore timestamp and schema
  RESTORETS=`cat ${TSDIR}/${LASTESTFILE} | awk '{print $1}'`
  RESTORESCHEMA=(`cat ${TSDIR}/${LASTESTFILE} | awk '{print $2}'`)

  #Restoring data for every schema

  function restore_data()
  {
      print_success_log ">>>>>>Beginning restore data ^V^"
      while read line ;do
          fetch_schema=$(echo ${line} | awk '{print $2}')
          fetch_ts=$(echo ${line} | awk '{print $1}')
          print_log " >>>>>>${fetch_schema} schema will be restored,timestamp is:${fetch_ts}"
          gp_restore -h ${HOST} -U ${USERNAME} -d ${DATABASE} -p ${DBPORT} --gp-c --gp-d=${BACKUPDIR} --gp-k=${fetch_ts} --gp-r=${REPORTDIR}  1>>${RESTORELOG} 2>&1
          ERROR=$(grep -i -c -E 'ERROR' ${RESTORELOG})
          if [ ${ERROR} -ge 1 ];then
              print_error_log "Restoring data failed,please check error info  from ${RESTORLOG}"
              exit 88
          fi
      done<${TSDIR}/${LASTESTFILE}
      print_success_log ">>>>>>Restoring data finished ^_^"
  }

  restore_data

结语

以上通过执行两个脚本可以实现按照 schema 来备份数据,同时也可以通过schema 恢复最新一次备份的数据,供大家参考。