数据库历史数据年度备份
1、文件说明
matomo_backup.sql 备份库表结构脚本(这个根据自己数据结构准备,对于时间命名的表结构就不要加了,只加非时间命名的表结构)
export.sh 数据导出脚本
clean.sh 源数据库历史数据清除脚本
2、需求与思路
需求
对于一些统计功能,我们需要对历史数据进行数据备份,以降低统计查询的压力,备份方式为按年度备份,每年度备份的数据都单独创建一个数据库,如下:
思路
整体业务通过shell脚本执行数据库操作,思路如下:
- 先导出数据备份,再清除对应的历史数据(好像是废话)
- 通过mysqldump命令导出源数据库结构及数据,生成脚本matomo.sql
- 切换到目标数据库
- 创建备份库,通过source命令执行matomo_backup.sql备份库脚本
- 创建数据源临时库,通过source命令执行第二步生成的源数据库结构及数据
- 非时间命名的表同步,直接使用create_date作为条件insert
- 时间命名的表同步,切换到备份库,先创建对应导出年份的时间表,然后全表导入源库数据(这个用存储过程来实现,因为涉及到了动态表,采用游标的形式遍历)
- 删除存储过程
- 切换回数据源临时库,删除临时库
- 删除mysqldump命令生成的源数据库结构及数据脚本matomo.sql
- 删除已备份数据
- 非时间命名的表直接通过create_date作为条件delete
- 时间命名的表直接drop掉(同理,使用存储过程实现)
3、操作
数据导出备份
- 将matomo_backup.sql放export.sh同级目录
- 根据实际情况修改export.sh中源数据库和备份数据库服务连接信息
- export.sh 执行,传参:$1为要导出数据年份,$2为需要创建备份数据库名称
执行效果如下表示执行成功:
历史数据清除
-
确保数据已经导出备份!!!!
-
根据实际情况修改clean.sh中源数据库服务连接信息
-
clean.sh 执行,传参:$1为要清除数据年份
执行效果如下表示执行成功:
4、脚本附件
export.sh
#!/bin/bash
echo "Start Export Matomo Data..."
#$1为要导出数据年份,$2为需要创建备份数据库名称(不需要手动创建,matomo_backup.sql放export.sh同级目录)
echo "导出$1年的数据到备份数据库$2...";
#mysqldump导出源数据库结构及数据,具体数据库连接信息请自行修改
mysqldump -h192.168.137.128 -P3306 -uroot -proot matomo --column-statistics=0 > ./matomo.sql;
#切换到目标数据库服务器,具体数据库连接信息请自行修改
mysql -h192.168.137.128 -P3307 -uroot -proot -e"
#创建备份库
CREATE DATABASE IF NOT EXISTS $2 DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_bin;
use $2;
source ./matomo_backup.sql;
#创建数据源临时库
CREATE DATABASE IF NOT EXISTS matomo DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_bin;
use matomo;
set names utf8;
source ./matomo.sql;
#导入需要备份年份的数据
INSERT IGNORE INTO $2.matomo_user_token_auth SELECT * FROM matomo_user_token_auth where DATE_FORMAT(last_used,'%Y') = $1;
INSERT IGNORE INTO $2.new_user_model SELECT * FROM new_user_model where DATE_FORMAT(query_date,'%Y') = $1;
INSERT IGNORE INTO $2.visit_statics_model SELECT * FROM visit_statics_model where DATE_FORMAT(query_date,'%Y') = $1;
...
#切换到备份库,通过存储过程、游标创建备份库中不存在的数据表及数据插入
use $2;
#处理matomo_archive_blob_*;matomo_archive_numeric_*数据表集合
DROP PROCEDURE IF EXISTS export_list;
delimiter $
CREATE PROCEDURE export_list()
BEGIN
#遍历结束标志
DECLARE var_flag INT DEFAULT 0;
#遍历表名变量
DECLARE var_table_name VARCHAR(100);
#表集合
DECLARE table_name_list CURSOR FOR
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'matomo' AND table_type = 'base table'
AND
(
table_name like 'matomo_archive_blob_%' AND SUBSTR(table_name,21,4) = $1
OR
table_name like 'matomo_archive_numeric_%' AND SUBSTR(table_name,24,4) = $1
) ;
#将结束标志绑定到游标
DECLARE CONTINUE HANDLER FOR NOT FOUND SET var_flag = 1;
#打开游标
OPEN table_name_list;
FETCH table_name_list INTO var_table_name;
WHILE var_flag !=1 DO
#判断表类型
IF FIND_IN_SET('matomo_archive_blob_',var_table_name)
THEN
#需要先判断该表在备份库是否存在,不存在需要先创建,然后再插入数据
SET @createTableStr = CONCAT('CREATE TABLE IF NOT EXISTS ',var_table_name,'(
idarchive int(10) UNSIGNED NOT NULL,
name varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
idsite int(10) UNSIGNED NULL DEFAULT NULL,
date1 date NULL DEFAULT NULL,
date2 date NULL DEFAULT NULL,
period tinyint(3) UNSIGNED NULL DEFAULT NULL,
ts_archived datetime NULL DEFAULT NULL,
value mediumblob NULL,
PRIMARY KEY (idarchive, name) USING BTREE,
INDEX index_period_archived(period, ts_archived) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = COMPACT');
ELSE
#先判断该表在备份库是否存在,不存在需要先创建,然后再插入数据
SET @createTableStr = CONCAT('CREATE TABLE IF NOT EXISTS ',var_table_name,'(
idarchive int(10) UNSIGNED NOT NULL,
name varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
idsite int(10) UNSIGNED NULL DEFAULT NULL,
date1 date NULL DEFAULT NULL,
date2 date NULL DEFAULT NULL,
period tinyint(3) UNSIGNED NULL DEFAULT NULL,
ts_archived datetime NULL DEFAULT NULL,
value mediumblob NULL,
PRIMARY KEY (idarchive, name) USING BTREE,
INDEX index_period_archived(period, ts_archived) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = COMPACT');
END IF;
PREPARE stmt FROM @createTableStr;
EXECUTE stmt;
#对matomo_archive_blob_*;matomo_archive_numeric_*数据表数据进行备份
SET @insertStr = CONCAT('INSERT IGNORE INTO ',var_table_name,' SELECT * FROM matomo.',var_table_name);
PREPARE stmt FROM @insertStr;
EXECUTE stmt;
FETCH table_name_list INTO var_table_name;
END WHILE;
CLOSE table_name_list;
END;
#执行存储过程
CALL export_list();
#删除存储过程
DROP PROCEDURE export_list;
#切换回matomo临时库
use matomo;
#删除临时源库
DROP DATABASE matomo;
commit;"
#remove dump file
rm ./matomo.sql;
echo "Export Data Successful."
exit;
clean.sh
#!/bin/bash
echo "Start Clean Matomo Data..."
echo "开始清除已备份的$1年数据,请确保已执行export.sh进行备份...";
mysql -h192.168.137.128 -P3306 -uroot -proot -e"
use matomo;
#删除已备份年份的历史数据
DELETE FROM matomo_user_token_auth where DATE_FORMAT(last_used,'%Y') = $1;
DELETE FROM new_user_model where DATE_FORMAT(query_date,'%Y') = $1;
DELETE FROM visit_statics_model where DATE_FORMAT(query_date,'%Y') = $1;
......
#删除matomo_archive_blob_*;matomo_archive_numeric_*已备份年份的数据表
DROP PROCEDURE IF EXISTS drop_table_list;
delimiter $
CREATE PROCEDURE drop_table_list()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 12 DO
IF i < 10
THEN
SET @dropTableStr = CONCAT('DROP table IF EXISTS matomo_archive_blob_$1_0' , i , ',' , 'matomo_archive_numeric_$1_0' , i);
ELSE
SET @dropTableStr = CONCAT('DROP table IF EXISTS matomo_archive_blob_$1_' , i , ',' , 'matomo_archive_numeric_$1_' , i);
END IF;
PREPARE stmt FROM @dropTableStr;
EXECUTE stmt;
SET i = i+1;
END WHILE;
END;
#执行存储过程
CALL drop_table_list();
#删除存储过程
DROP PROCEDURE drop_table_list;
commit;"
echo "Clean Data Successful."
exit;