使用脚本完成随机内容抽样比对
- 在华为云购买一台与源端、目的端都相通的ECS(建议购买CentOS操作系统的ECS)。
图1 购买ECS
要使该ECS和源端目的端数据库都通,需要在源端和目的端配置安全组。
- 在第一步购买的ECS上安装sqlcmd
安装参考:在 Linux 上安装 sqlcmd 和 bcp SQL Server 命令行工具
安装步骤如下:- 下载Microsoft Red Hat存储库配置文件
curl https://packages.microsoft.com/config/rhel/8prod.repo | sudo tee /etc/yum.repos.d/mssql-release.repo

- 如果安装了早期版本的mssql-tools,请删除所有旧的unixODBC包
sudo yum remove mssql-tools unixODBC-utf16 unixODBC-utf16-devel

- 运行以下命令,以使用unixODBC开发人员包安装mssql-tools18
sudo yum install -y mssql-tools18 unixODBC-devel

若要将mssql-tools更新至最新版本,请运行以下命令:
sudo yum check-update
sudo yum update mssql-tools18

- 向bash shell中的PATH环境变量添加/opt/mssql-tools18/bin/
若要使sqlcmd和bcp能从登录会话的 bash shell 进行访问,请使用下列命令修改~/.bash_profile 文件中的 PATH
echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bash_profile
source ~/.bash_profile

- 下载Microsoft Red Hat存储库配置文件
- 将校验脚本、源端/目的端的配置信息文件、校验表配置文件导入ECS。
ECS check脚本如下:
#!/bin/bash # 日志函数 log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" } # 错误处理函数 error_exit() { log "错误: $1" exit 1 } # 检查参数 if [ "$#" -ne 2 ]; then error_exit "用法: $0 <配置文件路径> <表信息文件路径>" fi config_file=$1 table_info_file=$2 # 检查文件是否存在 [ -f "$config_file" ] || error_exit "配置文件 $config_file 不存在" [ -f "$table_info_file" ] || error_exit "表信息文件 $table_info_file 不存在" # 读取第一个SQL Server连接信息 server1=$(awk -F'=' '/^server1/ {print $2}' "$config_file" | tr -d ' ') user1=$(awk -F'=' '/^user1/ {print $2}' "$config_file" | tr -d ' ') password1=$(awk -F'=' '/^password1/ {print $2}' "$config_file" | tr -d ' ') database1=$(awk -F'=' '/^database1/ {print $2}' "$config_file" | tr -d ' ') # 读取第二个SQL Server连接信息 server2=$(awk -F'=' '/^server2/ {print $2}' "$config_file" | tr -d ' ') user2=$(awk -F'=' '/^user2/ {print $2}' "$config_file" | tr -d ' ') password2=$(awk -F'=' '/^password2/ {print $2}' "$config_file" | tr -d ' ') database2=$(awk -F'=' '/^database2/ {print $2}' "$config_file" | tr -d ' ') # 检查连接信息是否完整 if [ -z "$server1" ] || [ -z "$user1" ] || [ -z "$password1" ] || [ -z "$database1" ] || [ -z "$server2" ] || [ -z "$user2" ] || [ -z "$password2" ] || [ -z "$database2" ]; then error_exit "配置文件缺少必要的连接信息" fi # 检查sqlcmd是否可用 command -v sqlcmd >/dev/null 2>&1 || error_exit "sqlcmd命令未找到,请确保SQL Server命令行工具已安装" # 处理表信息文件 total_tables=0 success_tables=0 failed_tables=0 for line in `cat $table_info_file` do # 去除空格 table1=$(echo $line | awk -F',' '{print $1}' | tr -d ' ') table2=$(echo $line | awk -F',' '{print $2}' | tr -d ' ') pk_column=$(echo $line | awk -F',' '{print $3}' | tr -d ' ') gt_value=$(echo $line | awk -F',' '{print $4}' | tr -d ' ') lt_value=$(echo $line | awk -F',' '{print $5}' | tr -d ' ') ((total_tables++)) log "开始比较表 #$total_tables: $table1 (服务器1) 和 $table2 (服务器2)" # 构建WHERE子句 where_clause="" if [ -n "$pk_column" ]; then conditions=() if [ -n "$gt_value" ]; then conditions+=("$pk_column > $gt_value") fi if [ -n "$lt_value" ]; then conditions+=("$pk_column < $lt_value") fi if [ ${#conditions[@]} -gt 0 ]; then where_clause="WHERE $(printf '%s AND ' "${conditions[@]}" | sed 's/ AND $//')" fi fi # 获取表1的checksum sql1="SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) AS checksum FROM $table1 $where_clause" checksum1=$(sqlcmd -S "$server1" -U "$user1" -P "$password1" -d "$database1" -h -1 -Q "SET NOCOUNT ON; $sql1" 2>/dev/null | tr -d ' ' | tr -d '\r\n') if [ $? -ne 0 ]; then log "警告: 无法获取表 $table1 的checksum,跳过此表" ((failed_tables++)) echo "----------------------------------------" continue fi # 获取表2的checksum sql2="SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) AS checksum FROM $table2 $where_clause" checksum2=$(sqlcmd -S "$server2" -U "$user2" -P "$password2" -d "$database2" -h -1 -Q "SET NOCOUNT ON; $sql2" 2>/dev/null | tr -d ' ' | tr -d '\r\n') if [ $? -ne 0 ]; then log "警告: 无法获取表 $table2 的checksum,跳过此表" ((failed_tables++)) echo "----------------------------------------" continue fi # 比较checksum if [ "$checksum1" == "$checksum2" ]; then log "结果: 表内容一致 (Checksum: $checksum1)" ((success_tables++)) else log "结果: 表内容不一致" log "表 $table1 (服务器1) Checksum: $checksum1" log "表 $table2 (服务器2) Checksum: $checksum2" ((failed_tables++)) fi echo "----------------------------------------" done log "比较完成" log "总计表数: $total_tables" log "一致表数: $success_tables" log "不一致表数: $failed_tables" if [ "$failed_tables" -gt 0 ]; then exit 1 else exit 0 fi- 源/目标信息配置文件
server1=testdbvm.database.windows.net
user1=azuser
password1=XXXXX
database1=smsa_mig
server2= 123.60.216.120
user2=rdsuser
password2=XXXXXXX
database2= smsa_mig

server user password与database用户需要按照实际需要修改。
- 同步对比表配置文件
vim table_info.txt
如第一行校验dbo.check1全表,不指定范围
如第二行校验dbo.check2,根据id>11 and id < 13的范围校验
dbo.check1,dbo.check1
dbo.check2,dbo.check2,id,11,13


- 源/目标信息配置文件
- 执行校验文件脚本。
sh chech.sh config.cfg table_info.txt





