
主从设计可以让数据从一台服务器(Master)复制到多台独立的服务器(Slaves)。主从结构有很多好处,这已经成为后端标配的架构,在MYSQL中实现这一功能的术语叫 - Replication 。
注:配图并没有体现读写分离
主从设计的好处:
-
水平扩展,读写分离 - 在这种架构下,所有的增/删/改操作在Master上执行,所有的读操作在Slaves上执行,这样可以把并行压力分担到多个从库(这个专题后面应该还有读写分离相关中间件的问题,可以了解下。)
-
数据安全 - 从库可以随时停下来备份数据,而不必考虑服务不可用的问题。
-
数据分析 - 在从库上分析数据,不会影响主库的性能
-
远程数据分配 - 可以通过从库创建数据提供给远端的网站使用,而不必暴露主库
目前MySQL支持两种方式的主从复制:
配置实施
原理
MySQL数据库的每次更新变化都会以“events”的方式记录到一个二进制的log文件,从库可以配置从主库中读取这些log文件,并在从库的本地执行,这样便可以把主库的数据同步到从库。
每个从库都会从主库读取完整的log文件,所以需要从库来记录“上次”同步的位置。这种设计可以保证不同的从库可以独立工作,更新不同的内容。即使从库崩溃了,只要本地记录了上次更新的位置,依然可以把主库的数据同步回来。
BinaryLog主要作用:
主从复制
备份恢复
注意这和数据库用来处理事物的 “Write-ahead logging” 并不不是同一份日志,在MySQL里面是 “InnoDBLogs”,因为InnoDB是支持事物的DB引擎。另外,开启BinaryLog会拖慢系统性能。
步骤:
- 在Master上,启用 “binary logging” 并配置唯一的 “server ID”(需要重启服务)
打开 my.cnf 或者 my.ini 文件,添加如下:
[mysqld]
// 启用BinaryLog,配置log文件名为 'mysql-bin'
log-bin=mysql-bin
// 全局唯一的ServerId用来标示服务器在主从集群中的位置
server-id=1
这里的 my.cnf 文件的位置可以用mysqld --help --verbose
看到,见 StackOverflow.
- 在每个Slave上,配置唯一的 “server ID” (需要重启服务)
[mysqld]
server-id=2
采用同样的方式,给每台Slave服务编号(注意要重启服务!)。从库一般不需要开启BinaryLog,但是可以配置一台Slave开启BinaryLog,留作数据备份之用。
- (可选)创建一个用来给 Slave 访问 Master 日志(binarylog)的用户
mysql> CREATE USER 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.mydomain.com';
在Master上创建用户 'repl',并赋予 'REPLICATION SLAVE' 的权限,这样Slave可以通过用户名/密码的方式访问Master
- 在开始主从复制之前,需要先记录Master上的日志的当前位置(这样Slave才知道从哪儿开始执行BinaryLog中的事件)
在Master上执行
mysql > SHOW MASTER STATUS;
可以看到日志的信息(前提是已经启用了BinaryLog,否则是空)
mysql > SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 | 73 | test | manual,mysql |
+------------------+----------+--------------+------------------+
另外在这步操作时,需要先锁住数据库,避免在这时候产生数据的变化 FLUSH TABLES WITH READ LOCK;
,这一步需要非常小心,详见文档。
-
如果Master上已经有很多数据了,可以先把Master上的数据拷贝到Slave上
这一步的做法太多,如果我们的主从设计是从头开始的,没有遗留数据的烦恼,那么可以略过。
-
在Slave上配置相关设置,以便告诉Slave如何去连接Master,这包括主机地址,登陆凭证等等
执行如下语句,设置相关的环境信息。
mysql> CHANGE MASTER TO
-> MASTER_HOST='master_host_name',
-> MASTER_USER='replication_user_name',
-> MASTER_PASSWORD='replication_password',
-> MASTER_LOG_FILE='recorded_log_file_name',
-> MASTER_LOG_POS=recorded_log_position;
- 开启同步
start slave;//开启
stop slave;//停止
走完这一圈,整个配置完毕了,如果有新的Slave需要添加到集群中,可以先ShutDown一台Slave,把数据Copy过来,导入新的Slave在启动配置。
- 测试
随便在master上搞搞,就应该会同步了。
这是基本的主从配置大概步骤,对于生产环境还会有更复杂情况:
全新的Master和Slave,一切从头开始的情况
全新的Master,但是已经有了一些数据需要导入,并配置Slave
Master已经配置了Slave,这时候追加一些Slave
问题
如果出现无法同步的情况可以在slave上使用show slave status
查看状态
检查从服务器复制功能状态:
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.2.222 //主服务器地址
Master_User: mysync //授权帐户名,尽量避免使用root
Master_Port: 3306 //数据库端口,部分版本没有此行
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 600 //#同步读取二进制日志的位置,大于等于Exec_Master_Log_Pos
Relay_Log_File: ddte-relay-bin.000003
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes //此状态必须YES
Slave_SQL_Running: Yes //此状态必须YES
......
注:Slave_IO及Slave_SQL进程必须正常运行,即YES状态,否则都是错误的状态(如:其中一个NO均属错误)。
如果有错误可以看Last_SQL_Error
信息,做适当的调整。