MySQL同步功能由3个线程(master上1个,slave上2个)来实现。执行 DE>START SLAVEDE> 语句后,slave就创建一个I/O线程。I/O线程连接到master上,并请求master发送二进制日志中的语句。master创建一个线程来把日志的内容发送到slave上。这个线程在master上执行 DE>SHOW PROCESSLISTDE> 语句后的结果中的 DE>Binlog DumpDE> 线程便是。slave上的I/O线程读取master的 DE>Binlog DumpDE> 线程发送的语句,并且把它们拷贝到其数据目录下的中继日志(relay logs)中。第三个是SQL线程,salve用它来读取中继日志,然后执行它们来更新数据。
如上所述,每个master/slave上都有3个线程。每个master上有多个线程,它为每个slave连接都创建一个线程,每个slave只有I/O和SQL线程。
show slave master 用于提供有关从属服务器线程的关键参数的信息
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.2.40
Master_User: photorepl
Master_Port: 4331
Connect_Retry: 60
Master_Log_File: mysql-bin.005502
Read_Master_Log_Pos: 64401238
Relay_Log_File: mysqld-relay-bin.015418
Relay_Log_Pos: 13456757
Relay_Master_Log_File: mysql-bin.005152
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table: photo.%
Replicate_Wild_Ignore_Table: mysql.%
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 13456620
Relay_Log_Space: 36764898503
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: 249904
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
SHOW SLAVE STATUS会返回以下字段:
? Slave_IO_State
SHOW PROCESSLIST输出的State字段的拷贝。SHOW PROCESSLIST用于从属I/O线程。如果线程正在试图连接到主服务器,正在等待来自主服务器的时间或正在连接到主服务器等,本语句会通知您
? Master_User
被用于连接主服务器的当前用户。
? Master_Port
当前的主服务器接口。
? Connect_Retry
–master-connect-retry选项的当前值
? Master_Log_File
I/O线程当前正在读取的主服务器二进制日志文件的名称。
? Read_Master_Log_Pos
在当前的主服务器二进制日志中,I/O线程已经读取的位置。
? Relay_Log_File
SQL线程当前正在读取和执行的中继日志文件的名称。
? Relay_Log_Pos
在当前的中继日志中,SQL线程已读取和执行的位置。
? Relay_Master_Log_File
由SQL线程执行的包含多数近期事件的主服务器二进制日志文件的名称。
? Slave_IO_Running
I/O线程是否被启动并成功地连接到主服务器上。
? Slave_SQL_Running
SQL线程是否被启动。
? Replicate_Do_DB,Replicate_Ignore_DB
使用–replicate-do-db和–replicate-ignore-db选项指定的数据库清单。
? Replicate_Do_Table,Replicate_Ignore_Table,Replicate_Wild_Do_Table,Replicate_Wild_Ignore_Table
使用–replicate-do-table,–replicate-ignore-table,–replicate-wild-do-table和–replicate-wild-ignore_table选项指定的表清单。
? Last_Errno,Last_Error
被多数最近被执行的查询返回的错误数量和错误消息。错误数量为0并且消息为空字符串意味着“没有错误”。如果Last_Error值不是空值,它也会在从属服务器的错误日志中作为消息显示。
举例说明:
Last_Errno: 1051
Last_Error: error ‘Unknown table ‘z” on query ‘drop table z’
该消息指示,表z曾经存在于在主服务器中并已被取消了,但是它没有在从属服务器中存在过,因此对于从属服务器,DROP TABLE失败。(举例说明,在设置复制时,如果您忘记了把此表拷贝到从属服务器中,则这有可能发生。)
? Skip_Counter
最近被使用的用于SQL_SLAVE_SKIP_COUNTER的值。
? Exec_Master_Log_Pos
来自主服务器的二进制日志的由SQL线程执行的上一个时间的位置(Relay_Master_Log_File)。在主服务器的二进制日志中的(Relay_Master_Log_File, Exec_Master_Log_Pos)对应于在中继日志中的(Relay_Log_File,Relay_Log_Pos)。
? Relay_Log_Space
所有原有的中继日志结合起来的总大小。
? Until_Condition,Until_Log_File,Until_Log_Pos
在START SLAVE语句的UNTIL子句中指定的值。
Until_Condition具有以下值:
o 如果没有指定UNTIL子句,则没有值
o 如果从属服务器正在读取,直到达到主服务器的二进制日志的给定位置为止,则值为Master
o 如果从属服务器正在读取,直到达到其中继日志的给定位置为止,则值为Relay
Until_Log_File和Until_Log_Pos用于指示日志文件名和位置值。日志文件名和位置值定义了SQL线程在哪个点中止执行。
? Master_SSL_Allowed,Master_SSL_CA_File,Master_SSL_CA_Path,Master_SSL_Cert,Master_SSL_Cipher,Master_SSL_Key
这些字段显示了被从属服务器使用的参数。这些参数用于连接主服务器。
Master_SSL_Allowed具有以下值:
o 如果允许对主服务器进行SSL连接,则值为Yes
o 如果不允许对主服务器进行SSL连接,则值为No
o 如果允许SSL连接,但是从属服务器没有让SSL支持被启用,则值为Ignored。
与SSL有关的字段的值对应于–master-ca,–master-capath,–master-cert,–master-cipher和–master-key选项的值。
? Seconds_Behind_Master
本字段是从属服务器“落后”多少的一个指示。当从属SQL线程正在运行时(处理更新),本字段为在主服务器上由此线程执行的最近的一个事件的时间标记开始,已经过的秒数。当此线程被从属服务器I/O线程赶上,并进入闲置状态,等待来自I/O线程的更多的事件时,本字段为零。总之,本字段测量从属服务器SQL线程和从属服务器I/O线程之间的时间差距,单位以秒计。
如果主服务器和从属服务器之间的网络连接较快,则从属服务器I/O线程会非常接近主服务器,所以本字段能够十分近似地指示,从属服务器SQL线程比主服务器落后多少。如果网络较慢,则这种指示不准确;从属SQL线程经常会赶上读取速度较慢地从属服务器I/O线程,因此,Seconds_Behind_Master经常显示值为0。即使I/O线程落后于主服务器时,也是如此。换句话说,本列只对速度快的网络有用。
即使主服务器和从属服务器不具有相同的时钟,时间差计算也会起作用(当从属服务器I/O线程启动时,计算时间差。并假定从此时以后,时间差保持不变)。如果从属SQL线程不运行,或者如果从属服务器I/O线程不运行或未与主服务器连接,则 Seconds_Behind_Master为NULL(意义为“未知”)。举例说明,如果在重新连接之前,从属服务器I/O线程休眠了master- connect-retry秒,则显示NULL,因为从属服务器不知道主服务器正在做什么,也不能有把握地说落后多少
MySQL复制的概述、安装、故障、技巧、工具
同MongoDB,Redis这样的NoSQL数据库的复制相比,MySQL复制显得相当复杂!接下来就是详细的介绍,相信下文中的内容对大家掌握MySQL数据库的复制是非常有帮助的。
概述
首先主服务器把数据变化记录到主日志,然后从服务器通过I/O线程读取主服务器上的主日志,并且把它写入到从服务器的中继日志中,接着SQL线程读取中继日志,并且在从服务器上重放,从而实现MySQL复制。具体如下图所示:
MySQL复制
整个过程反映到从服务器上,对应三套日志信息,可在从服务器上用如下命令查看:
mysql> SHOW SLAVE STATUS;
Master_Log_File & Read_Master_Log_Pos:下一个传输的主日志信息。
Relay_Master_Log_File & Exec_Master_Log_Pos:下一个执行的主日志信息。
Relay_Log_File & Relay_Log_Pos:下一个执行的中继日志信息。
理解这些日志信息的含义对于解决故障至关重要,后文会详细阐述。
安装
先在主服务器上创建复制账号:
mysql> GRANT REPLICATION SLAVE ON *.*
TO '<SLAVE_USER>'@'<SLAVE_HOST>'
IDENTIFIED BY '<SLAVE_PASSWORD>';
注:出于安全性和灵活性的考虑,不要把root等具有SUPER权限用户作为复制账号。
然后设置主服务器配置文件(缺省:/etc/my.cnf):
[mysqld]
server_id = 100
log_bin = mysql-bin
log_bin_index = mysql-bin.index
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1
innodb_support_xa = 1
注:一定要保证主从服务器各自的server_id唯一,避免冲突。
注:如果没有指定log_bin的话,缺省会使用主机名作为名字,如此一来一旦主机名发生改变,就会出问题,所以推荐指定log_bin(从服务器的relay_log存在一样的问题)。
注:sync_binlog,innodb_flush_log_at_trx_commit,innodb_support_xa三个选项都是出于安全目的设置的,不是复制的必须选项。
接着设置从服务器配置文件(缺省:/etc/my.cnf):
[mysqld]
server_id = 200
log_bin = mysql-bin
log_bin_index = mysql-bin.index
relay_log = mysql-relay-bin
relay_log_index = mysql-relay-bin.index
read_only = 1
skip_slave_start = 1
log_slave_updates = 1
注:如果用户有SUPER权限,则read_only无效。
注:有了skip_slave_start,除非使用START SLAVE命令,否则从服务器不会开始复制。
注:设置log_slave_updates,让从服务器记录日志,有助于在必要时把从切换成主。
下面最重要的步骤是如何克隆一份主服务器的数据:
如果数据库使用的是MyISAM表类型的话,可按如下方式操作:
shell> mysqldump --all-databases --master-data=1 > data.sql
注:master-data选项缺省会打开lock-all-tables,并写入CHANGE MASTER TO语句。
如果数据库使用的是InnoDB表类型的话,则应该使用single-transcation:
shell> mysqldump --all-databases --single-transaction --master-data=1 > data.sql
有了数据文件,传输到从服务器上并导入:
shell> mysql < data.sql
如果数据量很大的话,mysqldump会非常慢,此时直接拷贝数据文件能节省不少时间:
在拷贝之前要先锁定数据,然后再获得相关的日志信息(FILE & POSITION):
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
接下来拷贝数据文件时,如果是MyISAM表类型的话,直接拷贝即可;如果是InnoDB表类型的话,一定要先停止MySQL服务再拷贝,否则拷贝文件可能无法使用。把拷贝的数据文件直接复制到从服务器的数据目录。
最后还需要再指定一下日志信息:
mysql> CHANGE MASTER TO
MASTER_HOST='<MASTER_HOST>',
MASTER_USER='<SLAVE_USER>',
MASTER_PASSWORD='<SLAVE_PASSWORD>',
MASTER_LOG_FILE='<FILE>',
MASTER_LOG_POS=<POSITION>;
注:不要在my.cnf配置文件里设置MASTER_USER和MASTER_PASSWORD,因为最终生效的是CHANGE MASTER TO生成的master.info文件里的信息。
在主服务器上直接拷贝数据文件虽然很快,但需要锁表或者停止服务,这会影响线上服务。如果先前已经有了从服务器,那么可以用旧的从服务器做母本来克隆新的从服务器:
先在旧的从服务器上查询日志信息:
mysql> SHOW SLAVE STATUS;
我们需要的是其中的Relay_Master_Log_File & Exec_Master_Log_Pos。
然后在旧的从服务器上按照前面的方法得到数据,并在新的从服务器上还原。
接着在新的从服务器上设置日志信息:
mysql> CHANGE MASTER TO
MASTER_HOST='<MASTER_HOST>',
MASTER_USER='<SLAVE_USER>',
MASTER_PASSWORD='<SLAVE_PASSWORD>',
MASTER_LOG_FILE='<Relay_Master_Log_File>',
MASTER_LOG_POS=<Exec_Master_Log_Pos>;
不管用那个方法,最后记得在从服务器上启动复制,并检查工作是否正常:
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS;
如果IO线程和SQL线程都显示Yes,就可以感谢上帝了:
Slave_IO_Running 对应:Master_Log_File & Read_Master_Log_Pos
Slave_SQL_Running 对应:Relay_Master_Log_File & Exec_Master_Log_Pos
如果显示No,则说明前面某些配置步骤出错,或者对应的日志文件有问题。
故障
问题:主从复制不止何故停止了,我该怎么办?
答案:复制错误多半是因为日志错误引起的,所以首先要搞清楚是主日志错误还是中继日志错误,从错误信息里一般就能判断,如果不能可以使用类似下面的mysqlbinlog命令:
shell> mysqlbinlog <MASTER_BINLOG_FILE> > /dev/null
shell> mysqlbinlog <SLAVE_BINLOG_FILE> > /dev/null
如果没有错误,则不会有任何输出,反之如果有错误,则会显示出来。
如果是主日志错误,则需要在从服务器使用SET GLOBAL sql_slave_skip_counter,如下:
mysql> SET GLOBAL sql_slave_skip_counter = 1;
mysql> START SLAVE;
注:如果有多个错误,可能需要执行多次(提醒:主从服务器数据可能因此不一致)。
如果是中继日志错误,只要在从服务器使用SHOW SLAVE STATUS结果中的日志信息重新CHANGE MASTER TO即可,系统会抛弃当前的中继日志,重新下载:
mysql> CHANGE MASTER TO
MASTER_LOG_FILE='<Relay_Master_Log_File>',
MASTER_LOG_POS=<Exec_Master_Log_Pos>;
mysql> START SLAVE;
至于为什么使用的是Relay_Master_Log_File & Exec_Master_Log_Pos,参见概述。
问题:主服务器宕机了,如何把从服务器提升会主服务器?
答案:在一主多从的环境总,需选择数据最新的从服务器做新的主服务器。如下图所示:
提升从服务器为主服务器
在一主(Server1)两从(Server2,、Server3)的环境中,Server1宕机后,等到Server1和Server2把宕机前同步到的日志都执行完,比较Master_Log_File和Read_Master_Log_Pos就可以判断出谁快谁慢,因为Server2从 Server1同步的数据(1582)比Server3从Server1同步的数据(1493)新,所以应该提升Server2为新的主服务器,那么 Server3在CHANGE MASTER TO到Server2的时候应该使用什么样的参数呢?1582-1493=89,而Server2的最后的二进制日志位置是8167,所以答案是 8167-89=8078。
技巧
主从服务器中的表可以使用不同的表类型。比如主服务器可以使用InnoDB表类型,提供事务,行锁等高级特性,从服务器可以使用MyISAM表类型,内存消耗少,易备份等优点。还有一个例子,一台主服务器如果同时带很多个从服务器的话,势必会影响其性能,此时可以拿出一台服务器作为从服务器代理,使用BLACKHOLE表类型,只记录日志,不写数据,由它带多台从服务器,从而提升性能。
主从服务器中的表可以使用不同的键类型。比如主服务器用InnoDB,键用VARCHAR的话节省空间,从服务器使用MyISAM,键用CHAR提高速度,因为MyISAM有静态表一说。
主从服务器中的表可以使用不同的索引。主服务器主要用来应付写操作,所以除了主键和唯一索引等保证数据关系的索引一般都可以不加,从服务器一般用来应付读操作,所以可以针对查询特征设置索引,再进一步,不同的从服务器可以针对不同的查询设置不同的索引。
工具
有一些优秀的工具可以让你的复制工作得到事半功倍的效果,详细内容请参考各自文档:
Multi-Master Replication Manager for MySQL
Percona XtraBackup
Maatkit
Tungsten-replicator
本文转载自: http://zhumeng8337797.blog.163.com/blog/static/10076891420115732244591/