"高可用MySQL"学习笔记-深入复制
复制系统系统中,从master到slave的事件流如下:
1、会话接收来自客户端的语句并执行这个语句,并与其他会话保持同步,保证每个事件的执行不与其他会话的更新发生冲突。
2、语句执行结束之前,向二进制日志写入一条记录。
3、事件写入二进制日志后,master的转储线程(dump thread)从二进制日志中读取事件,然后将他们发送给slave的I/O线程。
4、slave的I/O线程接收到该事件时,将它写入中继日志(relay log)的末尾。
5、写入中继日志后,salve的SQL线程从中继日志中读取事件并执行,从而在slave的数据库应用这些更新。
中继日志充当缓冲,这样master不必等待salve执行完就可以发送下一个事件。中继日志除了二进制日志中的内容文件和索引文件外,中继日志还维护两个文件来跟踪复制进度,即中继日志信息文件和master日志信息文件。reset slave会删除这两个文件。master.info文件中的优先级高于my.cnf,如果改变my.cnf信息然后重启slave,会从master.info读取而不是my.cnf,所以chang master命令不放在my.cnf文件中。
master.info里面包含master的读位置,以及连接master和启动复制必需的所有信息。当I/O线程启动时,如果有这个文件,则线程从这个文件读取信息。 master.info文件中记录的密码没有加密,为了保护文件,服务器上定义了专门的用户来运行服务,将复制和数据库维护的所有文件都交给这个用户,只有这个用户对这些文件具备读写权限。。其他用户不能访问。
relay-log.info文件跟踪复制的进度,并由SQL线程负责更新。如果某些文件不可用,在slave启动时,能够根据my.cnf和chang master的参数,重建这些文件。
复制线程
master转储线程,每个连接到master的slave都有一个转储线程。
slave I/O线程,负责连接master并请求master上的更新转储到中继日志,以便SQL线程进一步处理。一旦建立,I/O线程就一直存在,这样salve能够立即收到master的所有更新。
salve SQL线程,读取中继日志的更新,然后在slave上应用这些更新,这个线程负责协调其他mysql线程,保证这些更新不与mysql服务器上的其他活动产生冲突。
从master角度来说,I/O线程是能够在master上执行转储和SQL语句的客户端线程,客户端连接到服务器像slave一样请求master转储二进制日志的更新,mysqlbinlog程序的原理。
服务器启动时,如存在master.info,还会启动slave线程。服务器做了复制配置,start salve命令启动线程并创建master.info。I/O线程从master.info文件读取最后读位置进行恢复,在写时间时,I/O线程也会轮换(rotate)中继日志。SQL线程从relay-log.info文件读取中继日志位置进行恢复。
start slave io_thread、 stop slave io_thread启动停止i/o线程。
start slave sql_thread、 stop slave sql_thread启动停止SQL线程。
停止slave线程时,复制的当前状态将保存到master.info和relay-log.info文件中,然后salve线程再次启动时读取这些信息。
通过Intenet运行复制
分隔两地的数据中心进行复制,作为内容分发网络,提高响应速度。但开放的internet上master发给slave的事件总是不安全的,需要加密来保护信息不被窃取。internet上传输一般使用SSL进行加密。 1、可以使用内置的加密支持,对master到slave的复制进行加密/2、对于不支持SSL的程序,使用Stunel程序建立一个SSL隧道(其实是虚拟的私有网络)。3、在隧道模式下(tunel model)使用SSH。
内置支持建立安全链接。openssl生成自签名的公有证书及其私有秘钥,master配置为支持SSL,需要向my.cnf文件添加参数。ssl-capath提供了可信CA证书所在的目录文件名,ssl-cert给出了服务器证书的文件名,ssl-key提供服务器私有秘钥的文件名。也需要配置slave也能使用SSL,change master命令需要带参数MASTER_SSL_CAPATH、MASTER_SSL_CERT、MASTER_SSL_KEY。
使用stunnel建立安全复制。stunnel是一个简单易用的SSL隧道应用,可以配置为SSL服务器或者SSL客户端。这个比内置支持需要更多的配置,如果服务器不支持SSL编译,或加密解密的额外处理从mysql服务器分离出去,这个方法非常有用。需要配置/etc/stunnel/master.conf和/etc/stunnel/slave.conf。
复制状态
show slave hosts;列出master和slave的信息。show master logs;查看master的二进制日志文件。 show master status;给出下个事件即将写入二进制日志的位置,与show master logs命令的最后一行匹配。show slave status;查看slave线程的状态,几乎包含了复制状态的所有信息。
salve-IO-state描述了当前正在运行的IO线程的状态,消息变化状态有:等地master更新、连接master、在master上注册salve、请求binlog转储、等待master发送事件、master事件排队写入中继日志等等。
断开连接的选项
error connecting to master 'sync@192.168.31.76:3306 ' - retry-time: 60 maximum-retries: 86400 message: Can't connect to MySQL server on '192.168.31.76' (101 "Network is unreachable")。 retry-time和maximum-retries。当master断开后,salve的状态。还有一个参数是slave-net-timout,可以接受的无响应时间,超过这个时间slave认为master连接丢失并重新开始连接,但是重新连接受前两个参数限制。

slave如何处理事件
复制的核心是日志事件。二进制日志在master上是按照事务提交顺序记录的,事务在master上是多线程的,在salve上是以单线程执行。如果在master上提交了很多事务,slave就难以与maaster保持同步。master上有些语句是特定于会话的,在slave上单线程执行可能产生不同的结果,因为用户变量、临时表、有些函数是特定于会话的。二进制日志决定了执行顺序。
管理IO线程
sql线程真正执行前,io线程根据某些字节判断事件的类型,然后对中继日志采取必要的行动:
1、停止事件,表明salve链中的下一个服务器被有序执行,IO线程忽略这个事件,不把这个事件写入中继日志。
2、轮换事件,如果master日志轮换,那么中继日志也会被轮换,中继日志轮换次数可能比master多,但是每次master轮换时,中继日志也要被轮换。
3、格式描述事件,中继日志轮换时保存该事件。
如果是环形复制或者双主复制,事件将在环中传达下去直到到达最初发送给他们的那个服务器,为了避免在环中无休止的复制,每个服务器需要检查事件是否包含该服务器本身的ID。如果有,说明就是这个服务器发送的,已经在环上复制一圈。为了避免无限复制,不把这个事件写入中继日志,直接忽略它。设置replicate-same-server-id可以关闭这种检查,事件都会写入中继日志。
SQL线程处理
sql线程读取中继日志,然后在salve上重新执行master的数据库语句。 有些事件还需要sql语句以外的特殊信息。1、master的上下文发给salve;2、处理不同线程的事件,master执行的事务来自多个会话,slave线程必须知道事件是哪个线程产生的,master会标记那些线程特定的事件。3、过滤事件和表;4、跳过事件。
半同步复制
半同步复制事务原理是在复制继续运行之前,确保至少有一个slave将变更写到磁盘,也就是说对于每个连接来说,如果master发生故障,至多有一个事务丢失。半同步复制不会阻止事务提交,而是直到事务至少写入一个slave中继日志才向客户端发送响应。
半同步复制需要安装插件,mariadb默认安装了。需要配置参数为ON。

为了防止半同步复制收不到确认被阻塞,timeout可以配合超时设置,在timeout后仍收不到任何确认,就还原为常规的异步复制继续操作,不再使用半同步复制。
全局事务标识符GTID
mysql5.6开始,引入全局事务标识符,即每个事务都有一个唯一的标识符,64位的非零数值,根据事务提交的顺序分配。但是这个值是服务器本地的,要使事务标识符称为全局的,还要加上UUID构成一对。
启用gtid,gtid-mode=ON用来生成全局事务标识符。log-salve-update,保证master上已经执行的事件同样写入备用服务器的日志。全局事务配置后,change master不需要填写二进制日志位置和文件,会自动协商应该发送什么事务。
使用全局事务标识符切换到热备份很简单,change master to madter_host="standby.host.ip",不需要提供位置。
使用GTID提升slave
如果master有多个slave,master失效后就要比较这些salve,看看“谁知道的多” 。
(未完待续)