@@ -17,6 +17,9 @@ ASYNC_WAIT_DB_MAX=${ASYNC_WAIT_DB_MAX:-10}
1717DUMP_PV=${DUMP_PV:- 6m}
1818DUMP_WAIT_SECONDS=${DUMP_WAIT_SECONDS:- 0.6}
1919
20+ # MySQL数据目录,用于加速判断表文件是否修改
21+ MYSQL_DATA_DIR=${MYSQL_DATA_DIR:- }
22+
2023RUN_LIMIT_START=${RUN_LIMIT_START} ;
2124RUN_LIMIT_START_MYSQLDUMP=${RUN_LIMIT_START_MYSQLDUMP} ;
2225if [[ -n " $CPUQUOTA " ]]; then
@@ -230,99 +233,114 @@ for ((i = 0; i < num_databases; i++)); do
230233 fi
231234 echo $db >> /tmp/databases_count.log;
232235
233-
234- {
235- echo " Dumping database: $db "
236- # 空文件的md5=d41d8cd98f00b204e9800998ecf8427e
237- command=$( cat << BASH
236+ # 先通过SSH获取表列表
237+ echo " 获取数据库 $db 的表列表..."
238+ tables=$( echo " DB_PASS=\" ${DB_PASS} \" ;mysql --user=\" ${DB_USER} \" --port=\" ${DB_PORT} \" --password=\"\$ {DB_PASS}\" --host=\" ${DB_HOST} \" -N -e \" SHOW TABLES;\" $db 2>/dev/null" | eval " $sshRun 'bash -s'" | tr -d " | " | grep -v -e ' ^$' )
239+ echo " 获取到表列表: $tables "
240+
241+ # 转为数组
242+ tables_arr=();
243+ for table in $tables ; do
244+ tables_arr+=($table )
245+ done
246+ num_tables=${# tables_arr[@]}
247+ echo " 数据库 $db 表数量: $num_tables "
248+
249+ echo $db >> /tmp/databases_count.run.log;
250+
251+ # 本地循环每个表,并发处理
252+ for (( t = 0 ; t < num_tables; t++ )) ; do
253+ table=${tables_arr[$t]}
254+
255+ # 并发控制:等待当前并发数小于最大值
256+ while true ; do
257+ current_jobs=$( pgrep -f " mysqldump" | wc -l)
258+ current_jobs=$(( $current_jobs + 1 ))
259+ if [[ " $current_jobs " -lt " $ASYNC_WAIT_MAX " ]]; then
260+ break
261+ fi
262+ echo " $( date " +%Y-%m-%d %H:%M:%S" ) --等待并发槽位 $db .$table 当前jobs=$current_jobs ASYNC_WAIT_MAX=$ASYNC_WAIT_MAX "
263+ sleep 1
264+ done
265+
266+ {
267+ # 单个表的SSH判断脚本:同时检查修改时间和MD5
268+ table_command=$( cat << BASH
238269DB_PASS="${DB_PASS} ";
239- echo '开始运行mysqldump $db ';
270+ MYSQL_DATA_DIR="${MYSQL_DATA_DIR} ";
271+ table="${table} ";
240272mkdir -p /tmp/dump-import-ssh-temp/$db /;
241- lastTable='';
242- $RUN_LIMIT_START_MYSQLDUMP mysqldump --no-tablespaces --log-error=/tmp/dump-import-ssh-temp/mysql_error_log_dir/$db .log --no-create-info --skip-comments --user="${DB_USER} " --port="${DB_PORT} " --password="\$ {DB_PASS}" --host="${DB_HOST} " $DUMP_ARGS $db | pv -L $DUMP_PV |grep -e '^INSERT INTO' | while read -r line; do
243- table=\$ (echo "\$ line" | awk -F '\` ' '{print \$ 2}');
244- echo -n "\$ line" | md5sum | awk -v table="\$ table" '{print table, \$ 1}' >> /tmp/dump-import-ssh-temp/$db /\$ table.md5;
245- if [[ -z "\$ lastTable" ]];then
246- lastTable=\$ table;
247- echo \$ lastTable > /tmp/dump-import-ssh-temp/$db .lastTable.log;
248- fi;
249- if [[ "\$ lastTable" != "\$ table" ]];then
250- if [[ "\$ (cat /tmp/dump-import-ssh-temp/$db /\$ lastTable.md5 | md5sum)" != "\$ (cat /tmp/dump-import-ssh-diff/$db /\$ lastTable.md5 | md5sum)" ]];then
251- echo '有差异表名 '\$ lastTable;
273+ mkdir -p /tmp/dump-import-ssh-temp/mtime/$db /;
274+
275+ mtime_changed=0;
276+
277+ # 检查表文件修改时间是否改变(如果MYSQL_DATA_DIR存在)
278+ if [[ -n "\$ MYSQL_DATA_DIR" && -d "\$ MYSQL_DATA_DIR" ]]; then
279+ db_dir="\$ {MYSQL_DATA_DIR}/$db ";
280+ if [[ -d "\$ db_dir" ]]; then
281+ mtime_file="";
282+ if [[ -f "\$ {db_dir}/\$ {table}.ibd" ]]; then
283+ mtime_file="\$ {db_dir}/\$ {table}.ibd";
284+ elif [[ -f "\$ {db_dir}/\$ {table}.MYD" ]]; then
285+ mtime_file="\$ {db_dir}/\$ {table}.MYD";
286+ fi
287+
288+ if [[ -n "\$ mtime_file" ]]; then
289+ current_mtime=\$ (stat -c %Y "\$ mtime_file" 2>/dev/null || stat -f %m "\$ mtime_file" 2>/dev/null);
290+ stored_mtime=\$ (cat /tmp/dump-import-ssh-diff/mtime/$db /\$ {table}.mtime 2>/dev/null || echo 0);
291+ echo "\$ current_mtime" > /tmp/dump-import-ssh-temp/mtime/$db /\$ {table}.mtime;
292+
293+ if [[ "\$ current_mtime" != "\$ stored_mtime" ]]; then
294+ mtime_changed=1;
295+ fi
252296 fi
253- lastTable=\$ table;
254- echo \$ lastTable > /tmp/dump-import-ssh-temp/$db .lastTable.log;
255- fi;
256- done;
257-
258- lastTable=\$ (cat /tmp/dump-import-ssh-temp/$db .lastTable.log);
259- if [[ -n "\$ lastTable" ]];then
260- if [[ -f "/tmp/dump-import-ssh-diff/$db /\$ lastTable.md5" ]];then
261- if [[ "\$ (cat /tmp/dump-import-ssh-temp/$db /\$ lastTable.md5 | md5sum)" != "\$ (cat /tmp/dump-import-ssh-diff/$db /\$ lastTable.md5 | md5sum)" ]];then
262- echo '有差异表名 '\$ lastTable;
263- fi;
264- else
265- echo '有差异表名 '\$ lastTable;
266297 fi
267298fi
268299
269- echo '结束运行mysqldump $db ';
300+ # 导出表并计算MD5
301+ $RUN_LIMIT_START_MYSQLDUMP mysqldump --no-tablespaces --log-error=/tmp/dump-import-ssh-temp/mysql_error_log_dir/$db -\$ {table}.log --no-create-info --skip-comments --user="${DB_USER} " --port="${DB_PORT} " --password="\$ {DB_PASS}" --host="${DB_HOST} " $DUMP_ARGS $db \$ table 2>/dev/null | grep -e '^INSERT INTO' | md5sum | awk -v table="\$ table" '{print table, \$ 1}' > /tmp/dump-import-ssh-temp/$db /\$ table.md5;
270302
271- BASH
272- )
273-
274- # printf "%s\n" "$command"
275-
276- # todo 还要管道导出表
277- # ionice -c3
278- time (
279- # printf "%s\n" "$command" | eval "$sshRun 'exec -a \"导出数据库-$db\" bash -s 2> /dev/null'" | while read -r line; do
280- # printf "%s\n" "$command" | eval "$sshRun 'ionice -c3 bash -s 2> /dev/null'" | while read -r line; do
281- printf " %s\n" " $command " | eval " $sshRun '$RUN_LIMIT_START bash -c \" exec -a 导出数据库-$db bash -s\" 2> /dev/null'" | while read -r line; do
282- echo $db .$line ;
283- if [[ $line = " 开始运行mysqldump $db " ]]; then
284- echo $db >> /tmp/databases_count.run.log;
285- continue ;
286- fi
287- if [[ $line = " 结束运行mysqldump $db " ]]; then
288- echo $db >> /tmp/databases_count.end.log;
289- continue ;
290- fi
291-
292- table=$( echo $line | awk ' {print $2}' )
293- current_jobs=$( pgrep -f " mysqldump" | wc -l)
294- current_jobs=$(( $current_jobs + 1 ))
295-
296- if [[ " $current_jobs " -lt " $ASYNC_WAIT_MAX " ]]; then
297- {
298- echo " 进程数小于最大等待数,异步导入--$db .$table " ;
299- time (mysqldump --no-tablespaces --user=" ${DB_USER} " --port=" ${DB_TABLE_PORT} " --password=" ${DB_PASS} " --host=" ${DB_TABLE_HOST} " $DUMP_ARGS $db " $table " | pv -L $DUMP_PV | mysql --user=" ${IMPORT_DB_USER} " --password=" ${IMPORT_DB_PASS} " --host=" ${IMPORT_DB_HOST} " $IMPORT_ARGS " $db " )
300- echo $( date " +%Y-%m-%d %H:%M:%S" ) " --导入结束 $db .$table " ;
301- } &
302- sleep $DUMP_WAIT_SECONDS ;
303- else
304- echo " 进程数大于最大等待数,同步等待导入-$db .$table " ;
305- # sleep 20;
306- time (mysqldump --no-tablespaces --user=" ${DB_USER} " --port=" ${DB_TABLE_PORT} " --password=" ${DB_PASS} " --host=" ${DB_TABLE_HOST} " $DUMP_ARGS $db " $table " | pv -L $DUMP_PV | mysql --user=" ${IMPORT_DB_USER} " --password=" ${IMPORT_DB_PASS} " --host=" ${IMPORT_DB_HOST} " $IMPORT_ARGS " $db " )
307- echo $( date " +%Y-%m-%d %H:%M:%S" ) " --导入结束 $db .$table " ;
308- fi
309-
310- done ;
311- )
312- # time (eval "$sshRun 'bash -s'" < $command)
313-
314-
315- sed -i " /$db /d" /tmp/databases_count.log;
316- # sed -i "/$db/d" /tmp/databases_count.run.log;
317-
318-
319- echo $( date " +%Y-%m-%d %H:%M:%S" ) " --异步导出库--结束--$db ----continueBool=$continueBool --------------------------------------" ;
303+ # 判断是否有差异
304+ temp_md5=\$ (cat /tmp/dump-import-ssh-temp/$db /\$ table.md5);
320305
306+ if [[ -f "/tmp/dump-import-ssh-diff/$db /\$ table.md5" ]]; then
307+ diff_md5=\$ (cat /tmp/dump-import-ssh-diff/$db /\$ table.md5);
308+ if [[ "\$ temp_md5" != "\$ diff_md5" ]]; then
309+ echo "diff-sync 有差异表名 \$ table";
310+ elif [[ "\$ mtime_changed" == "1" ]]; then
311+ echo "diff-sync 文件修改时间改变 \$ table";
312+ fi
313+ else
314+ echo "diff-sync 新表 \$ table";
315+ fi
321316
322- #
323- # }
324- } &
325- sleep 2;
317+ BASH
318+ )
319+
320+ # 执行SSH并处理输出
321+ printf " %s\n" " $table_command " | eval " $sshRun '$RUN_LIMIT_START bash -c \" exec -a 导出表-$db .$table bash -s\" 2> /dev/null'" | while read -r line; do
322+ echo " 差异判断输出: " . $db .$line ;
323+
324+ # 只处理有差异的表
325+ if [[ $line == " diff-sync " * ]]; then
326+ import_table=$( echo $line | awk ' {print $3}' )
327+
328+ echo " 进程数小于最大等待数,异步导入--$db .$import_table " ;
329+ time (mysqldump --no-tablespaces --user=" ${DB_USER} " --port=" ${DB_TABLE_PORT} " --password=" ${DB_PASS} " --host=" ${DB_TABLE_HOST} " $DUMP_ARGS $db " $import_table " | pv -L $DUMP_PV | mysql --user=" ${IMPORT_DB_USER} " --password=" ${IMPORT_DB_PASS} " --host=" ${IMPORT_DB_HOST} " $IMPORT_ARGS " $db " ) || echo " 导入失败: $db .$import_table "
330+ echo $( date " +%Y-%m-%d %H:%M:%S" ) " --导入结束 $db .$import_table " ;
331+ fi
332+ done
333+ } &
334+ sleep $DUMP_WAIT_SECONDS ;
335+ done
336+
337+ # 等待当前库的所有表处理完成
338+ wait
339+
340+ echo $db >> /tmp/databases_count.end.log;
341+ sed -i " /$db /d" /tmp/databases_count.log;
342+
343+ echo $( date " +%Y-%m-%d %H:%M:%S" ) " --异步导出库--结束--$db --------------------------------------" ;
326344# exit;
327345 fi
328346done
0 commit comments