jsp开发的网站,牛二网站建设,seo下拉优化,从零开始制作 wordpress 主题Linux - MySQL迁移至一主一从 迁移准备安装MySQL ibd文件迁移原服务器操作目标服务器操作 一主一从增量同步异常解决结尾 首先部分单独安装MySQL#xff0c;请参考Linux - MySQL安装#xff0c;迁移数据量比较大约400G左右且网络不通故使用文件迁移#xff0c;需开启一段时间… Linux - MySQL迁移至一主一从 迁移准备安装MySQL ibd文件迁移原服务器操作目标服务器操作 一主一从增量同步异常解决结尾 首先部分单独安装MySQL请参考Linux - MySQL安装迁移数据量比较大约400G左右且网络不通故使用文件迁移需开启一段时间只读和锁表。 迁移准备
测试机作用172.17.7.9原MySQL10.3.69.6目标主库10.3.69.7目标从库 原服务器与目标服务器不在同一局域网内而且无外网。 思路 先检测原MySQL健康的表进行记录设置原MySQL为只读以及锁表防止迁移过程中继续写入记录时间点用作迁移后增量同步导出所有表结构和ibd文件解锁恢复读写将表结构和ibd文件转至目标主库以及从库都先进行恢复ibd文件然后进行主从连接使用binlog导出原MySQL时间点开始的sql日志并增量同步至目标主库。 安装MySQL
先在目标2台服务器上面安装MySQL请参考Linux - MySQL安装其中my.cnf配置参考以下其中server_id主库与从库不一致 主库6 从库7其他配置都一致具体参数值参考自己MySQL需求大小进行配置。
[mysqld]
basedir/usr/local/mysql/mysql8
datadir/home/mysql/data
log-error/home/mysql/log/mysql.logserver_id6
gtid_modeon
enforce_gtid_consistencyon
binlog_formatrow
log-slave-updateson
log-binmysqlbin-log
binlog_row_image minimalmax_connections2000
lower_case_table_names1
character-set-serverutf8mb4
default_authentication_pluginmysql_native_password
max_binlog_size1G
max_binlog_cache_size4G
log_timestampssystem配置好后就初始化MySQL然后重置密码操作什么的先不进行主从连接。
ibd文件迁移
原服务器操作
注其中有些打通ssh免密也进行了记录(假设原服务器和目标服务器可以互通)本次迁移未使用到ssh免密
ssh免密
ssh-keygen -t rsa
ssh-copy-id root10.3.69.6
ssh-copy-id root10.3.69.7
ssh root10.3.69.6 # 测试是否免密登录
ssh root10.3.69.7创建一个export.sh脚本 找一个磁盘够大的位置看数据量创建一个transfer文件夹在这个文件夹里面创建脚本 我们要一次一个库的去迁移数据量有点大没磁盘了当然也可以一次全部迁移全部的库自行加一个循环先查询某个库的所有表名然后导出这个库所有的表结构然后把ibd文件复制压缩即可 此处我自己写了一个py每过10s向数据库orders表中新增一条数据模拟真实写入 #!/bin/bash# 数据库连接信息 变量 - 需要更改的
DB_USERroot # 替换为你的数据库用户名
DB_PASSWORD123456 # 替换为你的数据库密码
DB_HOST172.17.7.9 # 主机地址
DB_NAMEdw # 数据库名称想迁移整个MySQL所有库可以写个大循环
MYSQLDUMP_PATH/usr/local/mysql/mysql8/bin/mysqldump # mysqldump 路径
MYSQL_DATA_DIR/home/weekeight/mysql/data/${DB_NAME} # MySQL 数据目录路径# 注下面的所有值都不需要修改
# 输出文件路径
TABLES_FILE${DB_NAME}_table_name.txt
SCHEMA_FILE${DB_NAME}_schema.sql
# 创建 dw 文件夹如果不存在
DW_DIR./${DB_NAME}
mkdir -p $DW_DIR
# 查询所有表名并保存到文件移除标题行
mysql -u $DB_USER -p$DB_PASSWORD -h $DB_HOST -D $DB_NAME -e SHOW TABLES; | sed 1d $TABLES_FILE
if [ $? -ne 0 ]; thenecho 导出表名时发生错误exit 1
fi
echo 表名已成功导出到 $TABLES_FILE
# 使用 mysqldump 导出表结构到文件
$MYSQLDUMP_PATH -u $DB_USER -p$DB_PASSWORD -h $DB_HOST --no-data --single-transaction --routines --triggers --events $DB_NAME $SCHEMA_FILE
if [ $? -ne 0 ]; thenecho 导出表结构时发生错误exit 1
elseecho 表结构已成功导出到 $SCHEMA_FILE
fi
# 复制 IBD 文件到 dw 文件夹
while IFS read -r table; doibd_file${MYSQL_DATA_DIR}/${table}.ibdif [ -f $ibd_file ]; thencp $ibd_file $DW_DIR/echo 复制了 $ibd_file 到 $DW_DIR/elseecho 警告: $ibd_file 不存在fi
done $TABLES_FILE
# 压缩打包 dw 文件夹
TAR_FILE${DB_NAME}_ibd_files.tar.gz
tar -czvf $TAR_FILE $DW_DIR
if [ $? -eq 0 ]; thenecho dw 文件夹已成功压缩打包为 $TAR_FILE
elseecho 压缩打包时发生错误exit 1
fi
# 清理临时文件夹
rm -rf $DW_DIR
上面的脚本写好记得添加权限
chmod x export.sh搞好sh脚本后先不用管他接下来我们进入MySQL进行设置只读和锁表然后执行脚本恢复MySQL
SET GLOBAL read_only ON; # 设置全局只读模式
FLUSH TABLES WITH READ LOCK; # 锁表
SHOW ENGINE INNODB STATUS\G # 检查当前是否还有事务正在执行
# 记录一下当前时间(16:26:00,order结尾11)用作后续的增量同步order结尾11验证后面的增量同步order.ibd中只存在11条数据
# 然后去执行上面的./export.sh脚本脚本执行完毕后继续在MySQL中执行以下命令恢复MySQL
UNLOCK TABLES; # 解除锁表
SET GLOBAL read_only OFF; # 恢复读写模式恢复后order表记录到38上面sh脚本保存的ibd文件中不包含12-38现在的我们已经生成了三个文件了一个ibd数据文件、一个dw库所有表名文件、一个dw库表结构文件可以把export.sh文件删除了已经没用了 接下来就是把这三个文件移动到目标服务器了下面使用scp
scp -r ./transfer/ root10.3.69.6:/home/weekeight/
scp -r ./transfer/ root10.3.69.7:/home/weekeight/目标服务器操作 下面的操作在目标服务器的两台上面同步执行命令 cd /home/weekeight/transfer/ # 进入移动过来的文件夹里面创建一个import.sh脚本
#!/bin/bash# 变量 - 需要更改的
DB_USERroot # 替换为你的数据库用户名
DB_PASSWORD123456 # 替换为你的数据库密码
DB_NAMEdw # 迁移数据库名
MYSQL_DATA_DIR/home/mysql/data/${DB_NAME} # MySQL 数据目录路径
TRANSFER_DIR/home/weekeight/transfer # 资源目录就是从原服务器移动过来的# 注下面的所有值都不需要修改
IBD_TAR_FILE${TRANSFER_DIR}/${DB_NAME}_ibd_files.tar.gz
SCHEMA_FILE${TRANSFER_DIR}/${DB_NAME}_schema.sql
TABLES_NAME${TRANSFER_DIR}/${DB_NAME}_table_name.txt
log_fileall.log
# 清空日志文件$log_file
# 检查数据库是否存在
check_db_exists() {mysql -u $DB_USER -p$DB_PASSWORD -e SHOW DATABASES LIKE $DB_NAME; | grep -w $DB_NAME /dev/null
}
# 检查数据库是否存在
if check_db_exists; thenecho 数据库 $DB_NAME 已存在。 | tee -a $log_file
else# 创建数据库echo 正在创建数据库 $DB_NAME... | tee -a $log_filemysql -u $DB_USER -p$DB_PASSWORD -e CREATE DATABASE IF NOT EXISTS $DB_NAME;if [ $? -ne 0 ]; thenecho 创建数据库 $DB_NAME 失败请检查数据库连接信息和权限。 | tee -a $log_fileexit 1elseecho 数据库 $DB_NAME 创建成功。 | tee -a $log_filefi
fi
# 导入表结构
echo 正在导入表结构... | tee -a $log_file
mysql -u $DB_USER -p$DB_PASSWORD $DB_NAME $SCHEMA_FILE
if [ $? -eq 0 ]; thenecho 表结构已成功导入到数据库 $DB_NAME 中。 | tee -a $log_file
elseecho 导入表结构失败请检查 $SCHEMA_FILE 是否存在且格式正确。 | tee -a $log_fileexit 1
fi
# 解压 IBD 文件压缩包
echo 解压 IBD 文件... | tee -a $log_file
tar -xzvf $IBD_TAR_FILE -C $TRANSFER_DIR
if [ $? -ne 0 ]; thenecho 解压失败请检查 $IBD_TAR_FILE 是否存在且无损坏。 | tee -a $log_fileexit 1
elseecho 解压成功文件已放置在 $TRANSFER_DIR 中。 | tee -a $log_file
fi
# 循环读取表名
while IFS read -r table_name; doecho 开始处理表 $table_name... | tee -a $log_file# 设置源和目标路径source_path${TRANSFER_DIR}/${DB_NAME}/${table_name}.ibddestination_path${MYSQL_DATA_DIR}/${table_name}.ibd# 清除表空间mysql -u $DB_USER -p$DB_PASSWORD -e ALTER TABLE $DB_NAME.$table_name DISCARD TABLESPACE;if [ $? -ne 0 ]; thenecho 表 $table_name: DISCARD TABLESPACE 失败跳过 | tee -a $log_filecontinuefi# 复制 .ibd 文件cp $source_path $destination_pathif [ $? -ne 0 ]; thenecho 表 $table_name: 文件复制失败跳过 | tee -a $log_filecontinuefi# 修改文件拥有者为 mysqlchown mysql:mysql $destination_pathif [ $? -ne 0 ]; thenecho 表 $table_name: 更改文件拥有者失败跳过 | tee -a $log_filecontinuefi# 导入表空间mysql -u $DB_USER -p$DB_PASSWORD -e ALTER TABLE $DB_NAME.$table_name IMPORT TABLESPACE;if [ $? -ne 0 ]; thenecho 表 $table_name: IMPORT TABLESPACE 失败跳过 | tee -a $log_filecontinuefiecho 表 $table_name 迁移成功 | tee -a $log_file
done $TABLES_NAME
echo 所有表处理完成详情见 $log_file | tee -a $log_file创建import.sh后执行下面操作
chmod x import.sh # 修改权限
./import.sh # 执行执行完毕后检查一下打印是否正确可以查看all.log日志
cd ..
rm -rf ./transfer # 删除移动过来的文件夹即可已无用一主一从 下面是在目标服务器的MySQL上的操作是进行一主一从的连接 首先在主库上面查看gtid值
mysql SHOW VARIABLES LIKE gtid_executed;
----------------------------------------------------------
| Variable_name | Value |
----------------------------------------------------------
| gtid_executed | 36513eed-b6bd-11ef-843c-6c92bfcb11f0:1-76 |
----------------------------------------------------------
1 row in set (0.01 sec)然后在从库上面进行绑定连接
SET GLOBAL.GTID_PURGED36513eed-b6bd-11ef-843c-6c92bfcb11f0:1-76; # 把主库的gtid添加到这里
change master to master_host10.3.69.6,master_port3306,master_userroot,master_password123456,master_auto_position1 for channel master1; # 连接主库创建管道名为msater1
start slave for channel master1; # 单独启动master1进行复制可使用start slave;
show slave status\G # 查看从库的状态状态中Slave_IO_Running与Slave_SQL_Running同为yes时正常不然就是异常下面的几个命令不需要执行如果主从连接出现了问题那么我们就要停止连接清除配置重新连接时使用的
stop slave; # 停止主从
reset master; # 重置主库配置
reset slave all; # 重置从库配置下面就是去主库上面进行创建一个数据库或者写入数据查看从库是否变化了
增量同步 上方已经记录了时间以及order参数(16:26:00)目标数据库的参数为11原数据库的参数是38 先在原mysql上面进行查看binlog的file然后导出binlog信息
mysql SHOW MASTER STATUS;
----------------------------------------------------------------------------
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
----------------------------------------------------------------------------
| binlog.000014 | 33034659 | | | |
----------------------------------------------------------------------------
1 row in set (0.00 sec)–skip-gtids跳过GTID事件必填项不加的话导出的数据用不了GTID冲突–database指定数据库–start-datetime指定开始时间此时间即锁表后的时间上面已经记录了–stop-datetime指定结束时间最好指定此时间导出的数据包头不包尾这样的话如果有需要下次的增量同步这个就是开始时间binlog的文件在MySQL数据目录中上面已经有文件名称了
/usr/local/mysql/mysql8/bin/mysqlbinlog --skip-gtids --databasedw --start-datetime2024-12-12 16:26:00 --stop-datetime2024-12-13 10:00:00 /home/weekeight/mysql/data/binlog.000014 ./dw20241213100000.sql把dw20241213100000.sql文件发送到目标服务器主库上面从库不需要。
scp -r ./dw20241213100000.sql root10.3.69.6:/usr/local/下面在主库上导入sql
mysql -u root -p dw dw20241213100000.sql然后查看主库以及从库orders参数是否增加。
异常解决
SESSION.GTID_NEXT cannot be set to ANONYMOUS when GLOBAL.GTID_MODE ON. 主库执行增量的sql文件时报错 binlog导出sql信息时使用–skip-gtids跳过GTID事件 Multiple channels exist on the slave. Please provide channel name as an argument 需要将从机的master清空本机连接的有master的也要清空 stop slave; reset slave all; reset master; GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with GLOBAL.GTID_EXECUTED reset master; GLOBAL.GTID_PURGED cannot be changed: the new value must be a superset of the old value 之前已经存在gtid了想再需要配置一个多个的 SET GLOBAL.GTID_PURGED‘以前的gtid…,新的gtid’; 结尾 至此MySQL迁移至一主一从已经全部搞定如果有问题或者有其他好的方案望提议共同学习。