# 一.mysql主从备份(复制)的基本原理
mysql支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。mysql复制基于主服务器在二进制日志中跟踪所有对数据库的更改(更新、删除等等)。因此,要进行复制,必须在主服务器上启用二进制日志。每个从服务器从主服务器接收主服务器已经记录到其二进制日志的保存的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,并在本机上执行相同的更新。然后封锁并等待主服务器通知新的更新。从服务器执行备份不会干扰主服务器,在备份过程中主服务器可以继续处理更新。
# 二.mysql主从备份配置方法
>[danger]**在进行mysql主从备份时,最好确保主从服务器的版本兼容。从服务器至少与主服务器版本相同或更高。**
## 2.1、主机(master)配置:
### 1.修改mysql配置文件my.cnf
>[danger]`vi /etc/my.conf`;
在[mysqld]标签下添加以下几行
>[warning]log-bin=mysql-bin #开启二进制日志
server-id=id #主服务器id号
binlog-do-db=db_nameA #指定对db_nameA记录二进制日志
binlog-ignore-db=db_namB #指定不对db_namB记录二进制日志
我们现在的配置是
~~~
log-bin=mysql-bin
server-id = 1
binlog-do-db=test
~~~
### 2.为从服务器添加mysql账户并配置权限
在主服务器上,必须为从服务器创建一个用来连接主服务器的用户,并设置replication slave权限。所用具体命令如下:
>[warning]`grant replication slave on *.* to '帐号' @ '从服务器IP' identified by '密码';`
其中服务器地址可以写成通配符的形式
现在我的代码是
>[danger]`grant replication slave on *.* to 'ncgis'@'%' identified by 'ncgis';`
登录mysql数据库 (mysql -uroot -p)
进入数据库mysql(use mysql)
查询
>[danger]`select * from user where user = 'ncgis' \G; `
出现一下结果
~~~
*************************** 1. row ***************************
Host: %
User: ncgis
Password: *9EAEAC24C4B6C98D611B4E95A4EE54F86904B538
Select_priv: N
Insert_priv: N
Update_priv: N
Delete_priv: N
Create_priv: N
Drop_priv: N
Reload_priv: N
Shutdown_priv: N
Process_priv: N
File_priv: N
Grant_priv: N
References_priv: N
Index_priv: N
Alter_priv: N
Show_db_priv: N
Super_priv: N
Create_tmp_table_priv: N
Lock_tables_priv: N
Execute_priv: N
Repl_slave_priv: Y
Repl_client_priv: N
Create_view_priv: N
Show_view_priv: N
Create_routine_priv: N
Alter_routine_priv: N
Create_user_priv: N
Event_priv: N
Trigger_priv: N
Create_tablespace_priv: N
ssl_type:
ssl_cipher:
x509_issuer:
x509_subject:
max_questions: 0
max_updates: 0
max_connections: 0
max_user_connections: 0
plugin: mysql_native_password
authentication_string:
password_expired: N
1 row in set (0.00 sec)
~~~
可以看到Repl_slave_priv项对就的值为Y。
###3、导出主服务器的数据
>[danger]`mysqldump test>test.bak`
### 4.查询记录File 及Position 项的值
>[danger]`show master status\G;`
得到的结果如下
~~~
*************************** 1. row ***************************
File: mysql-bin.000013
Position: 944
Binlog_Do_DB: test
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
~~~
从新启动服务器
>[danger]~~~
service mysql stop
service mysql start
~~~
或者
>[danger]`service mysql reload (推荐试使用)`
## 2、2从服务器配置
### 1.修改mysql配置文件my.cnf
在[mysqld]标签下添加以下面一行:
>[danger]`server-id=id #从机id `
实际中,我们添加:
>[danger]`server-id=2`
### 2、导入数据:
>[danger]`mysql test < test.bak `
### 3.重启mysql数据库并设置相关参数
>[danger]change master to
master_host = '主服务器的地址',
master_user = '使用的账号',
master_password = '密码',
master_log_file = 'file值',
master_log_pos = position值;
slave start;
我们的代码是(此处的file值和position值请查看主服务器配置的第四步查询出来的值)
>[danger]change master to
master_host = '192.168.10.105',
master_user = 'ncgis',
master_password = 'ncgis',
master_log_file = 'mysql-bin.000013',
master_log_pos = 944;
slave start;
### 4.检查数据库查看相关参数
执行
>[danger]service mysql reload
重启后进入mysql
执行
>[danger]show slave status \G;
我们查看到的结果是
`
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.105
Master_User: ncgis
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000013
Read_Master_Log_Pos: 944
Relay_Log_File: localhost-relay-bin.000003
Relay_Log_Pos: 1107
Relay_Master_Log_File: mysql-bin.000013
Slave_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: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 944
Relay_Log_Space: 1284
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_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
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: b9d68e0d-6cca-11e5-92f0-000c2935acaa
Master_Info_File: /usr/local/mysql/var/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
1 row in set (0.00 sec)
`
对部分参数的解释:
>[danger]Slave_IO_State: Waiting for master to send event
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
以上参数说听slave正常运行,正等待主服务器发来的消息。此时若用netstate命令可以看到从机与主机间已经建立了一条链接接。
特别需要注意的两个参数是:
>[danger]Master_Log_File代表主机上用于主备同步的日志文件名
Read_Master_Log_Pos代表上一次成功同步到的日志文件中的位置。
如果这两项与先前在主服务器上看到的File及Position的值不相符,则无法正确进行同步。
如果 Slave_IO_Running: 显示在连接中
Slave_SQL_Running: Yes 这种状态的话 主要是网络不通 需要检查一下防火墙
# 三.主从备份的实现细节
mysql使用3个线程来执行复制功能(其中1个在主服务器上,另两个在从服务器上)。当发出start slave时,从服务器创建一个I/O线程,以连接主服务器并让它发送记录在其二进制日志中的语句。主服务器创建一个线程将二进制日志中的内容发送到从服务器。该线程可以即为主服务器上show processlist输出中的Binlog Dump线程。从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器数据目录中的本地文件中,即中继日志。第3个线程是sql线程,由从服务器创建,用于读取中继日志并执行日志中包含的更新。在从服务器上,读取和执行更新语句被分成两个独立的任务。当从服务器启动时,其I/O线程可以很快地从主服务器索取所有二进制日志内容。
![](https://box.kancloud.cn/2015-11-06_563c4ad5177e9.JPG)
## 1.复制线程状态
通过show slave status\G和show master status可以查看复制线程状态。常见的线程状态有:
### (1)主服务器Binlog Dump线程
Has sent all binlog to slave; waiting for binlog to be updated
线程已经从二进制日志读取所有主要的更新并已经发送到了从服务器。线程现在正空闲,等待由主服务器上新的更新导致的出现在二进制日志中的新事件。
### (2)从服务器I/O线程状态
Waiting for master to send event
线程已经连接上主服务器,正等待二进制日志事件到达。如果主服务器正空闲,会持续较长的时间。如果等待持续slave_read_timeout秒,则发生超时。此时,线程认为连接被中断并企图重新连接。
### (3)从服务器SQL线程状态
Reading event from the relay log
线程已经从中继日志读取一个事件,可以对事件进行处理了。
Has read all relay log; waiting for the slave I/O thread to update it
线程已经处理了中继日志文件中的所有事件,现在正等待I/O线程将新事件写入中继日志。
## 2.复制过程中使用的传递和状态文件
默认情况,中继日志使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是从服务器主机名,nnnnnn是序列号。中继日志与二进制日志的格式相同,并且可以用mysqlbinlog读取。
从服务器在data目录中另外创建两个小文件。这些状态文件默认名为主master.info和relay-log.info。状态文件保存在硬盘上,从服务器关闭时不会丢失。下次从服务器启动时,读取这些文件以确定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。
## 附录1
关于log_bin日志
my.conf 文件中的[mysqld]标签下的log_bin指定日志文件,如果不提供文件名,mysql将自己产生缺省文件名。mysql会在文件名后面自动添加数字引,每次启动服务时,都会重新生成一个新的二进制文件。此外,使用log-bin-index可以指定索引文件;使用binlog-do-db可以指定记录的数据库;使用binlog-ignore-db可以指定不记录的数据库。注意的是:binlog-do-db和binlog-ignore-db一次只指定一个数据库,指定多个数据库需要多个语句。而且,MySQL会将所有的数据库名称改成小写,在指定数据库时必须全部使用小写名字,否则不会起作用。
以后对数据库每做的一次操作,都会在binlog中有所记录。