Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这样的分布的机制,是通过将Mysql的某一台主机的数据拷贝到其他主机(slaves)上,并又一次运行一遍来实现的。复制过程中一个server充当主server。而一个或多个其他server充当从server。
主server将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志能够记录发送到从server的更新。当一个从server连接主server时。它通知主server从server在日志中读取的最后一次成功更新的位置。从server接收从那时起发生的不论什么更新,然后封锁并等待主server通知新的更新。
请注意当你进行复制时。全部对复制中的表的更新必须在主server上进行。否则,你必需要小心,以避免用户对主server上的表进行的更新与对从server上的表所进行的更新之间的冲突。
(1):基于语句的复制: 在主server上运行的SQL语句。在从server上运行相同的语句。
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重做中继日志中的事件,将改变反映它自己的数据。
下图描写叙述了复制的过程:
该过程的第一部分就是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
1、在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,输出例如以下:
所以,尽量使用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集群可能出现的数据延时也会更为明显。所以考虑使用多层级联复制之前,也须要评估数据延时相应用系统的影响。
原文:http://www.cnblogs.com/mfmdaoyou/p/7237988.html