第6章:MySQL中的复制
6.1.
复制介绍
MySQL
支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。
(
这与同步复制可以进行对比,同步复制是
MySQL
簇的一个特征―参见第
15
章:
MySQL
簇)。在单个主服务器复制时
,
这个主将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志记录要发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。
如果你想要设置链式复制服务器,从服务器本身也可以充当主服务器。
多个主复制时可能的
,
但是会出现在单个主复制中不会发生的问题
.
查看
6.13, “Auto-Increment in Multiple-Master Replication”.
请注意当你进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,以避免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。
6.2.
复制实施概述
MySQL
复制基于主服务器在二进制日志中跟踪所有对数据库的更改
(
更新、删除等等
)
。因此,要进行复制,必须在主服务器上启用二进制日志。参见
5.11.3
节,“二进制日志”。
每个从服务器从主服务器接收主服务器已经记录到其二进制日志的保存的更新,以便从服务器可以对其数据拷贝执行相同的更新。
认识到二进制日志只是一个从启用二进制日志的固定时间点开始的记录非常重要。任何设置的从服务器需要主服务器上的在主服务器上启用二进制日志时的数据库拷贝。如果启动从服务器时,其数据库与主服务器上的启动二进制日志时的状态不相同,从服务器很可能失败。
从服务器设置为复制主服务器的数据后,它连接主服务器并等待更新过程。如果主服务器失败,或者从服务器失去与主服务器之间的连接,从服务器保持定期尝试连接,直到它能够继续帧听更新。由
--master-connect-retry
选项控制重试间隔。
默认为
60
秒。
每个从服务器跟踪上一次他从主服务器的复制时间和更新的地方。主服务器不知道有多少个从服务器或在某一时刻有哪些被更新了。
6.3.
复制实施细节
MySQL
使用
3
个线程来执行复制功能
(
其中
1
个在主服务器上,另两个在从服务器上。当
(
从服务器
)
发出
START SLAVE
时,从服务器创建一个
I/O
线程,以连接主服务器并让它发送记录在其二进制日志中的语句。主服务器创建一个线程将二进制日志中的内容发送到从服务器。该线程可以识别为主服务器上
SHOW PROCESSLIST
的输出中的
Binlog Dump
线程。从服务器
I/O
线程读取主服务器
Binlog Dump
线程发送的内容并将该数据拷贝到从服务器数据目录中的本地文件中,即中继日志
relay logs
。第
3
个线程是
SQL
线程,是从服务器创建用于读取中继日志并执行日志中包含的更新。
在前面的描述中,每个主
/
从的连接有
3
个线程。有多个从服务器的主服务器创建为每个当前连接的从服务器创建一个线程;每个从服务器有自己的
I/O
和
SQL
线程。
从服务器有两个线程
,
所以从主读取更新和执行它们可以被划分为两个独立的工作
.
当执行的工作慢的时候并不会使读的工作变慢
.
如果从服务器在
SQL
线程执行完所有索取的语句前停止,
I/O
线程至少已经索取了所有内容,以便语句的安全拷贝保存到本地从服务器的中继日志中,供从服务器下次启动时执行。这样允许清空主服务器上的二进制日志,因为不再需要等候从服务器来索取其内容。
SHOW PROCESSLIST
语句可以提供在主服务器上和从服务器上发生的关于复制的信息。
下面的例子说明了这
3
个线程在
SHOW PROCESSLIST
中的显示。
在主服务器上,
SHOW PROCESSLIST的输出看上去应为:
mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 2
User: root
Host: localhost:32931
db: NULL
Command: Binlog Dump
Time: 94
State: Has sent all binlog to slave; waiting for binlog to
be updated
Info: NULL
这儿,线程
2是一个连接从服务器的复制线程。该信息表示所有主要更新已经被发送到从服务器,主服务器正等待更多的更新出现。
在从服务器上,
SHOW PROCESSLIST的输出看上去应为:
mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 10
User: system user
Host:
db: NULL
Command: Connect
Time: 11
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 11
User: system user
Host:
db: NULL
Command: Connect
Time: 11
State: Has read all relay log; waiting for the slave I/O
thread to update it
Info: NULL
该信息表示线程
10是同主服务器通信的
I/O线程,线程
11是处理保存在中继日志中的更新的
SQL线程。
SHOW PROCESSLIST运行时,两个线程均空闲,等待其它更新。
请注意
Time列的值可以显示从服务器比主服务器滞后多长时间。参见
6.10节,“复制FAQ”。
6.3.1.
复制主线程状态
下面列出了主服务器的
Binlog Dump
线程的
State
列的最常见的状态。如果你没有在主服务器上看见任何
Binlog Dump
线程,这说明复制没有在运行―即,目前没有连接任何从服务器。
・
Sending binlog event to slave
二进制日志由各种事件组成,一个事件通常为一个更新加一些其它信息。线程已经从二进制日志读取了一个事件并且正将它发送到从服务器。
・
Finished reading one binlog; switching to next binlog
线程已经读完二进制日志文件并且正打开下一个要发送到从服务器的日志文件。
・
Has sent all binlog to slave; waiting for binlog to be updated
线程已经从二进制日志读取所有主要的更新并已经发送到了从服务器。线程现在正空闲,等待由主服务器上新的更新导致的出现在二进制日志中的新事件。
・
Waiting to finalize termination
线程停止时发生的一个很简单的状态。
6.3.2.
复制从
I/O
线程状态
下面列出了从服务器的
I/O
线程的
State
列的最常见的状态。该状态也出现在
Slave_IO_State
列,由
SHOW SLAVE STATUS
显示。这说明你可以只通过该语句仔细浏览所发生的事情。
・
Connecting to master
线程正试图连接主服务器。
・
Checking master version
建立同主服务器之间的连接后立即临时出现的状态。
・
Registering slave on master
建立同主服务器之间的连接后立即临时出现的状态。
・
Requesting binlog dump
建立同主服务器之间的连接后立即临时出现的状态。线程向主服务器发送一条请求,索取从请求的二进制日志文件名和位置开始的二进制日志的内容。
・
Waiting to reconnect after a failed binlog dump request
如果二进制日志转储请求失败
(
由于没有连接
)
,线程进入睡眠状态,然后定期尝试重新连接。可以使用
--master-connect-retry
选项指定重试之间的间隔。
・
Reconnecting after a failed binlog dump request
线程正尝试重新连接主服务器。
・
Waiting for master to send event
线程已经连接上主服务器,正等待二进制日志事件到达。如果主服务器正空闲,会持续较长的时间。如果等待持续
slave_net_timeout (
注
:5.1
里面写的是
slave_read_timeout)
秒,则发生超时。此时,线程认为连接被中断并企图重新连接。
・
Queueing master event to the relay log
线程已经读取一个事件,正将它复制到中继日志供
SQL
线程来处理。
・
Waiting to reconnect after a failed master event read
读取时
(
由于没有连接
)
出现错误。线程企图重新连接前将睡眠
master-connect-retry
秒。
・
Reconnecting after a failed master event read
线程正尝试重新连接主服务器。当连接重新建立后,状态变为
Waiting for master to send event
。
・
Waiting for the slave SQL thread to free enough relay log space
正使用一个非零
relay_log_space_limit
值,中继日志已经增长到其组合大小超过该值。
I/O
线程正等待直到
SQL
线程处理中继日志内容并删除部分中继日志文件来释放足够的空间。
・
Waiting for slave mutex on exit
线程停止时发生的一个很简单的状态。
6.3.3.
复制从
SQL
线程状态
下面列出了从服务器的
SQL
线程的
State
列的最常见的状态。
・
Reading event from the relay log
线程已经从中继日志读取一个事件,可以对事件进行处理了。
・
Has read all relay log; waiting for the slave I/O thread to update it
线程已经处理了中继日志文件中的所有事件,现在正等待
I/O
线程将新事件写入中继日志。
・
Waiting for slave mutex on exit
线程停止时发生的一个很简单的状态。
I/O
线程的
State
列也可以显示语句的文本。这说明线程已经从中继日志读取了一个事件,从中提取了语句,并且正在执行语句。
6.3.4.
复制传递和状态文件
默认情况,中继日志使用
host_name-relay-bin.nnnnnn
形式的文件名,其中
host_name
是从服务器主机名,
nnnnnn
是序列号。用连续序列号来创建连续中继日志文件,从
000001
开始。从服务器运用一个索引文件来跟踪当前正在用的中继日志文件
(relay log files).
默认的这个中继日志索引文件名称为
host_name-relay-bin.index.
默认情况,在从服务器的数据目录中创建这些
relay log
文件。可以用
--relay-log
和
--relay-log-index
服务器选项覆盖默认文件名
(
也就是重新指认文件名
)
。参见
6.8
节,“复制启动选项”。
中继日志与二进制日志的格式相同,并且可以用
mysqlbinlog
读取。
SQL
线程执行完中继日志中的所有事件并且不再需要之后,立即自动删除它。没有直接的删除中继日志的机制,因为
SQL
线程可以负责完成。然而,
FLUSH LOGS
可以循环
(rotate)
中继日志,当
SQL
线程删除日志时会有影响。
从服务器在以下情况下会创建一个新的中继日志文件
:
・
每次
I/O
线程启动时
・
当日志被刷新时;例如,用
FLUSH LOGS
或
mysqladmin flush-logs
。
・
当当前的中继日志文件变得太大时。“太大”含义的确定方法:
o max_relay_log_size
,如果
max_relay_log_size > 0
o max_binlog_size
,如果
max_relay_log_size = 0
从属复制服务器在数据目录中另外创建两个小文件。这些状态文件默认名为
master.info
和
relay-log.info
。他们的名字可以被改变
,
通过用
--master-info-file
和
--relay-log-info-file
选项
.
查阅
Section 6.8,
“
Replication Startup Options
”
.
因为这些状态文件保存在硬盘上
,
所以从服务器关闭时不会丢失。下次从服务器启动时,读取这些文件以确定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。
由
I/O
线程更新
master.info
文件。文件中的行和
SHOW SLAVE STATUS
显示的列的对应关系为:
Line
|
Description
|
1
|
Number of lines in the file
(文件中行的数量?)
|
2
|
Master_Log_File
|
3
|
Read_Master_Log_Pos
|
4
|
Master_Host
|
5
|
Master_User
|
6
|
Password (not shown by
SHOW SLAVE STATUS
)
|
7
|
Master_Port
|
8
|
Connect_Retry
|
9
|
Master_SSL_Allowed
|
10
|
Master_SSL_CA_File
|
11
|
Master_SSL_CA_Path
|
12
|
Master_SSL_Cert
|
13
|
Master_SSL_Cipher
|
14
|
Master_SSL_Key
|
由
SQL线程更新
relay-log.info文件。文件中的行和
SHOW SLAVE STATUS显示的列的对应关系为:
Line
|
Description
|
1
|
Relay_Log_File
|
2
|
Relay_Log_Pos
|
3
|
Relay_Master_Log_File
|
4
|
Exec_Master_Log_Pos
|
The contents of the
relay-log.info
file and the states shown by the
SHOW SLAVE STATES
command may not match if the
relay-log.info
file has not been flushed to disk. Ideally, you should only view
relay-log.info
on a slave that is offline (i.e.
mysqld
is not running). For a running system,
SHOW SLAVE STATUS
should be used.
当备份从服务器的数据时,你还应备份这两个小文件以及中继日志文件。它们用来在恢复从服务器的数据后继续进行复制。如果丢失了中继日志但仍然有
relay-log.info文件,你可以通过检查该文件来确定
SQL线程已经执行的主服务器中二进制日志的程度。然后可以用
Master_Log_File和
Master_LOG_POS选项执行
CHANGE MASTER TO来告诉从服务器重新从该点读取二进制日志。当然,要求二进制日志仍然在主服务器上。
如果从服务器正复制
LOAD DATA INFILE
语句,你应也备份该目录内从服务器用于该目的的任何
SQL_LOAD-*
文件。从服务器需要这些文件继续复制任何中断的
LOAD DATA INFILE
操作。用
--slave-load-tmpdir
选项来指定目录的位置。如果未指定,
默认值为
tmpdir
变量的值。