MySQL 主从同步操作文档

取自 NSOP-WIKI

目录

1 同步原理说明

2 同步设置基本步骤(以下设置均涉及my.cnf文件的修改)

2.1 设置主(she4 zhi4 zhu3)服务器:启用bin-log日志、同步帐号

2.2 设置从服务器:设置需要同步的内容

2.3 拷贝主服务器数据到从服务器

2.3.1 方式1:停止主服务器或其中一台从服务器并拷贝数据

2.3.2 方式2:在主服务器或其中一台从服务器上设置锁,禁止一切读写操作并拷贝数据

2.4 启动同步

3 实例参考:

4 FAQ

1 同步原理说明

MySQL的Replication基于主服务器在二进制日志中跟踪所有对数据库的更改(更新、删除等)。

MySQL使用3个线程来完成Replication工作,具体分布是(gong1 zuo1 _ju4 ti3 fen1 bu4 shi4)主上1个相关线程、从上2个相关线程;

主的相关线程可以理解为主服务器上SHOW PROCESSLIST的输出中的Binlog Dump线程、从服务器分别为IO和SQL线程;

主 服务器创建将binlog中的内容发送到从服务器。从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器数据目录中的中继日志文件(relay-log)里,SQL线程用于读取中继(xian4 cheng2 yong4 yu2 du2 qu3 zhong1 ji4)日志并执行日志中包含的更新。

MySQL的Replication是单向,异步同步

MySQL同 步机制基于master把所有对数据库的更新、删除等)都记录在二进制日志里。因此,想(dou ji lu zai er jin zhi ri zhi li _yin ci _xiang)要启用同步机制,在master就必须启用二进 制日志。每个slave接受来自master上在二进制日志中记录的更新操作,因此在slave上执行了这个操作的一个拷贝。应该非常重要地意识到,二进 制日志只是从启用二进制日志开始的时刻才记录更新操作的。所有的 slave必须在启用二进制日志时把master上已经存在的数据拷贝过来。如果运行同步时slave上的数据(shang4 de0 shu3 ju4)和master上启用二进制日志时的数据不 一致的话,那么slave同步就会失皬嫞把master上的数据拷贝过来的方法之一实在slave上执行 LOAD DATA FROM MASTER 语句。不过要注意(yu ju _bu guo yao zhu yi),LOAD DATA FROM MASTER 是从MySQL 4.0.0 之后才开始可以(zhi hou cai kai shi ke yi)用的,而且只支持master上的 MyISAM 类型表。同样地,这个操作需要一个全局的读锁,这样的话传送日志到slave的时候在master上就不会有更新操作了。(shang jiu bu hui you geng xin cao zuo le _)当实现了自由锁表热备份时(在 MySQL 5.0中),全局读锁就没必要了。由于有这些限制,因此我们建议只在master上相关数据比较小的时候才执行 LOAD DATA FROM MASTER 语句,或(yu3 ju4 _huo4)者在master上允许一个长时间的读锁。由于每个系统之间 LOAD DATA FROM MASTER 的速度各不一样,一个比较好的衡量规则是每秒能拷贝1MB数据。这只是的粗略的估计,不过master和slave都是奔腾700MHz的机器且用 100MBit/s网络连接时就能达到这个速度了。slave上已经完整拷贝master数据后,就可以连接到master上然后等待处理更新了 (shang ran hou deng dai chu li geng xin le)。如果 master当机或者slave连接断开,slave会定期尝试连接到master上直到能重连并且等待更新。重试的时间间隔由 --master-connect-retry 选项来控制,它的默(xuan3 xiang4 lai2 kong4 zhi4 _ta1 de0 mo4)认值是60秒。每个slave都记录了它关闭时的日志位置。master是不知道有多少个slave连接(lian jie)上来或者哪个slave从什么 时候开始更新。

MySQL同步功能由3个线 程(master上1个,slave上2个)来实现。执行 START SLAVE 语句后,slave就创(jiu chuang)建一个I/O线程。I/O线程连接到master上,并请求master发送二进制日志中的语句。master创建一个(chuang jian yi ge)线程来把日 志的内容发送到slave上。这个线程在master上执行 SHOW PROCESSLIST 语句后的结果中的 Binlog Dump 线程便是。slave上的I/O线程读取master的 Binlog Dump 线程发送的语句,并且把它们拷贝到其数据目录下的中继日志(relay logs)中。第三个是SQL线程,salve用它来读取中继日志,然后执行它们来更新数据。如上所述,每个mster/slave上都有3个线程。每个 master上有多个线程,它为每个slave连接都创建一个线程,每个slave只有I/O和SQL线程。在MySQL 4.0.2 以前,同步只需2个线程(master和slave各一个)。slave上的I/O和SQL线程合并成一个了,它不使用中继日志。slave上 使用2个线程的优点是,把读日志和执行分开成2个独立的任务。执行任务如果慢的话,读日志任务不会跟着慢下来。例如,如果slave停止了一段时间,那么 I/O线程可以在slave启动后很快地从master上读取全部日志,尽管SQL线程可能落后I/O线程好几的小时。如果slave在SQL线程没全部 执行完就停(zhi xing wan jiu ting)止了,但I/O线程却已经把所有的更新日志都读取并且保存在本地的中继日志(relay-log)中了,因此在slave再次启动后就会继续执 行它们了。这就允许在 master上清除二进制日志,因为slave已经无需去master读取更新日志了。执行 SHOW PROCESSLIST 语句就会告诉我们所关心的master和slave上发生的情况。

2 同步设置基本(tong bu she zhi ji ben)步骤(以下设置均涉及my.cnf文件的修改)

2.1 设置主服务器:启用bin-log日志、同步帐号

server-id = n #设置ID

log-bin #启用bin-log记录,如需要指定binlog文件名,可使用如下语法

#log-bin=binlog #binlog文件名为binlog.0,binlog.1……

set-variable=binlog-ignore-db=mysql #不记录数据库mysql的更新日志

binlog-do-db = #记录指定的数据库的更新日志,还可以单独处理只更新表内容

此外,需要注意两个环境变量:

innodb_flush_log_at_trx_commit=1 #Default: 1。在使用了事务的数据库中,强烈建议该值显式的设置为1,以确保在每个事务提交时,日志缓冲被写到日志文件,并将该写操作同步到磁盘上

sync_binlog=1 #在每进行1次binlog写操作后就将该操作同步到硬盘上。设为更高的值可以有效降低io并获得更好的性能,但会增加bilog丢失的风险

为从服务器上的同步帐号授权:

mysql>GRANT REPLICATION SLAVE ON *.* TO 同步帐号的用户名@从服务器ip地址 IDENTIFIED BY '同步帐号的密码';

如果想要从服务器上有权限执行”LOAD TABLE FROM MASTER”和”LOAD DATA FROM MASTER”还需要增加”FILE”和”SELECT”权限;

2.2 设置从服务器:设置需要同步的内容

server-id = n #设置ID

master-host = #设置主服务器的ip

master-user = #设置同步帐户的用户名

master-password = #设置(she4 zhi4)同步帐户的密码

master-port = #设置TCP/IP端口,默认为3306

set-variable=replicate-ignore-db=mysql #设置忽略的同步数据库名

set-variable=replicate-db-db= #设置同pass_adm步的数据库名若需要单独设置可以针对表级设置的数据多个,请设置多次

这里的设置可以在后面登陆进从数据库之后用CHANGE MASTER TO来修改。

2.3 拷贝主服务器数据到从服务器

2.3.1 方式1:停止(ting2 zhi3)主服务器或其中一台从服务器并拷贝数据

在需要拷贝数据的服务器上停止mysqld,完全停止服务。如果是从服务器,则需要在停止mysqld之前,停止同步进程。

mysql>stop slave;

$mysqladmin -uroot -p shutdown

确认mysqld停止之后,将其中的数据文件ib*,master.info需要同步的数据库目录和其他相关文件拷贝到新机器上。binlog和relay-log不用拷贝

2.3.2 方式2:在主服务器或其中一台从服务器上设置锁,禁止一切读写操作并拷贝数据

在主服务器上执行:

mysql>FLUSH TABLES WITH READ LOCK;

导出数据到从数据库(可以使用tar、scp、mysqldump等方式,此处实现比较灵活):

$cd ~/mysql/

$tar zcvf var.tar.gz var/ #数据目录可能不为var目录

然后是拷贝此var.tar.gz包到从服务器并解压缩到嫌う目录

在主服务器上执行:

mysql>UNLOCK TABLES;

说 明: 拷贝主服务器的数据到从服务器的实现方式太多:可以直接停止mysqld程序拷(cheng xu kao)贝数据、可以直接tar方式打包处理、可以直接scp方式处理、可以直接导出嫌う表结构等,具体实现方式看具体应用,适而择之,主要保证在拷贝数 据的时候没有数据写入和更改即可

2.4 启动同步

启动从数据库的mysqld推荐使用--skip-slave-start启动,进入mysql后再start slave启动同步。

说 明: 通常使用的mysqld_safe会记住启动时的参数,例如--skip-slva-start。如果从库因为意外原因重启,且该数据库启动的时候使用了 mysqld_safe --skip-slave-start,则需要手工启动同步进程,否则同步进程会始终处于停止状态

从服务器上执行:

mysql>SHOW SLAVE STATUS

若Slave_IO_Running 和 Slave_SQL_Running 两行的值都为 "Yes",这表明 Slave 的 I/O 和 SQL 线程都在正常运行。

说明: 推荐使用CHANGE MASTER TO 语句进行同步参数设置; 具体参照help change master to语法如下:

master_def:aster_def [ master_def] ...

master_def:

MASTER_HOST = 'host_name'

MASTER_USER = 'user_name'

MASTER_PASSWORD = 'password'

MASTER_PORT = port_num

MASTER_CONNECT_RETRY = count

MASTER_LOG_FILE = 'master_log_name'

MASTER_LOG_POS = master_log_pos

RELAY_LOG_FILE = 'relay_log_name'

RELAY_LOG_POS = relay_log_pos

MASTER_SSL =

MASTER_SSL_CA = 'ca_file_name'

MASTER_SSL_CAPATH = 'ca_directory_name'

MASTER_SSL_CERT = 'cert_file_name'

MASTER_SSL_KEY = 'key_file_name'

MASTER_SSL_CIPHER = 'cipher_list'

3 实例参考:

主数据库A的my.cnf配置:

server-id = 1 #设置ID

log-bin #启用bin-log记录

binlog-do-db = iknow #记录指定库的binlog更新记录,每个数据库一行

binlog-do-db = iknow_adm

binlog-do-db = ...

现在,新搭建一个从数据库B。需要进行如下步骤

1.修改配置文件: 修改my.cnf,加入如下项(_jia ru ru xia xiang):

server-id = 2 #指定server id,每台机器的id必须保证唯一

log-bin #启用binlog记录

master-connect-retry = 60 #连接主库的重试间隔

master-host = xxx.xxx.xxx.xxx #指定主库A的IP,不能用虚IP

master-port = 3306 #指定主库端口

master-user = rep #指定同步用户的用户名为(zhi ding tong bu yong hu de yong hu ming wei)replication

master-password = rep #指定同步用户的密码为PassWORd

replicate-do-db = iknow #指定需要同步的库,每个库独占一行

replicate-do-db = iknow_adm

replicate-do-db = ...

log-slave-updates #在从库上对同步进行日志记录,磁盘占用量较大,建议从库运行稳定后将其去除,如要作为第二层主数据库,则此项必须

这里的设置可以在后面登陆进从数据库之后用CHANGE MASTER TO来修改。

2.拷贝数据:从一台从数据库C拷贝数据到B 从数据库没有对外提供服(cong2 shu3 ju4 ku4 mei2 you3 dui4 wai4 ti2 gong1 fu2)务,因此可以直接停掉从数据库拷贝数据。

注意:

停 从数据库的时候(ting cong shu ju ku de shi hou)需要显式的执行stop slave,并执行show slave status,确认Read_Master_Log_Pos和Exec_Master_Log_Pos一致,再执行mysqladmin -uroot -p shutdown停掉mysqld。

mysql>stop slave;

mysql>show slave status

确认Read_Master_Log_Pos和Exec_Master_Log_Pos一致

$ mysqladmin -uroot -p shutdown

待mysqld完全退出后,将var目录下的ib*,master.info,以及需要同步的库cp到本地目录var.$DATE下(主要是为了缩短C上mysqld的服务停止时间)

$ cd $MYSQL/var; mkdir ../var.$DATE

$ cp -r ib* iknow iknow_adm master.info ../var.$DATE/

$ scp $MYSQL/var.$DATE B:~/mysql

3.在主数据库上为一台从库授权同步

mysql>GRANT REPLICATION SLAVE ON *.* TO replication@B机器的ip地址 IDENTIFIED BY 'Password;

4.在B上启动mysqld

$ mysqld_safe –-skip-slave-start &

5.进入mysql观察slave status

mysql> show slave status

6.观察master.info和relay-log.info

$ cat $MYSQL/master.info

$ cat $MYSQL/relay-log.info

在这里不需要change master一步是因为master.info中已记录了master_log_file和master_log_pos等相关信息。这是一种比较保险而且简单的办法

7.复查确认my.cnf中replication slave配置正确如果master.info文件存在的话,mysql是 优先读取它的,但在某些情况下,比如mysqld异常重启等,有可能会读取 my.cnf中配置,因此需要保证my.cnf中的replication slave配置正确 由于mysqld在正常情况下优先读取master.info,因此,在主数据库上一定要保证master.info是不存在的,否则可能出现不 (shi4 bu4 cun2 zai4 de0 _fou3 ze2 ke3 neng2 chu1 xian4 bu4)可预知的 后果。

8. CHANGE MASTER TO语句这是用于在mysql命令行中显式的更改主库的语句。在mysql命令行中执(ming ling xing zhong zhi)行

mysql> help change master to

可获得关于这条语句的详细信息。如果在进行主从数据库切换后,或需要临时更改主库,而又不想重启数据库的时候,可以使用如下语句动态的更改主库:

mysql> CHANGE MASTER TO MASTER_HOST=xxx.xxx.xxx.xxx MASTER_USER='replication' MASTER_PASSWORD='Password' MASTER_LOG_FILE='master-binlog.' MASTER_LOG_POS='';

以上语句各项含义如下:

MASTER_HOST主库的机器名或IP地址

MASTER_USER主库为从库授权的同步帐号

MASTER_PASSWORD主库为(zhu3 ku4 wei4)从库授权的同步帐号密码

MASTER_LOG_FILE主库的binlog文件名

MASTER_LOG_POS主库的binlog文件偏移(wen jian pian yi)

MASTER_LOG_FILE 和MASTER_LOG_POS两项需要在启动主库之(liang3 xiang4 xu1 yao4 zai4 qi3 dong4 zhu3 ku4 zhi1)前执行show master status记录下来,并且必须保证准确无误,否则会出现同步失败的情况。

4 FAQ

1. scp了整个var目录到新的从库(mu lu dao xin de cong ku),start slave后,发现同步(hou _fa xian tong bu)无法正常进行,Slave_IO_Running正常,但Slave_SQL_Running的状态为No,并且mysql错误日志中报找不到一个releylog文件

答:这是由于reley-log.info文件的存在造成的,它记录了数据库当前正在使用的relaylog,而mysql默 认的relaylog 命名是以机器名命名的,因此如果从一台机器拷贝到另一台机器,它是找不到这个文件的。如果可以确认Read_Master_Log_Pos和 Exec_Master_Log_Pos一致,那么可以直接将relay-log.info删除,重启mysqld,再start slave就可以解决。

2. start slave后, Slave_IO_Running和Slave_SQL_Running的状态都为No,并且日志中报类似“Slave I/O thread: Failed reading log event reconnecting to retry log 'tc-nsop-test00-bin.' position 08”的错误

答:这是由于主库对从库(da _zhe shi you yu zhu ku dui cong ku)的同步帐号授权不正确造成的,更改并确认授权正确之后,重新start slave,就可以正常同步。

3. 如果错误日志中出现如下提示“Warning: You should set server-id to a non-0 value if master_host is set; we force server id to 2 but this MySQL server will not act as a slave.”,并且 Slave_IO_Running和Slave_SQL_Running的状态都为No

答:检查主库的my.cnf,这样的错误是由于没有设置主库的server id或者server id不合法造成的。更改主库server id并重启主库后,start slave,同步可以恢复正常。

4. 如果Slave_SQL_Running状态为No,并且错误日志中有类似“Error 'Lock wait timeout exceeded; try restarting transaction' on query. Default database: ……”这样的错误

答:这是由于同步某个行的时候恰好遇到有其他SQL进程对该行进行了锁定,并且锁定时间较长导致同步进程等待超时。直接start slave即可。

5. 同时启动多台从库的同步进程对主库有什么影响

答:通常情况会导致主库的io和网卡流量增加。MySQL的Binlog Dump进程是没有限速的,因此会全速进行binlog读取和数据分发,给主库带来较大的负担。在实际操作中,尽量依次启动从库,并在启动后观察主库 io,确保Binlog Dump进程读取完binlog后,再启动下一台。