Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这样的分布的机制,是经过将Mysql的某一台主机的数据拷贝到其余主机(slaves)上,并又一次运行一遍来实现的。复制过程当中一个server充当主server。而一个或多个其余server充当从server。mysql
主server将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从server的更新。当一个从server链接主server时。它通知主server从server在日志中读取的最后一次成功更新的位置。从server接收从那时起发生的不论什么更新,而后封锁并等待主server通知新的更新。算法
请注意当你进行复制时。所有对复制中的表的更新必须在主server上进行。不然,你必须要当心,以免用户对主server上的表进行的更新与对从server上的表所进行的更新之间的冲突。sql
(1):基于语句的复制: 在主server上运行的SQL语句。在从server上运行相同的语句。shell
MySQL默认採用基于语句的复制,效率比較高。数据库
一旦发现无法精确复制时, 会本身主动选着基于行的复制。
(2):基于行的复制:把改变的内容复制过去,而不是把命令在从server上运行一遍. 从mysql5.0開始支持
(3):混合类型的复制: 默认採用基于语句的复制,一旦发现基于语句的没法精确的复制时。就会採用基于行的复制。缓存
MySQL复制技术有下面一些特色:
(1) 数据分布 (Data distribution )
(2) 负载平衡(load balancing)
(3) 备份(Backups)
(4) 高可用性和容错行 High availability and failover 服务器
整体上来讲。复制有3个步骤: 网络
(1) master将改变记录到二进制日志(binary log)中(这些记录叫作二进制日志事件。binary log events);
(2) slave将master的binary log events复制到它的中继日志(relay log)。
(3) slave重作中继日志中的事件,将改变反映它本身的数据。
session
下图描写叙述了复制的过程:架构
该过程的第一部分就是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数据库serverMaster和slave,Master为主server,slave为从server。初始状态时。Master和slave中的数据信息一样,当Master中的数据发生变化时,slave也跟着发生对应的变化。使得master和slave的数据信息同步,达到备份的目的。
要点:
负责在主、从server传输各类修修改做的媒介是主server的二进制变动日志。这个日志记载着需要传输给从server的各类修修改做。
所以。主server必须激活二进制日志功能。
从server必须具有足以让它链接主server并请求主server把二进制变动日志传输给它的权限。
环境:
Master和slave的MySQL数据库版本号同为5.0.18
操做系统:unbuntu 11.10
IP地址:10.100.0.100
一、在Master的数据库中创建一个备份账户:每个slave使用标准的MySQLusername和password链接master。进行复制操做的用户会授予REPLICATION SLAVE权限。username的password都会存储在文本文件master.info中
命令例如如下:
mysql > GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.*
TO backup@’10.100.0.200’
IDENTIFIED BY ‘1234’;
创建一个账户backup,并且仅仅能赞成从10.100.0.200这个地址上来登录,password是1234。
(假设因为mysql版本号新旧密码算法不一样。可以设置:set password for 'backup'@'10.100.0.200'=old_password('1234'))
(假如是你全然新安装mysql主从server,这个一步就不需要。因为新安装的master和slave有一样的数据)
关停Masterserver,将Master中的数据复制到Bserver中,使得Master和slave中的数据同步,并且确保在全部设置操做结束前,禁止在Master和slaveserver中进行写操做。使得两数据库中的数据必定要一样。
接下来对master进行配置。包含打开二进制日志。指定惟一的servr ID。
好比。在配置文件增长例如如下值:
server-id=1
log-bin=mysql-bin
server-id:为主服务器A的ID值
log-bin:二进制变动日值
从新启动master,执行SHOW MASTER STATUS,输出例如如下:
有些人开启了slave的二进制日志。却没有设置log_slave_updates,而后查看slave的数据是否改变,这是一种错误的配置。
因此,尽可能使用read_only,它防止改变数据(除了特殊的线程)。但是,read_only并是很是有用。特别是那些需要在slave上建立表的应用。
例如如下:
mysql> CHANGE MASTER TO MASTER_HOST='server1',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='p4ssword',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=0;
MASTER_LOG_POS的值为0,因为它是日志的開始位置。
你可以用SHOW SLAVE STATUS语句查看slave的设置是否正确:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
...omitted...
Seconds_Behind_Master: NULL
Slave_IO_State, Slave_IO_Running, 和Slave_SQL_Running是No
代表slave尚未開始复制过程。
日志的位置为4而不是0,这是因为0仅仅是日志文件的開始位置,并不是日志位置。实际上,MySQL知道的第一个事件的位置是4。
为了開始复制。你可以执行:
mysql> START SLAVE;
执行SHOW SLAVE STATUS查看输出结果:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 164
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 164
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...omitted...
Seconds_Behind_Master: 0
slave的I/O和SQL线程都已经開始执行,而且Seconds_Behind_Master再也不是NULL。日志的位置添加了,意味着一些事件被获取并执行了。
假设你在master上进行改动,你可以在slave上看到各类日志文件的位置的变化,相同,你也可以看到数据库中数据的变化。
你可查看master和slave上线程的状态。在master上,你可以看到slave的I/O线程建立的链接:
mysql> show processlist \G *************************** 1. row *************************** Id: 1 User: root Host: localhost:2096 db: test Command: Query Time: 0 State: NULL Info: show processlist *************************** 2. row *************************** Id: 2 User: repl Host: localhost:2144 db: NULL Command: Binlog Dump Time: 1838 State: Has sent all binlog to slave; waiting for binlog to be updated Info: NULL 2 rows in set (0.00 sec) |
行2为处理slave的I/O线程的链接。
在slaveserver上执行该语句:
mysql> show processlist \G *************************** 1. row *************************** Id: 1 User: system user Host: db: NULL Command: Connect Time: 2291 State: Waiting for master to send event Info: NULL *************************** 2. row *************************** Id: 2 User: system user Host: db: NULL Command: Connect Time: 1852 State: Has read all relay log; waiting for the slave I/O thread to update it Info: NULL *************************** 3. row *************************** Id: 5 User: root Host: localhost:2152 db: test Command: Query Time: 0 State: NULL Info: show processlist 3 rows in set (0.00 sec) |
假如master已经执行很是久了,想对新安装的slave进行数据同步,甚至它没有master的数据。
此时,有几种方法可以使slave从还有一个服务開始,好比。从master拷贝数据,从还有一个slave克隆。从近期的备份開始一个slave。
Slave与master同步时,需要三样东西:
(1)master的某个时刻的数据快照;
(2)master当前的日志文件、以及生成快照时的字节偏移。这两个值可以叫作日志文件坐标(log file coordinate),因为它们肯定了一个二进制日志的位置,你可以用SHOW MASTER STATUS命令找到日志文件的坐标。
(3)master的二进制日志文件。
可以经过下面几中方法来克隆一个slave:
(1) 冷拷贝(cold copy)
中止master。将master的文件复制到slave。而后从新启动master。缺点很是明显。
(2) 热拷贝(warm copy)
假设你仅使用MyISAM表,你可以使用mysqlhotcopy拷贝。即便server正在执行。
(3) 使用mysqldump
使用mysqldump来获得一个数据快照可分为下面几步:
<1>锁表:假设你尚未锁表,你应该对表加锁,防止其余链接改动数据库,不然。你获得的数据可以是不一致的。例如如下:
mysql> FLUSH TABLES WITH READ LOCK;
<2>在还有一个链接用mysqldump建立一个你想进行复制的数据库的转储:
shell> mysqldump --all-databases --lock-all-tables >dbdump.db
<3>对表释放锁。
mysql> UNLOCK TABLES;
master记录下改变数据的查询,而后,slave从中继日志中读取事件,并运行它,这些SQL语句与master运行的语句同样。
这样的方式的长处就是实现简单。
此外,基于语句的复制的二进制日志可以很是好的进行压缩。而且日志的数据量也较小,占用带宽少——好比,一个更新GB的数据的查询仅需要几十个字节的二进制日志。而mysqlbinlog对于基于语句的日志处理十分方便。
但是。基于语句的复制并不是像它看起来那么简单,因为一些查询语句依赖于master的特定条件,好比。master与slave可能有不一样的时间。因此,MySQL的二进制日志的格式不不过查询语句,还包含一些元数据信息。好比,当前的时间戳。
即便如此,仍是有一些语句,比方,CURRENT USER函数。不能正确的进行复制。
此外。存储过程和触发器也是一个问题。
另一个问题就是基于语句的复制必须是串行化的。
这要求大量特殊的代码。配置,好比InnoDB的next-key锁等。并不是所有的存储引擎都支持基于语句的复制。
这样的方式有长处,也有缺点。长处就是可以对不论什么语句都能正确工做。一些语句的效率更高。基本的缺点就是二进制日志可能会很是大,而且不直观,因此。你不能使用mysqlbinlog来查看二进制日志。
对于一些语句。基于记录的复制能够更有效的工做,如:
mysql> INSERT INTO summary_table(col1, col2, sum_col3)
-> SELECT col1, col2, sum(col3)
-> FROM enormous_table
-> GROUP BY col1, col2;
若是,仅仅有三种惟一的col1和col2的组合。但是。该查询会扫描原表的不少行。却仅返回三条记录。
此时,基于记录的复制效率更高。
还有一方面。如下的语句,基于语句的复制更有效:
mysql> UPDATE enormous_table SET col1 = 0;
此时使用基于记录的复制代价会很是高。由于两种方式不能对所有状况都能很是好的处理,因此,MySQL 5.1支持在基于语句的复制和基于记录的复制以前动态交换。你可以经过设置session变量binlog_format来进行控制。
它用于跟踪磁盘上存在哪些二进制日志文件。MySQL用它来定位二进制日志文件。它的内容例如如下(个人机器上):
内容例如如下:
.\mysql-02-relay-bin.000017
.\mysql-02-relay-bin.000018
不要删除它,不然,slave从新启动后不能链接master。内容例如如下(个人机器上):
I/O线程更新master.info文件,内容例如如下(个人机器上):
.\mysql-02-relay-bin.000019 254 mysql-01-bin.000010 286 0 52813 |
MySQL不支持多主server复制(Multimaster Replication)——即一个slave可以有多个master。
但是。经过一些简单的组合,咱们却可以创建灵活而强大的复制体系结构。
Slave之间并不相互通讯。仅仅能与master进行通讯。
在实际应用场景中。MySQL复制90%以上都是一个Master拷贝到一个或者多个Slave的架构模式,主要用于读压力比較大的应用的数据库端便宜扩展解决方式。
因为仅仅要Master和Slave的压力不是太大(尤为是Slave端压力)的话,异步复制的延时通常都很是少很是少。尤为是自从Slave端的复制方式改为两个线程处理以后。更是减少了Slave端的延时问题。而带来的效益是。对于数据实时性要求不是特别Critical的应用。仅仅需要经过便宜的pcserver来扩展Slave的数量,将读压力分散到多台Slave的机器上面,就能够经过分散单台数据库服务器的读压力来解决数据库端的读性能瓶颈。毕竟在大多数数据库应用系统中的读压力仍是要比写压力大很是多。
这在很是大程度上攻克了眼下很是多中小型站点的数据库压力瓶颈问题。甚至有些大型站点也在使用相似方案解决数据库瓶颈。
但是,当slave添加到必定数量时,slave对master的负载以及网络带宽都会成为一个严重的问题。
这样的结构尽管简单,但是。它却很灵活,足够知足大多数应用需求。一些建议:
(1) 不一样的slave扮演不一样的做用(好比使用不一样的索引,或者不一样的存储引擎);
(2) 用一个slave做为备用master,仅仅进行复制。
(3) 用一个远程的slave。用于灾难恢复。
你们应该都比較清楚,从一个Master节点可以复制出多个Slave节点。可能有人会想。那一个Slave节点可否够从多个Master节点上面进行复制呢?至少在眼下来看,MySQL是作不到的,之后是否会支持就不清楚了。
MySQL不支持一个Slave节点从多个Master节点来进行复制的架构。主要是为了不冲突的问题。防止多个数据源之间的数据出现冲突,而形成最后数据的不一致性。只是据说已经有人开发了相关的patch,让MySQL支持一个Slave节点从多个Master结点做为数据源来进行复制,这也正是MySQL开源的性质所带来的优势。
可能有些读者朋友会有一个操心,这样搭建复制环境以后。难道不会形成两台MySQL之间的循环复制么?实际上MySQL本身早就想到了这一点。因此在MySQL的BinaryLog中记录了当前MySQL的server-id,而且这个參数也是咱们搭建MySQLReplication的时候必须明白指定。而且Master和Slave的server-id參数值比需要不一致才干使MySQLReplication搭建成功。一旦有了server-id的值以后。MySQL就很是easy推断某个变动是从哪个MySQLServer最初产生的,因此就很是easy避免出现循环复制的状况。而且。假设咱们不打开记录Slave的BinaryLog的选项(--log-slave-update)的时候,MySQL根本就不会记录复制过程当中的变动到BinaryLog中,就更不用操心可能会出现循环复制的情形了。
主动的Master-Master复制有一些特殊的用处。好比,地理上分布的两个部分都需要本身的可写的数据副本。
这样的结构最大的问题就是更新冲突。
若是一个表仅仅有一行(一列)的数据,其值为1,若是两个server分别同一时候运行例如如下语句:
在第一个server上运行:
mysql> UPDATE tbl SET col=col + 1;
在第二个server上运行:
mysql> UPDATE tbl SET col=col * 2;
那么结果是多少呢?一台server是4,还有一个server是3,但是,这并不会产生错误。
实际上。MySQL并不支持其余一些DBMS支持的多主server复制(Multimaster Replication),这是MySQL的复制功能很是大的一个限制(多主server的难点在于解决更新冲突),但是。假设你实在有这样的需求,你可以採用MySQL Cluster。以及将Cluster和Replication结合起来。可以创建强大的高性能的数据库平台。但是。可以经过其余一些方式来模拟这样的多主server的复制。
在有些应用场景中,可能读写压力区别比較大,读压力特别的大,一个Master可能需要上10台甚至不少其它的Slave才能够支撑注读的压力。这时候,Master就会比較吃力了。因为只连上来的SlaveIO线程就比較多了。这样写的压力略微大一点的时候,Master端因为复制就会消耗较多的资源,很是easy形成复制的延时。
遇到这样的状况怎样解决呢?这时候咱们就可以利用MySQL可以在Slave端记录复制所产生变动的BinaryLog信息的功能,也就是打开—log-slave-update选项。
而后,经过二级(或者是不少其它级别)复制来下降Master端因为复制所带来的压力。也就是说,咱们首先经过少数几台MySQL从Master来进行复制。这几台机器咱们姑且称之为第一级Slave集群。而后其它的Slave再从第一级Slave集群来进行复制。
从第一级Slave进行复制的Slave,我称之为第二级Slave集群。假设有需要。咱们可以继续往下添加不少其它层次的复制。这样。咱们很是easy就控制了每一台MySQL上面所附属Slave的数量。这样的架构我称之为Master-Slaves-Slaves架构
这样的多层级联复制的架构,很是easy就攻克了Master端因为附属Slave太多而成为瓶颈的风险。
下图展现了多层级联复制的Replication架构。
固然,假设条件赞成,我更倾向于建议你们经过拆分红多个Replication集群来解决
上述瓶颈问题。
毕竟Slave并无下降写的量,所有Slave实际上仍然仍是应用了所有的数据变动操做,没有下降不论什么写IO。
相反,Slave越多。整个集群的写IO总量也就会越多,咱们没有很是明显的感受,只不过因为分散到了多台机器上面,因此不是很是easy表现出来。
此外,添加复制的级联层次,同一个变动传到最底层的Slave所需要通过的MySQL也会不少其它。相同可能形成延时较长的风险。
而假设咱们经过分拆集群的方式来解决的话,可能就会要好很是多了,固然,分拆集群也需要更复杂的技术和更复杂的应用系统架构。
级联复制在必定程度上面确实攻克了Master因为所附属的Slave过多而成为瓶颈的问题。但是他并不能解决人工维护和出现异常需要切换后可能存在又一次搭建Replication的问题。
这样就很是天然的引伸出了DualMaster与级联复制结合的Replication架构,我称之为Master-Master-Slaves架构
和Master-Slaves-Slaves架构相比,差异只不过将第一级Slave集群换成了一台单独的Master,做为备用Master。而后再从这个备用的Master进行拷贝到一个Slave集群。
这样的DualMaster与级联复制结合的架构,最大的优势就是既可以避免主Master的写入操做不会受到Slave集群的复制所带来的影响,同一时候主Master需要切换的时候也基本上不会出现重搭Replication的状况。但是。这个架构也有一个弊端,那就是备用的Master有可能成为瓶颈,因为假设后面的Slave集群比較大的话。备用Master可能会因为过多的SlaveIO线程请求而成为瓶颈。固然,该备用Master不提供不论什么的读服务的时候。瓶颈出现的可能性并不是特别高,假设出现瓶颈,也可以在备用Master后面再次进行级联复制。架设多层Slave集群。固然,级联复制的级别越多。Slave集群可能出现的数据延时也会更为明显。因此考虑使用多层级联复制以前,也需要评估数据延时相应用系统的影响。