背景:有时候我们需要将一些千万级甚至亿级的数据表进行数据转移,移动到分表当中。如果直接通过SELECT和INSERT结合会非常缓慢,本人用的是SELECT INTO OUTFILE和LOAD DATA INFILE结合。不过一开始我是每次查询一个月数据,直接导入到每月的分表当中,但是发现LOAD DATA语句是一个完整的事务,所以开销巨大,而且数据量巨大的情况下,很容易事务中断导致一个很长时间的锁。后来我想了个办法,将事务按天切分,如果一个月有30天,那么我让它顺序执行30个小事务,每个大约是几百万的数据,每次休眠个几秒钟,这样开销会小很多,最后数据可以成功导入到分表。
代码:
#!/bin/bash
# description:Mysql转移大数据脚本(按月分表专用)
# author:ZZJ
# time:2018-12-27
USER=root
PASSWORD=123456
HOST=127.0.0.1
MYSQL="/usr/local/percona/bin/mysql -u$USER -h$HOST -p$PASSWORD"
DATABASE="origin_platform"
TABLE="tb_sdk_role_login"
INDEX="FORCE INDEX(UK_G_S_U_E)"
YEAR="2018"
MONTH="08"
FIRST_DATE=$YEAR"-"$MONTH"-01"
DAY_NUM=`date -d "$FIRST_DATE +1 month -1 days" +%d`
CHILD_TABLE=$TABLE"_"$YEAR$MONTH
FILE_PATH="/backup/dao_date/"
echo "$DATABASE.$CHILD_TABLE Begin:"
#按月创建分表
CREATE_SQL="CREATE TABLE IF NOT EXISTS $DATABASE.$CHILD_TABLE LIKE $DATABASE.$TABLE"
#按日导出导入数据
for((DAY=1;DAY<=$DAY_NUM;DAY++));
do
if [[ $DAY -lt 10 ]]; then
DATE=$YEAR"-"$MONTH"-0"$DAY
FILE_NAME="'"$FILE_PATH$DATABASE.$TABLE"_"$YEAR$MONTH"0"$DAY".sql'"
else
DATE=$YEAR"-"$MONTH"-"$DAY
FILE_NAME="'"$FILE_PATH$DATABASE.$TABLE"_"$YEAR$MONTH$DAY".sql'"
fi
TIME_BEGIN=$DATE" 00:00:00"
TIME_END=$DATE" 23:59:59"
OUTFILE=" INTO OUTFILE $FILE_NAME"
#导出数据
EXPORT_SQL='SELECT * FROM '"$DATABASE.$TABLE $INDEX WHERE TIME BETWEEN '$TIME_BEGIN' AND '$TIME_END' $OUTFILE"
RESULT=`$MYSQL -e "$EXPORT_SQL"`
#导入数据
LOAD_SQL="LOAD DATA INFILE $FILE_NAME INTO TABLE $DATABASE.$CHILD_TABLE;"
RESULT=`$MYSQL -e "$LOAD_SQL"`
echo "$DATE Completed."
sleep 3s
done
echo "All Done."
网友评论