6.3. 复制实施细节
- 6.3.1. 复制主线程状态
- 6.3.2. 复制从I/O线程状态
- 6.3.3. 复制从SQL线程状态
- 6.3.4. 复制传递和状态文件
MySQL使用3个线程来执行复制功能(其中1个在主服务器上,另两个在从服务器上。当发出START SLAVE时,从服务器创建一个I/O线程,以连接主服务器并让它发送记录在其二进制日志中的语句。主服务器创建一个线程将二进制日志中的内容发送到从服务器。该线程可以识别为主服务器上SHOW PROCESSLIST的输出中的Binlog Dump线程。从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器数据目录中的本地文件中,即中继日志。第3个线程是SQL线程,是从服务器创建用于读取中继日志并执行日志中包含的更新。
在前面的描述中,每个从服务器有3个线程。有多个从服务器的主服务器创建为每个当前连接的从服务器创建一个线程;每个从服务器有自己的I/O和SQL线程。
这样读取和执行语句被分成两个独立的任务。如果语句执行较慢则语句读取任务没有慢下来。例如,如果从服务器有一段时间没有运行了,当从服务器启动时,其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.9节,“复制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_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开始。从服务器跟踪索引文件中目前正使用的中继日志。默认中继日志索引文件名为host_name-relay-bin.index。默认情况,在从服务器的数据目录中创建这些文件。可以用--relay-log和--relay-log-index服务器选项覆盖默认文件名。参见6.8节,“复制启动选项”。
中继日志与二进制日志的格式相同,并且可以用mysqlbinlog读取。SQL线程执行完中继日志中的所有事件并且不再需要之后,立即自动删除它。没有直接的删除中继日志的机制,因为SQL线程可以负责完成。然而,FLUSH LOGS可以循环中继日志,当SQL线程删除日志时会有影响。
在下面的条件下创建新的中继日志:
·每次I/O线程启动时创建一个新的中继日志。
·当日志被刷新时;例如,用FLUSH LOGS或mysqladmin flush-logs。
·当当前的中继日志文件变得太大时。“太大”含义的确定方法:
omax_relay_log_size,如果max_relay_log_size > 0
omax_binlog_size,如果max_relay_log_size = 0
从属复制服务器在数据目录中另外创建两个小文件。这些状态文件默认名为主master.info和relay-log.info。它们包含SHOW SLAVE STATUS语句的输出所显示的信息(关于该语句的描述参见13.6.2节,“用于控制从服务器的SQL语句”)。状态文件保存在硬盘上,从服务器关闭时不会丢失。下次从服务器启动时,读取这些文件以确定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。
由I/O线程更新master.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:
行 | 描述 |
1 | 文件中的行号 |
2 | Master_Log_File |
3 | Read_Master_Log_Pos |
4 | Master_Host |
5 | Master_User |
6 | 密码(不由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显示的列的对应关系为:
行 | 描述 |
1 | Relay_Log_File |
2 | Relay_Log_Pos |
3 | Relay_Master_Log_File |
4 | Exec_Master_Log_Pos |
当备份从服务器的数据时,你还应备份这两个小文件以及中继日志文件。它们用来在恢复从服务器的数据后继续进行复制。如果丢失了中继日志但仍然有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变量的值。