通过主从复制机制完成MySQL数据库服务迁移

qunyingliu

0x00 背景

业务所在机房裁撤,原业务机器也已经过保,通过MySQL主从复制机制完成MySQL数据服务的无缝迁移。

0x01 准备

1.环境:

原则上搭建mysql主从复制最好是操作系统版本、环境,MySQL版本、配置保持一致,这样可以保证MySQL主从集群的稳定性,以及减少版本和环境造成的异常,便于排查和定位问题。

由于我们涉及迁移的机器往往是很久以前上线,而且也从未有相关系统和服务升级的机制,还好这次涉及的MySQL版本比较高,与MySQL 5.6的兼容性还是比较好的,谢天谢地,谢前任。

原机器环境:

IP:A(机器已回收)

系统版本:suse 11 linux x64

mysql版本:mysql 5.5.3

配置文件路径:无

程序启动方式:/bin/sh /usr/local/mysql/bin/mysqld_safe &

新机器环境:

IP:xxxxxx B

系统版本: tlinux 1.2 64bit(centos 6.2)

mysql版本:mysql-5.6.25

配置文件路径: /etc/my.cnf

程序启动方式: /etc/init.d/mysqld  start

2.安装包准备

源码包下载:

cmake:yum install cmake (2.6.4) 即可 或 下载 https://cmake.org/files/v3.3/cmake-3.3.2.tar.gz

MySQL :http://dev.mysql.com/downloads/mysql/5.6.html#downloads

0x02 MySQL安装与配置

1.安装(这里不是本文重点,如果出错了,需要根据错误分析解决)

原则上,运营环境一般推荐通过源码进行编译安装,这样才能充分利用当前机器的特性,但是由于我们以前在相同系统环境下编译安装并制作了相关部署包,所以真实安装过程就略过了。这里的安装过程是我们一般通用的安装过程:

a. yum 安装

yum install mysql mysql-server (推荐tlinux2.0,对应centos 7.0,fedora 20+)

很不幸,tilnux 1.2环境 yum安装的版本为mysql-5.1.61,老掉牙了。

b. 源码编译安装

cd mysql-5.6.25groupadd mysql

useradd -g mysql mysql -s /bin/false

mkdir -p /data/dbdata

chown mysql:mysql  /data/dbdata

cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/data/dbdata  -DSYSCONFDIR=/etc/

make&&make install

cp /usr/local/mysql/support-files/my-default.cnf /etc/my.cnf

cd /usr/local/

mv  mysql mysql-5.6.25 && ln -s mysql-5.6.25 mysql

cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld

chmod +x /etc/init.d/mysqld

chkconfig --add mysqld

chkconfig mysqld on

初始化mysql:

/usr/local/mysql/scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/data/dbdata

vi /etc/profile

增加:export PATH=$PATH:/usr/local/mysql/bin

/etc/init.d/mysqld start

2.配置

旧机器:

登录 mysql服务终端:

设置server id:

set  gloabl  server_id=2;select  @@server_id;

开启binlog:

SET SQL_LOG_BIN=1;

SET GLOBAL binlog_format = ‘MIXED‘; ##表结构变更以statement模式来记录,update或者delete等修改数据的语句是记录所有行的变更。

mysql> select @@server_id;

+-------------+

| @@server_id |

+-------------+

| 2           |

+-------------+

1 row in set (0.00 sec)

新机器:

vi /etc/my.cnf

log-bin = /data/dbdata/binlog/mysql-binbinlog_format = MIXED

binlog_cache_size = 4M

max_binlog_cache_size = 1024M

max_binlog_size = 1024M

expire_logs_days = 5log-slave-updates

server-id = 20151109

mysql> select  @@server_id;+-------------+

| @@server_id |+-------------+

|    20151109 |

+-------------+1 row in set (0.00 sec)

0x03 数据的导出与导入

1.数据导出:

涉及的DB不多,DB的读写不频繁,导出mysql数据我们选择使用mysqldump。

因为要添加主从信息,所以需要添加-master-data=1,附带锁表操作,当表的存储引擎为InnoDB时,加了 --single-transaction 可以减少锁表的影响,准确的说只会有短时间的全局读锁,比MyISAM的锁表情况要好得多。

mysqldump -u root --default-character-set=utf8  -Y -B  --set-charset  --single-transaction   --master-data=1  hehehehhe >  /data/backup/databases/hehehehhe20151109.sql

CHANGE MASTER

-Y, --all-tablespaces

Dump all the tablespaces.

-B, --databases    Dump several databases. Note the difference in usage; in

if you dump many databases at once (using the option

--databases= or --all-databases), the logs will be

Locks all tables across all databases. This is achieved

--all-databases or --databases is given.

--master-data[=#]   This causes the binary log position and filename to be

appended to the output. If equal to 1, will print it as a

CHANGE MASTER command; if equal to 2, that command will

be prefixed with a comment symbol. This option will turn

--lock-all-tables on, unless --single-transaction is

specified too (in which case a global read lock is only

taken a short time at the beginning of the dump; don‘t

forget to read about --single-transaction below). In all

cases, any action on logs will happen at the exact moment

of the dump. Option automatically turns --lock-tables

off.

--dump-slave[=#]    This causes the binary log position and filename of the

master to be appended to the dumped data output. Setting

the value to 1, will printit as a CHANGE MASTER command

in the dumped data output; if equal to 2, that command

will be prefixed with a comment symbol. This option will

turn --lock-all-tables on, unless --single-transaction is

specified too (in which case a global read lock is only

taken a short time at the beginning of the dump - don‘t

forget to read about --single-transaction below). In all

cases any action on logs will happen at the exact moment

of the dump.Option automatically turns --lock-tables off.

--include-master-host-port

Adds ‘MASTER_HOST=<host>, MASTER_PORT=<port>‘ to ‘CHANGE

MASTER TO..‘ in dump produced with --dump-slave.

--single-transaction

Creates a consistent snapshot by dumping all tables in a

single transaction. Works ONLY for tables stored in

storage engines which support multiversioning (currently

only InnoDB does); the dump is NOT guaranteed to be

consistent for other storage engines. While a

--single-transaction dump is in process, to ensure a

valid dump file (correct table contents and binary log

position), no other connection should use the following

statements: ALTER TABLE, DROP TABLE, RENAME TABLE,

TRUNCATE TABLE, as consistent snapshot is not isolated

from them. Option automatically turns off --lock-tables.

--set-charset       Add ‘SET NAMES default_character_set‘ to the output.

(Defaults to on; use --skip-set-charset to disable.)

查看主从信息:

[[email protected]_B_IP_HOST /data/backup/databases]#

自带切换主从同步点命令,需要注意的是添加此命令时需要将所有主从同步状态的数据库数据一同导出。

grep CHANGE /data/backup/databases/hehehehhe20151109.sql

CHANGE MASTER TO MASTER_LOG_FILE=‘mysql-bin.000001‘, MASTER_LOG_POS=120;

2.数据导入:

新机器:

CREATE DATABASE `hehehehhe` /*!40100 DEFAULT CHARACTER SET utf8 */;

搭建主从同步后stop slave,直接通过mysql 直接导入数据,然后在start slave即可。

0x04 主从复制配置与数据的同步

1. MySQL binlog

binlog是MySQL主从复制的基础,MySQL通过binlog来记录数据库数据的变更,可用来搭建主从复制集群,也可以用mysqlbinlog来通过binlog恢复部分数据异常。

如果遇到灾难事件,应该用最近一次制作的完整备份恢复数据库,然后使用备份之后的日志文件把数据库恢复到最接近现在的可用状态。使用日志进行恢复时需要依次进行,即最早生成的日志文件要最先恢复。

常用binlog日志操作命令

1.查看所有binlog日志列表

mysql> show master logs;(新机器作为主时,binlog的信息)

[[email protected]_B_IP_HOST /data/dbdata/binlog]# pwd/data/dbdata/binlog

[[email protected]_B_IP_HOST /data/dbdata/binlog]# lltotal 884156-rw-rw---- 1 mysql admin     27317 Nov  9 12:41 mysql-bin.000001-rw-rw---- 1 mysql admin   1034478 Nov  9 12:41 mysql-bin.000002-rw-rw---- 1 mysql admin       531 Nov  9 12:42 mysql-bin.000003-rw-rw---- 1 mysql admin 903407219 Nov 12 00:10 mysql-bin.000004-rw-rw---- 1 mysql admin       148 Nov  9 15:08 mysql-bin.index

[[email protected]_B_IP_HOST /data/dbdata/binlog]# mysql -e "show master logs;"+------------------+-----------+

| Log_name         | File_size |

+------------------+-----------+

| mysql-bin.000001 |     27317 |

| mysql-bin.000002 |   1034478 |

| mysql-bin.000003 |       531 |

| mysql-bin.000004 | 903407219 |

+------------------+-----------+

2.查看master状态,即最后(最新)一个binlog日志的编号名称,及其最后一个操作事件pos结束点(Position)值

mysql> show master status;(新机器作为从时,主服务器最新binlog的位置信息)

[[email protected]_B_IP_HOST /data/dbdata/binlog]# mysql -e "show master status;"+------------------+-----------+--------------+------------------+-------------------+

| File             | Position  | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |

+------------------+-----------+--------------+------------------+-------------------+

| mysql-bin.000004 | 903407219 |              |                  |                   |

+------------------+-----------+--------------+------------------+-------------------+

3.刷新log日志,自此刻开始产生一个新编号的binlog日志文件

mysql> flush logs;

mysql> flush logs;

Query OK, 0 rows affected (0.00 sec)

mysql> show master logs;

+------------------+-----------+

| Log_name         | File_size |

+------------------+-----------+

| mysql-bin.000001 |     27317 |

| mysql-bin.000002 |   1034478 |

| mysql-bin.000003 |       531 |

| mysql-bin.000004 | 903407266 |

| mysql-bin.000005 |       120 |

+------------------+-----------+5 rows in set (0.00 sec)

注:每当mysqld服务重启时,会自动执行此命令,刷新binlog日志;在mysqldump备份数据时加 -F 选项也会刷新binlog日志;

4.重置(清空)所有binlog日志

mysql> reset master;

mysql> reset master;

Query OK, 0 rows affected (0.08 sec)

mysql> show master logs;

+------------------+-----------+

| Log_name         | File_size |

+------------------+-----------+

| mysql-bin.000001 |       120 |

+------------------+-----------+1 row in set (0.00 sec)

清空当前机器的binlog。

5.清理

清除binlog

PURGE {MASTER|BINARY} LOGS TO ‘log_name‘ //log_name不会被清除

PURGE {MASTER|BINARY} LOGS BEFORE ‘date‘ //date不会被清除

2. 主从复制配置

1)旧机器(主A_IP)上创建主从同步帐号:

grant replication slave on *.* to ‘rep‘@‘B_IP‘ identified by ‘heheheh‘;

2)查看当前旧机器(主A_IP)的binlog状态

mysql> show master status;+------------------+----------+--------------+------------------+-------------------+| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |

+------------------+----------+--------------+------------------+-------------------+

| mysql-bin.000001 |      120 |              |                  |                   |

+------------------+----------+--------------+------------------+-------------------+1 row in set (0.00 sec)

3)在新机器(B_IP)上创建主从同步

mysql> change master to master_host=‘A_IP‘,

master_user=‘rep‘,

master_password=‘heheheh‘,

master_port=3306,

master_log_file=‘mysql-bin.000001‘,

master_log_pos=120,

master_connect_retry=10;

参数详解:

master_host:主服务器的IP。

master_user:配置主服务器时建立的用户名

master_password:用户密码

master_port:主服务器mysql端口,如果未曾修改,默认即可。

master_log_file:日志文件名称,填写查看master状态时显示的Filemaster_log_pos:日志位置,填写查看master状态时显示的Positionmaster_connect_retry:重连次数

4)启动进程

mysql> start slave;

查看主从同步情况:

主要需要关注Slave_IO_Running: YES; Slave_SQL_Running: YES;Seconds_Behind_Master: 0

mysql> show slave status \G;*************************** 1. row ***************************

Slave_IO_State:

Master_Host: A_IPMaster_User: rep

Master_Port: 3306Connect_Retry: 60Master_Log_File: Tencent64-bin.000164Read_Master_Log_Pos: 107Relay_Log_File: WEBAPP_B_IP_HOST-relay-bin.000006Relay_Log_Pos: 270Relay_Master_Log_File: Tencent64-bin.000164Slave_IO_Running: YES

Slave_SQL_Running: YES

Replicate_Do_DB:

Replicate_Ignore_DB:

Replicate_Do_Table:

Replicate_Ignore_Table:

Replicate_Wild_Do_Table:

Replicate_Wild_Ignore_Table:

Last_Errno: 0Last_Error:

Skip_Counter: 0Exec_Master_Log_Pos: 107Relay_Log_Space: 786Until_Condition: None

Until_Log_File:

Until_Log_Pos: 0Master_SSL_Allowed: No

Master_SSL_CA_File:

Master_SSL_CA_Path:

Master_SSL_Cert:

Master_SSL_Cipher:

Master_SSL_Key:

Seconds_Behind_Master: 0

Master_SSL_Verify_Server_Cert: No

主从信息查看的命令:

show slave hosts \G;主机上查看从机信息

show master status\G;主机上查看状态信息

show slave status \G;从机上查看主从状态信息

0x05 存储过程与权限的导入

1.存储过程和函数的导出

由于存储过程和数据库权限信息存储在mysql库中,通过mysqldump普通参数是不会导出的。

导出存储过程: mysqldump 加 -R (或 --routines)参数即可。

-R, --routines      Dump stored routines (functions and procedures).

Add ‘SET @@GLOBAL.GTID_PURGED‘ to the output. Possible                      @@GLOBAL.GTID_PURGED‘ is added to the output. If GTIDs

statements: ALTER TABLE, DROP TABLE, RENAME TABLE,

TRUNCATE TABLE, as consistent snapshot is not isolated

单独导出存储过程等内容:

mysqldump -uroot  -n -d -t -R hehehehhe > procedure_name.sql

-- MySQL dump 10.10--

-- Host: localhost    Database: hehehehhe

-- ------------------------------------------------------

-- Server version       5.5.3-m3-log

后期也发现,如果在导出时mysqldump指定 --databases 会自动将原DB的创建语句添加进去,但是有的时候我们希望自己指定DB创建语句,比如要指定默认字符集为utf8,而原来的用的是latin1,这个时候我们就不需要加这个参数了。

2.数据库权限的导出与导入

数据库的权限有针对全局的也有针对特定库和表的权限,无法直接导出再导入。

主要通过查出旧机器授权过的帐号和机器IP,在通过show grants语句来获取相应权限。

mysql>  SELECT CONCAT("show grants for ",user,"@",host,";") from mysql.user;

+----------------------------------------------+

| CONCAT("show grants for ",user,"@",host,";") |

+----------------------------------------------+

| show grants for [email protected];      || show grants for [email protected];     || show grants for [email protected];     || show grants for [email protected];    || show grants for [email protected];     || show grants for [email protected];              || show grants for [email protected]::1;                    || show grants for [email protected];         || show grants for [email protected];              |+----------------------------------------------+9 rows in set (0.00 sec)

然后将show grants语句放到脚本中,运行脚本获取到旧机器上相关授权信息。

最后,在新机器上运行之前获得的授权信息脚本,即可导入相关权限。

注意,这里可能出现报错,数据库不存在的情况下将相关权限导入,所以在导入前需要过滤下。

0x06 数据校验与业务验证

数据校验和业务验证不是我们要讲的重点,但是是数据库迁移不可缺少的一部分。

验证数据的方式有两种:

1.查看数据记录与主从同步状态,可以简单快速判断,但是不是最准确的。

2.通过跑脚本,校验数据库下每个表的checksum值,准确,可能会有些慢。

3.通过Percona Toolkit for MySQL 工具中pt-table-checksum来进行主从校验,强烈推荐

https://www.percona.com/doc/percona-toolkit/2.2/index.html

https://www.percona.com/doc/percona-toolkit/2.1/pt-table-checksum.html

0x07 常见问题分析与解决

1. MyIsam存储引擎 锁表导致服务中断,影响到业务。

之前与互娱的兄弟在RTX沟通,备份数据时MyISAM锁表时间过久导致服务出现异常,所以我们一般建议搭建专门的备机进行备份数据,以及尽量用INNODB存储引擎。

2.数据校验时,用percona的工具发现数据不一致,处理数据时发现自增ID发生变化,通过自增ID查不到指定的业务数据

数据不一致时优先使用pt-table-sync进行修复,但是这个修复方式是缺少时插入,冲突时replace,自增ID会发生变化。

建议自增ID不要作为业务属性使用。

3.占坑,未完待续,欢迎一起续写。

0x08 其他

一切皆有可能,在实验环境多去实践会降低出问题时空手无策的几率。

还好这次迁移MySQL版本比较高,要是碰到5.0或5.1那就坑死了。

感谢Percona,让一个二把手也可以保障mysql服务的稳定性。

感谢国家,感谢父母。

感谢一起讨论问题的你们。

时间: 2024-10-17 13:57:23

通过主从复制机制完成MySQL数据库服务迁移的相关文章

转:Mysql使用主从复制机制(replication)

内容转自:http://blog.sina.com.cn/s/blog_4e424e2101000c1z.html;http://blog.sina.com.cn/s/blog_4e424e2101000c20.html MySQL支持单向.异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器.主服务器将 更新写入二进制日志文件,并维护日志文件的一个索引以跟踪日志循环.当一个从服务器连接到主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置.从服务器接

MySQL数据库服务主从复制

随着访问量的不断增加,单台MySQL数据库服务器压力不断的增加,需要对MySQL进行优化和架构改造,如果MySQL优化不能明显改善,可以使用高可用,主从复制,读写分离,拆分库,拆分表等方法来进行优化. MySQL主从复制的目的是实现数据冗余备份,将master数据库数据定时同时到slave库中,一旦master数据库宕机,可以将Web应用数据库配置快速切换至slave数据库,确保Web应用有较高的高可用率. 一.什么是主从复制?** 主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从

mysql数据迁移

一. 数据迁移简介所谓的数据迁移,就是指将原有的数据库系统迁移到另外一个业务系统上数据迁移的原因是多种多样的,有可能是业务变更.硬件升级.平台切换或升级mysql数据库 迁移的注意事项:(1).相同版本可以迁移(2).注意版本可以使用的引擎(3).低版本可以向高版本进行数据迁移,高版本一般兼容低版本的特性(4).高版本的数据不能向低版本进行数据迁移,会出现数据不兼容的情况(5).迁移是请注意导出数据和备份数据,出现迁移失败时,立即启动备份方案,保证公司业务的正常运行(6).在数据迁移时,要选择用

MySQL数据迁移到MSSQL-以小米数据库为例-测试828W最快可达到2分11秒

这里采用.NET Framework 4.0以上版本中新出现的 ConcurrentQueue<T> 类 MSDN是这样描述的: ConcurrentQueue<T> 类是一个线程安全的先进先出 (FIFO) 集合. ConcurrentQueue<T> 的所有公共且受保护的成员都是线程安全的,可从多个线程同时使用. 共采用两个线程,一个读一个写. ConcurrentQueue<T>的实现方法: (FIFO) 集合: ConcurrentQueue<

阿里云 CentOS下面 Mysql 数据迁移

本次Mysql数据迁移, 只是从阿里云的CentOS系统盘中,把mysql的data数据, 迁移到非系统盘中. 起因: 由于购买阿里云时候,  默认的系统盘只有20G.  后又购买了100G磁盘空间, 这时, 需要把原mysql数据, 迁移到新的磁盘分区中. 所有的操作步骤记录如下: 1. 新挂载磁盘分区: mount, 并设置为重启后自动加载. 2. 暂时关闭nginx服务器. 再关闭mysql服务器. 3. 修改/etc/my.cnf配置文件, 将里面的路径, 修改为新磁盘中的, 需要保存m

手工编译安装mysql数据库服务

实验要求:手工编译安装mysql数据库服务 实验步骤: 首先挂载并且建立yum仓库,查看yum有没有建好,在创建lamp文件 然后把宿主机的LAMP共享文件夹挂载到lamp目录下 将mysql归档包解压到/opt目录下 安装 gcc . gcc-c++. make .cmake(编译).后面都是开发包ncurses-devel.bison.libaio-devel的软件包(gcc . gcc-c++用yum装,其他用rpm装),在查看下有没有安装make 和cmake,诶有就安装 添加一个叫做m

CentOS6.7下使用非root用户(普通用户)编译安装与配置mysql数据库并使用shell脚本定时任务方式实现mysql数据库服务随机自动启动

CentOS6.7下使用非root用户(普通用户)编译安装与配置mysql数据库并使用shell脚本定时任务方式实现mysql数据库服务随机自动启动1.关于mysql?MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司.MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性.特点: Mysql是开源的,所以你不需要支付额外的费用.Mysql支持大型的数据库.可以处理拥有上千

MySQL数据库迁移(转)

MySQL数据库迁移(数据文件直接迁移) 在今年10月下旬的时候,公司的服务器需要迁移,其中涉及到了MySQL数据库迁移.查看了一下MySQL数据文件的大小,接近60G的大小(实际数据并没用那么多).由于服务器上业务需要,要尽量减少服务器迁移时的损失.所以迁移时间选在了晚上零点开始,而且要尽量减少迁移所用的时间. 在迁移之前有三种方案: 数据库直接导出,拷贝文件到新服务器,在新服务器上导入. 使用[MySQL GUI Tools]中的 MySQLMigrationTool. 数据文件和库表结构文

Mysql备份迁移——MySqlBackup——(无法解决视图嵌视图报错)

这里是利用MySqlBackup,可以再nuget中下载. 无法解决视图嵌视图报错的问题,只导表跟数据比较合适,如果有视图嵌视图,请参照Mysql备份迁移——Mysqldump(.NET调用Mysqldump.exe方式)——(解决视图嵌视图报错)http://www.cnblogs.com/pbys/p/4142367.html string constring = "server=192.168.0.1;port=3306;user=root; pwd=123456; database=te