整体上来说,复制大致分为3个步骤:
1. master将数据库的改变记录到二进制日志(binary log)中,这些记录叫做二进制日志事件(binary log
events);
2. slave将master的binary log events dump到它的中继日志(relay log);
3. slave重做中继日志中的事件,将改变反映到它自己的数据。
下图描述了复制的原理:
该过程的第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。
接下来就是slave将master的binary log拷贝到它自己的中继日志。首先,slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。
SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。
此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。
以一个实验介绍mysql主从复制的部署过程.
场景介绍:
HostName: Mysql_master IP: 192.168.200.20 Mysql复制主服务器
HostName: Mysql_slave IP: 192.168.200.21 Mysql复制从服务器
Mysql版本: 5.6.19
安装部分:
1. 安装cmake:从mysql5.5版本开始,开始使用cmake
cmake安装:
1
2
3
4
5
6
<code>#cmake安装</code>
<code>[root@Master_mysql src]</code><code># tar zxvf cmake-3.0.0.tar.gz</code>
<code>[root@Master_mysql src]</code><code># cd cmake-3.0.0</code>
<code>[root@Master_mysql cmake-3.0.0]</code><code># ./bootstrap</code>
<code>[root@Master_mysql cmake-3.0.0]</code><code># gmake</code>
<code>[root@Master_mysql cmake-3.0.0]</code><code># make install</code>
2.安装mysql:
7
8
9
10
11
12
13
14
15
<code>[root@Master_mysql ~]</code><code># groupadd mysql</code>
<code>[root@Master_mysql ~]</code><code># useradd -g mysql mysql</code>
<code>[root@Master_mysql src]</code><code># tar zxvf mysql-5.6.19.tar.gz</code>
<code>[root@Master_mysql src]</code><code># cd mysql-5.6.19</code>
<code>[root@Master_mysql mysql-5.6.19]</code><code># cmake .</code>
<code>[root@Master_mysql mysql-5.6.19]</code><code># make</code>
<code>[root@Master_mysql mysql-5.6.19]</code><code># make install</code>
<code>[root@Master_mysql mysql-5.6.19]</code><code># cd /usr/local/mysql/</code>
<code>[root@Master_mysql mysql]</code><code># chown -R mysql:mysql .</code>
<code>[root@Master_mysql mysql]</code><code># scripts/mysql_install_db --user=mysql &</code>
<code>[root@Master_mysql mysql]</code><code># chown -R root:root .</code>
<code>[root@Master_mysql mysql]</code><code># chown -R mysql:mysql data</code>
<code>[root@Master_mysql mysql]</code><code># bin/mysqld_safe --user=mysql &</code>
<code>[root@Master_mysql mysql]</code><code># cp support-files/mysql.server /etc/init.d/</code>
在Mysql主从服务器上分别执行上诉安装过程.
配置部分:
主数据库服务器配置
修改主数据库服务器配置文件my.cnf:
<code>#增加如下:</code>
<code>[mysqld]</code>
<code>server_id = 1</code>
<code>log_bin = mysql-binlog </code><code>#二进制日志名称前缀</code>
启动Mysql服务:
<code>[root@Master_mysql mysql]</code><code># /etc/init.d/mysql.server start</code>
主服务器上创建授权账号并获取二进制文件和位置:
16
17
18
19
20
21
<code>#复制权限</code>
<code>mysql> grant replication slave on *.* to </code><code>'replica'</code><code>@</code><code>'192.168.200.21'</code> <code>identified by </code><code>'replicapass'</code><code>;</code>
<code>Query OK, 0 rows affected (0.00 sec)</code>
<code>mysql> flush privileges;</code>
<code>Query OK, 0 rows affected (0.10 sec)</code>
<code>#锁表</code>
<code>mysql> flush tables with </code><code>read</code> <code>lock;</code>
<code>Query OK, 0 rows affected (0.01 sec)</code>
<code>#</code>
<code>mysql> show master status\G</code>
<code>*************************** 1. row ***************************</code>
<code> </code><code>File: mysql-binlog.000015</code>
<code> </code><code>Position: 413</code>
<code> </code><code>Binlog_Do_DB:</code>
<code> </code><code>Binlog_Ignore_DB:</code>
<code>Executed_Gtid_Set:</code>
<code>1 row </code><code>in</code> <code>set</code> <code>(0.00 sec)</code>
<code>mysql> unlock tables;</code>
<code>Query OK, 0 rows affected (0.04 sec)</code>
此处主要用来获取File 文件名称、Postition 位置,之后从服务器配置change master to时需要
指定此处获取的内容.
2. 从数据库服务器配置:
修改从数据库服务器配置文件my.cnf:
<code>server_id = 2</code>
<code>log_bin = mysql-binlog </code>
<code>relay_log = mysql-relaylog </code><code>#(中继日志名称前缀)</code>
<code>log_slave_updates = 1 </code><code>#(slave重做中继日志内容并写入到log_bin指定的二进制日志文件)</code>
普通的从数据库服务器是不需要启用二进制日志的,但在某些特殊情况下,必须启用二进制日志。比
如:某个从服务器同时作为其他数据库服务器的主、或者希望日常备份在从库上执行等。 开启二进制
日志后,需要同时开启log_slave_updates参数,如果不启用,二进制日志文件则不会有内容.
<code>[root@Slave_mysql mysql]</code><code># /etc/init.d/mysql.server start</code>
设置复制并启动复制:
<code>mysql> change master to master_host=</code><code>'192.168.200.20'</code><code>,</code>
<code> </code><code>-> master_user=</code><code>'replica'</code><code>,</code>
<code> </code><code>-> master_password=</code><code>'replicapass'</code><code>,</code>
<code> </code><code>-> master_log_file=</code><code>'mysql-binlog.000015'</code><code>,</code>
<code> </code><code>-> master_log_pos=413,</code>
<code> </code><code>-> master_connect_retry=10;</code>
<code>Query OK, 0 rows affected, 2 warnings (0.08 sec)</code>
<code>mysql> start slave;</code>
<code>Query OK, 0 rows affected (0.03 sec)</code>
从服务器上查看复制状态:
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<code>mysql> show slave status\G</code>
<code> </code><code>Slave_IO_State: Waiting </code><code>for</code> <code>master to send event</code>
<code> </code><code>Master_Host: 192.168.200.20</code>
<code> </code><code>Master_User: replica</code>
<code> </code><code>Master_Port: 3306</code>
<code> </code><code>Connect_Retry: 10</code>
<code> </code><code>Master_Log_File: mysql-binlog.000015</code>
<code> </code><code>Read_Master_Log_Pos: 413</code>
<code> </code><code>Relay_Log_File: mysql-relaylog.000002</code>
<code> </code><code>Relay_Log_Pos: 286</code>
<code> </code><code>Relay_Master_Log_File: mysql-binlog.000015</code>
<code> </code><code>Slave_IO_Running: Yes</code>
<code> </code><code>Slave_SQL_Running: Yes</code>
<code> </code><code>Replicate_Do_DB:</code>
<code> </code><code>Replicate_Ignore_DB:</code>
<code> </code><code>Replicate_Do_Table:</code>
<code> </code><code>Replicate_Ignore_Table:</code>
<code> </code><code>Replicate_Wild_Do_Table:</code>
<code> </code><code>Replicate_Wild_Ignore_Table:</code>
<code> </code><code>Last_Errno: 0</code>
<code> </code><code>Last_Error:</code>
<code> </code><code>Skip_Counter: 0</code>
<code> </code><code>Exec_Master_Log_Pos: 413</code>
<code> </code><code>Relay_Log_Space: 458</code>
<code> </code><code>Until_Condition: None</code>
<code> </code><code>Until_Log_File:</code>
<code> </code><code>Until_Log_Pos: 0</code>
<code> </code><code>Master_SSL_Allowed: No</code>
<code> </code><code>Master_SSL_CA_File:</code>
<code> </code><code>Master_SSL_CA_Path:</code>
<code> </code><code>Master_SSL_Cert:</code>
<code> </code><code>Master_SSL_Cipher:</code>
<code> </code><code>Master_SSL_Key:</code>
<code> </code><code>Seconds_Behind_Master: 0</code>
<code>Master_SSL_Verify_Server_Cert: No</code>
<code> </code><code>Last_IO_Errno: 0</code>
<code> </code><code>Last_IO_Error:</code>
<code> </code><code>Last_SQL_Errno: 0</code>
<code> </code><code>Last_SQL_Error:</code>
<code> </code><code>Replicate_Ignore_Server_Ids:</code>
<code> </code><code>Master_Server_Id: 1</code>
<code> </code><code>Master_UUID: e84592e0-0e5b-11e4-a5d3-000c29e88022</code>
<code> </code><code>Master_Info_File: </code><code>/usr/local/mysql/data/master</code><code>.info</code>
<code> </code><code>SQL_Delay: 0</code>
<code> </code><code>SQL_Remaining_Delay: NULL</code>
<code> </code><code>Slave_SQL_Running_State: Slave has </code><code>read</code> <code>all relay log; waiting </code><code>for</code> <code>the slave I</code><code>/O</code> <code>thread to update it</code>
<code> </code><code>Master_Retry_Count: 86400</code>
<code> </code><code>Master_Bind:</code>
<code> </code><code>Last_IO_Error_Timestamp:</code>
<code> </code><code>Last_SQL_Error_Timestamp:</code>
<code> </code><code>Master_SSL_Crl:</code>
<code> </code><code>Master_SSL_Crlpath:</code>
<code> </code><code>Retrieved_Gtid_Set:</code>
<code> </code><code>Executed_Gtid_Set:</code>
<code> </code><code>Auto_Position: 0</code>
可以看到: Slave_IO_Running和Slave_SQL_Running 状态都是Yes,这说明两个线程都在正常运行,复制
成功执行.
复制验证部分:
主服务器上,登录数据库进行建库操作:
本例创建库temp和表t1
<code>mysql> create database temp;</code>
<code>Query OK, 1 row affected (0.06 sec)</code>
<code>mysql> create table temp.t1(</code>
<code> </code><code>-> number varchar(10) not null,</code>
<code> </code><code>-> name varchar(20),</code>
<code> </code><code>-> birthday </code><code>date</code><code>,</code>
<code> </code><code>-> primary key (number)</code>
<code> </code><code>-> );</code>
<code>Query OK, 0 rows affected (0.23 sec)</code>
<code>mysql> insert into temp.t1</code>
<code> </code><code>-> values(</code><code>'20140805'</code><code>,</code><code>'shizhenning'</code><code>,</code><code>'19860101'</code><code>);</code>
<code>Query OK, 1 row affected (0.07 sec)</code>
<code>mysql> </code><code>select</code> <code>* from temp.t1;</code>
<code>+----------+-------------+------------+</code>
<code>| number | name | birthday |</code>
<code>| 20140805 | shizhenning | 1986-01-01 |</code>
<code>1 row </code><code>in</code> <code>set</code> <code>(0.03 sec)</code>
查询从库服务器复制结果:
<code>mysql> show databases;</code>
<code>+--------------------+</code>
<code>| Database |</code>
<code>| information_schema |</code>
<code>| mysql |</code>
<code>| performance_schema |</code>
<code>| temp |</code>
<code>| </code><code>test</code> <code>|</code>
<code>5 rows </code><code>in</code> <code>set</code> <code>(0.00 sec)</code>
可以看到,从库服务器已经复制完成.
对比两台服务器日志:
主服务器执行: mysqlbinlog data/mysql-binlog.000015
从库服务器执行: mysqlbinlog data/mysql-binlog.000002
从库服务器的二进制日志已经有了内容,时间戳和主库二进制保持一致.
这样一个基本的主从复制就部署完成了.
本文转自marbury 51CTO博客,原文链接:http://blog.51cto.com/magic3/1439426,如需转载请自行联系原作者