数据库的主从复制

image.png

主从设计可以让数据从一台服务器(Master)复制到多台独立的服务器(Slaves)。主从结构有很多好处,这已经成为后端标配的架构,在MYSQL中实现这一功能的术语叫 - Replication 。

注:配图并没有体现读写分离

主从设计的好处:

  • 水平扩展,读写分离 - 在这种架构下,所有的增/删/改操作在Master上执行,所有的读操作在Slaves上执行,这样可以把并行压力分担到多个从库(这个专题后面应该还有读写分离相关中间件的问题,可以了解下。)

  • 数据安全 - 从库可以随时停下来备份数据,而不必考虑服务不可用的问题。

  • 数据分析 - 在从库上分析数据,不会影响主库的性能

  • 远程数据分配 - 可以通过从库创建数据提供给远端的网站使用,而不必暴露主库

目前MySQL支持两种方式的主从复制:

  • 基于BinaryLog的比较传统的方式 这种方式log文件和文件中的同步位置

  • 基于GlobalTransactionIdentifiers (GTIDs) 这种方式比较新,暂未研究

配置实施

原理

MySQL数据库的每次更新变化都会以“events”的方式记录到一个二进制的log文件,从库可以配置从主库中读取这些log文件,并在从库的本地执行,这样便可以把主库的数据同步到从库。

每个从库都会从主库读取完整的log文件,所以需要从库来记录“上次”同步的位置。这种设计可以保证不同的从库可以独立工作,更新不同的内容。即使从库崩溃了,只要本地记录了上次更新的位置,依然可以把主库的数据同步回来。

BinaryLog主要作用:
主从复制
备份恢复
注意这和数据库用来处理事物的 “Write-ahead logging” 并不不是同一份日志,在MySQL里面是 “InnoDBLogs”,因为InnoDB是支持事物的DB引擎。另外,开启BinaryLog会拖慢系统性能。

步骤:

  1. 在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.

  1. 在每个Slave上,配置唯一的 “server ID” (需要重启服务)
[mysqld]
server-id=2

采用同样的方式,给每台Slave服务编号(注意要重启服务!)。从库一般不需要开启BinaryLog,但是可以配置一台Slave开启BinaryLog,留作数据备份之用。

  1. (可选)创建一个用来给 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

  1. 在开始主从复制之前,需要先记录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;,这一步需要非常小心,详见文档。

  1. 如果Master上已经有很多数据了,可以先把Master上的数据拷贝到Slave上 这一步的做法太多,如果我们的主从设计是从头开始的,没有遗留数据的烦恼,那么可以略过。

  2. 在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;
  1. 开启同步
start slave;//开启
stop slave;//停止

走完这一圈,整个配置完毕了,如果有新的Slave需要添加到集群中,可以先ShutDown一台Slave,把数据Copy过来,导入新的Slave在启动配置。

  1. 测试 随便在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信息,做适当的调整。

# 数据库 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×