复制的原理
对于主库中的二进制日志同步到从库时发起请求的方向: 二进制日志的同步,既有从库主动请求的情况,也有主库主动推送的情况。 (1)对于复制线程在主从之间新建立连接或重新建立的情况,因为这时候主库并不知道需要发送哪些二进制日志给新建立连接的从库, 从库向主库注册连接时,携带了从库二进制的位置信息,所以是从库主动向主库请求所需的二进制日志。 (2)对于复制线程已经在主从之间建立连接,而且从库已经完全接收建立连接时请求的二进制日志内容, 这时主库随时都可能写入新的内容,从库难以及时感知,后续的增量二进制日志是由主库主动推送给从库的。 复制的原理: (1)用户提交对数据的修改,然后主库把所有数据库变更写进二进制日志,主库通过Binlog Dump线程把二进制日志内容推送给从库, 从库被动接受数据,不是主动去获取,除非是新建连接。 (1.1)从库正常连接主库时,在主库中使用SHOW PROCESSLIST语句可以查看到标识为"Binlog Dump"的线程。 (1.2)"Binlog Dump"线程在读取二进制日志中要发送到从库的每个事件时,会获取二进制日志上的锁。 一旦读取完事件,即使事件还未发送到从库,二进制日志上的锁也会被释放。 (2)在从库执行START SLAVE语句时,已经使用CHANGE MASTER TO语句配置好复制信息,从库会创建一个I/O线程。 该线程连接到主库并请求为其发送所需的二进制日志(从库向主库连接时,里面携带了请求二进制日志的位置, 该位置表示从库所请求的二进制日志的起点)。 (2.1)从库I/O线程与主库的Binlog Dump线程成功建立连接之后,从库I/O线程接收主库Binlog Dump线程发送的二进制日志, 并将他们写入从库本地的Relay Log。 (2.2)I/O线程的状态可以通过SHOW SLAVE STATUS语句输出的Slave_IO_running字段查看, 或者通过SHOW STATUS语句输出的Slave_running状态查看(该状态变量在MySQL5.7中已启用,MySQL8.0已将其移除。 (3)从库SQL线程读取并解析中继日志中的内容,按照读取的顺序进行回放(二进制日志中存放的事务顺序就是主库中事务的提交顺序), 并将数据变更写入本地数据文件中,这样就实现了数据在主从之间的同步。 每一对主从关系中,都有三个线程。 主库可以连接多个从库,而且会为每一个连接成功的从库创建一个Binlog Dump线程。 从库也可以连接多个主库(多源复制),而且会为每一个连接成功的主库创建自己的I/O线程和SQL线程。 从库使用两个线程分别将主库的二进制日志读取到本地,并应用这些日志以实现主从之间的数据同步。 因此,即使SQL线程执行语句缓慢,也不会影响I/O线程读取日志的速度,正常情况下I/O线程不会成为性能瓶颈,除非网络出现问题。 如果SQL线程已经应用完所有中继日志,就表明I/O线程已经获取了主库中所有的二进制日志。 主库:Id 为 841261 的线程就是 Binlog Dump,如下所示: root@localhost [(none)]> show processlist\G Id: 841261 User: repl Host: 10.10.10.137:57816 db: NULL Command: Binlog Dump Time: 1050683 State: Master has sent all binlog to slave; waiting for more updates Info: NULL 从库:Id 为 1 的线程就是 SQL 线程,Id 为 2 的线程就是 I/O 线程: root@localhost [(none)]> show processlist\G *************************** 1. row *************************** Id: 1 User: system user Host: db: NULL Command: Connect Time: 21 State: Slave has read all relay log; waiting for more updates Info: NULL *************************** 2. row *************************** Id: 2 User: system user Host: db: NULL Command: Connect Time: 1050709 State: Waiting for master to send event Info: NULL