MySQL 表分区和事件调度器

MySQL 表分区实践及操作

MySQL 分区表的备份与恢复策略

针对分区表的备份和恢复,有多种策略可供选择。以下是详细的操作示例方法:

1. 分区级备份(推荐)

备份单个分区

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-- 创建分区备份表(结构相同但不分区)
CREATE TABLE orders_backup_p202312 LIKE orders;
ALTER TABLE orders_backup_p202312 REMOVE PARTITIONING;

-- 拷贝分区数据到备份表
ALTER TABLE orders EXCHANGE PARTITION p202312 
WITH TABLE orders_backup_p202312;

-- 此时数据在备份表中,原分区为空
-- 将数据插回原分区(可选)
INSERT INTO orders SELECT * FROM orders_backup_p202312;

批量备份多个分区

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
# 分区备份脚本

BACKUP_DIR="/backup/mysql_partitions"
DATE=$(date +%Y%m%d)

# 备份指定月份的分区
PARTITIONS="p202312 p202311 p202310"

for PARTITION in $PARTITIONS; do
    # 创建备份表
    mysql -e "CREATE TABLE orders_backup_${PARTITION} LIKE orders;"
    mysql -e "ALTER TABLE orders_backup_${PARTITION} REMOVE PARTITIONING;"
    
    # 交换分区数据到备份表
    mysql -e "ALTER TABLE orders EXCHANGE PARTITION ${PARTITION} WITH TABLE orders_backup_${PARTITION};"
    
    # 导出备份表数据
    mysqldump -u username -p database orders_backup_${PARTITION} > ${BACKUP_DIR}/orders_${PARTITION}_${DATE}.sql
    
    # 将数据插回原分区
    mysql -e "INSERT INTO orders SELECT * FROM orders_backup_${PARTITION};"
    
    # 清理备份表
    mysql -e "DROP TABLE orders_backup_${PARTITION};"
done

2. 物理文件备份

备份分区物理文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
# 物理文件备份

MYSQL_DATA_DIR="/var/lib/mysql"
BACKUP_DIR="/backup/mysql_physical"
DATABASE="your_database"
TABLE="orders"

# 停止MySQL或锁定表
mysql -e "FLUSH TABLES $DATABASE.$TABLE WITH READ LOCK;"

# 备份分区文件
for PARTITION_FILE in ${MYSQL_DATA_DIR}/${DATABASE}/orders#P#p*.ibd; do
    if [ -f "$PARTITION_FILE" ]; then
        FILENAME=$(basename "$PARTITION_FILE")
        cp "$PARTITION_FILE" "${BACKUP_DIR}/${FILENAME}_$(date +%Y%m%d)"
    fi
done

# 解锁表
mysql -e "UNLOCK TABLES;"

# 备份表结构
mysqldump -d $DATABASE $TABLE > ${BACKUP_DIR}/orders_structure.sql

3. 逻辑备份工具

使用 mysqldump 备份特定分区

1
2
3
4
5
6
7
8
# 备份单个分区
mysqldump -u username -p database orders --where="created_at >= '2023-12-01' AND created_at < '2024-01-01'" > orders_p202312.sql

# 备份表结构+所有分区数据
mysqldump -u username -p database orders > orders_full_backup.sql

# 仅备份表结构
mysqldump -d -u username -p database orders > orders_structure.sql

使用 mysqlpump(MySQL 5.7+)

1
2
# 并行备份,支持进度显示
mysqlpump -u username -p --parallel-schemas=4 database --include-tables=orders > orders_backup.sql

4. 分区数据恢复

从逻辑备份恢复分区

1
2
3
4
5
6
7
8
-- 方法1:直接插入备份数据
LOAD DATA INFILE '/backup/orders_p202312.csv' 
INTO TABLE orders 
FIELDS TERMINATED BY ',' 
LINES TERMINATED BY '\n';

-- 方法2:使用SOURCE命令
SOURCE /backup/orders_p202312.sql;

恢复单个分区数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
-- 创建临时恢复表
CREATE TABLE orders_restore_p202312 LIKE orders;
ALTER TABLE orders_restore_p202312 REMOVE PARTITIONING;

-- 导入备份数据到临时表
SOURCE /backup/orders_p202312.sql;

-- 清空目标分区(如果需要)
ALTER TABLE orders TRUNCATE PARTITION p202312;

-- 交换数据回分区
ALTER TABLE orders EXCHANGE PARTITION p202312 
WITH TABLE orders_restore_p202312;

-- 清理临时表
DROP TABLE orders_restore_p202312;

5. 完整的分区备份恢复方案

备份脚本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
# 完整分区备份脚本

BACKUP_BASE="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="${BACKUP_BASE}/${DATE}"
LOG_FILE="${BACKUP_BASE}/backup.log"

mkdir -p $BACKUP_DIR

# 备份表结构
echo "$(date): Backing up table structure..." >> $LOG_FILE
mysqldump -d -u backup_user -p'password' your_database orders > ${BACKUP_DIR}/orders_structure.sql

# 备份每个分区数据
echo "$(date): Backing up partition data..." >> $LOG_FILE
mysql -u backup_user -p'password' -N -e "SELECT PARTITION_NAME FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='orders' AND TABLE_SCHEMA='your_database'" | while read partition; do
    if [ "$partition" != "pmax" ]; then
        echo "Backing up partition: $partition"
        mysqldump -u backup_user -p'password' your_database orders --where="created_at >= DATE_SUB(DATE_ADD(STR_TO_DATE(REPLACE('$partition', 'p', ''), '%Y%m'), INTERVAL 1 MONTH), INTERVAL 1 MONTH) AND created_at < DATE_ADD(STR_TO_DATE(REPLACE('$partition', 'p', ''), '%Y%m'), INTERVAL 1 MONTH)" > ${BACKUP_DIR}/orders_${partition}.sql
    fi
done

# 备份分区定义
echo "$(date): Backing up partition definition..." >> $LOG_FILE
mysql -u backup_user -p'password' -e "SHOW CREATE TABLE orders" your_database > ${BACKUP_DIR}/orders_partition_def.sql

echo "$(date): Backup completed to $BACKUP_DIR" >> $LOG_FILE

恢复脚本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/bin/bash
# 分区恢复脚本

BACKUP_DIR="$1"
DATABASE="your_database"

if [ -z "$BACKUP_DIR" ]; then
    echo "Usage: $0 <backup_directory>"
    exit 1
fi

# 恢复表结构
echo "Restoring table structure..."
mysql -u root -p $DATABASE < ${BACKUP_DIR}/orders_structure.sql

# 重新创建分区(如果需要)
echo "Recreating partitions..."
mysql -u root -p $DATABASE < ${BACKUP_DIR}/orders_partition_def.sql

# 恢复分区数据
echo "Restoring partition data..."
for partition_file in ${BACKUP_DIR}/orders_p*.sql; do
    if [ -f "$partition_file" ]; then
        partition_name=$(basename $partition_file .sql | sed 's/orders_//')
        echo "Restoring partition: $partition_name"
        mysql -u root -p $DATABASE < $partition_file
    fi
done

echo "Restore completed!"

6. 基于时间点的备份策略

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/bin/bash
# 自动化备份策略

# 每日增量备份(最近7天)
mysqldump -u backup_user -p'password' your_database orders --where="created_at >= DATE_SUB(CURDATE(), INTERVAL 1 DAY)" > /backup/daily/orders_$(date +%Y%m%d).sql

# 每周全量备份
if [ $(date +%u) -eq 1 ]; then  # 每周一
    mysqldump -u backup_user -p'password' your_database orders > /backup/weekly/orders_$(date +%Y%m%d).sql
fi

# 每月分区归档
if [ $(date +%d) -eq 1 ]; then  # 每月1号
    LAST_MONTH=$(date -d "last month" +%Y%m)
    mysqldump -u backup_user -p'password' your_database orders --where="created_at >= DATE_SUB(DATE_FORMAT(NOW(), '%Y-%m-01'), INTERVAL 1 MONTH) AND created_at < DATE_FORMAT(NOW(), '%Y-%m-01')" > /backup/monthly/orders_${LAST_MONTH}.sql
fi

重要注意事项

  1. 备份期间锁定:大型分区备份时考虑业务影响,可在业务低峰期进行
  2. 存储空间:分区备份需要足够的磁盘空间
  3. 恢复测试:定期测试备份文件的恢复流程
  4. 监控告警:设置备份任务的监控和告警机制
  5. 保留策略:制定合理的备份文件保留周期

这种分层备份策略既能保证数据安全,又能在需要时快速恢复特定分区的数据。