1、复制的工作原理
复制(replication)是MySQL数据库提供的一种高可用高性能的解决方案,一般用来建立大型的应用。总体来说, replication的工作原理分为以下3个步骤:
- 主服务器(master)把数据更改记录到二进制日志(binlog)中。
- 从服务器(slave)把主服务器的二进制日志复制到自己的中继日志(relay log)中。
- 从服务器重做中继日志中的日志,把更改应用到自己的数据库上,以达到数据的最终一致性。
复制的工作原理并不复杂,其实就是一个完全备份加上二进制日志备份的还原。不同的是这个二进制日志的还原操作基本上实时在进行中。这里特别需要注意的是,复制不是完全实时地进行同步,而是异步实时。这中间存在主从服务器之间的执行延时,如果主服务器的压力很大,则可能导致主从服务器延时较大。复制的工作原理如图8-4所示。
从服务器有2个线程,一个是IO线程,负责读取主服务器的二进制日志,并将其保存为中继日志;另一个是SQL线程,复制执行中继日志。 MySQL4.0版本之前,从服务器只有1个线程,既负责读取二进制日志,又负责执行二进制日志中的SQL语句。这种方式不符合高性能的要求,目前已淘汰。因此如果查看一个从服务器的状态,应该可以看到类似如下内容:
可以看到ID为1的线程就是IO线程,目前的状态是等待主服务器发送二进制日志。ID为2的线程是SQL线程,负责读取中继日志并执行。目前的状态是已读取所有的中继日志,等待中继日志被IO线程更新。
在replication的主服务器上应该可以看到一个线程负责发送二进制日志,类似内容如下:
之前已经说过 MySQL的复制是异步实时的,并非完全的主从同步。若用户要想得知当前的延迟,可以通过命令 SHOW SLAVE STATUS和 SHOW MASTER STATUS得知,如:
通过 SHOW SLAVE STATUS命令可以观察当前复制的运行状态,一些主要的变量如下表所示。
变量 | 说明 |
---|---|
变量 | 说明 |
Slave_IO_State | 显示当前IO线程的状态,上述状态显示的是等待主服务发送二进制日志 |
Master_Log_File | 显示当前同步的主服务器的二进制日志,上述显示当前同步的是主服务器的mysql-bin.000007 |
Read_master_Log_Pos | 显示当前同步到主服务器上二进制日志的偏移量位置,单位是字节。上述的示例显示当前同步到mysql-bin000007的551671偏移量位置,即已经同步了mysql-bin000007这个二进制日志中529MB(555176471/10241024)的内容 |
Relay_Master_Log_File | 当前中继日志同步的二进制日志 |
Relay_Log_File | 显示当前写入的中继日志 |
Relay_Log_Pos | 显示当前执行到中继日志的偏移量位置 |
Slave_IO_Running | 从服务器中IO线程的运行状态,YES表示运行正常 |
Slave_SQL_Running | 从服务器中SQL线程的运行状态,YES表示运行正常 |
Exec_master_Log_Pos | 表示同步到主服务器的二进制日志偏移量的位置。(Read_Master_Log_Pos-Exec_Master_Log._Pos)可以表示当前SQL线程运行的延时,单位是字节。上述例子显示当前主从服务器是完全同步的 |
命令 SHOW MASTER STATU可以用来查看主服务器中二进制日志的状态,如:
可以看到,当前二进制日志记录了偏移量606181078的位置,该值减去这一时间点时从服务器上的Read_Master_Log_Pos,就可以得知IO线程的延时。
对于一个优秀的 MySQL数据库复制的监控,用户不应该仅仅监控从服务器上IO线程和SQL线程运行得是否正常,同时也应该监控从服务器和主服务器之间的延迟,确保从服务器上的数据库总是尽可能地接近于主服务器上数据库的状态。
2、快照+复制的备份架构
复制可以用来作为备份,但功能不仅限于备份,其主要功能如下:
- 数据分布。由于 MySQL数据库提供的复制并不需要很大的带宽要求,因此可以在不同的数据中心之间实现数据的复制。
- 读取的负载平衡。通过建立多个从服务器,可将读取平均地分布到这些从服务器中,并且减少了主服务器的压力。一般通过DNS的 Round-Robin和 Linux的LVS功能都可以实现负载平衡。
- 数据库备份。复制对备份很有帮助,但是从服务器不是备份,不能完全代替备份。
- 高可用性和故障转移。通过复制建立的从服务器有助于故障转移,减少故障的停机时间和恢复时间。
可见,复制的设计不是简简单单用来备份的,并且只是用复制来进行备份是远远不够的。假设当前应用采用了主从的复制架构,从服务器作为备份。这时,一个初级DBA执行了误操作,如 DROP DATABASE或 DROP TABLE,这时从服务器也跟着运行了。
这时用户怎样从服务器进行恢复呢?
因此,一个比较好的方法是通过对从服务器上的数据库所在分区做快照,以此来避免误操作对复制造成影响。当发生主服务器上的误操作时,只需要将从服务器上的快照进行恢复,然后再根据二进制日志进行point-in-time的恢复即可。因此快照+复制的备份架构如图8-5所示。
还有一些其他的方法来调整复制,比如采用延时复制,即间歇性地开启从服务器上的同步,保证大约一小时的延时。这的确也是一个方法,只是数据库在高峰和非高峰期间每小时产生的二进制日志量是不同的,用户很难精准地控制。另外,这种方法也不能完全起到对误操作的防范作用。
此外,建议在从服务上启用read-only选项,这样能保证从服务器上的数据仅与主服务器进行同步,避免其他线程修改数据。如:
[mysqld]
read-only
在启用read-only选项后,如果操作从服务器的用户没有 SUPER权限,则对从服务器进行任何的修改操作会抛出一个错误,如: