17.3 Replication Solutions 复制解决
复制可以用于很多不同的环境和不同的目的,这个章节提供了大体的注意事项
和建议
使用复制在一个备份的环境,包括安装说明,备份过程,和备份的文件。
对于建议和提示在使用不同的存储引擎在master和slaves上
使用复制作为一个扩展的解决方案需要在逻辑的一些变化
17.3.1 Using Replication for Backups
使用复制备份
使用一个复制作为备份方案,复制数据从master到slave,备份slave的数据。
slave可以暂停和关闭不影响master上的操作,因此你可以产生一个有效的快照 否则就可能需要关闭master来做
然而你备份数据库依赖 它的大小和你是否只备份数据,或者数据和复制slave的状态
你可以重建故障的事件中的slave. 因此这里有2个选择:
2.对于大的数据库,mysqldump 是不切合实际的或者低效的,你可以用raw 数据文件代替备份。
另一个备份策略,可以用于master和slave servers, 是把server 至于read-only状态。
17.3.1.1 Backing Up a Slave Using mysqldump
备份Slave 使用mysqldump
使用mysqldump 来创建数据库的copy 可以获取数据库的所有数据,可以用于import到另外的数据库
因为备份的信息是SQL语句, 文件很容易分散和应用到运行的server
如果你的数据库很大,mysqldump 是不切合实际的。
当使用mysqldump的时候,你需要停止复制 确保mysql 备份数据的一致性
shell> mysqladmin stop-slave
或者,你可以只停止SLAVE SQL thread 来暂停event处理
shell> mysql -e ‘STOP SLAVE SQL_THREAD;’
这个可以使slave继续从master接收binary log,把它们存储在relay logs里使用 I/O thread,
但是阻止slave 执行这些事件和改变它的数据
在繁忙的复制环境, 允许I/O thread 来运行在备份的时候可以加速追赶进程,当你启动slave SQL thread的时候。
2.运行mysqldump 来备份数据库,你可以备份所有的数据库或者选择指定的数据库来备份
比如备份所有的数据库:
shell> mysqldump –all-databases > fulldb.dump
3.dump完成后,启动slave
shell> mysqladmin start-slave
在前面的例子中,你需要增加登录认证(用户名和密码),把命令放入到脚本中,可以每天自动运行。
如果你使用这个方法, 确保你监控slave的复制进程来确保运行备份不影响slave跟上master的events
17.3.1.2 Backing Up Raw Data from a Slave
从Slave 备份Raw数据
为了保证复制文件的一致性,备份raw data files在你的复制的slave 环境,当你的slave关闭的时候
如果MySQL server 仍旧在运行,后台任务仍旧在更新数据文件,特别是那些调用存储引擎的后台进程
比如InnoDB.
在InnoDB,那些文件可以解决在crash recovery的时候,但是当slave server 在备份的时候被关闭
不影响master上的执行 ,就利用这个特性。
关闭server 备份文件:
1.关闭slave server
shell> slave:/root# mysqladmin -uroot -p’kjk123’ shutdown
shell> tar cf /tmp/dbbackup.tar ./data
3.启动MySQL server
shell> mysqld_safe &
通常 你可以备份整个数据目录,如果你需要回复数据(比如,salve的failure).除了slave的数据,
你也需要备份slave的状态文件,master info 和relay log info 这些文件需要继续复制在你恢复slave的数据后。
如果你丢失了relay logs 但是仍旧有relay-log.info文件,你可以检查它 来确定已经多久了SQL thread
应用master 的binary log.
然后你可以使用CHANGE MASTER TO 告诉slave 来重新读取binary logs从这个点开始,
这也需要master上仍旧存在这些binary log日志。
如果slave 在复制LOAD DATA INFILE语句,你也需要备份任何的SQL_LOAD-* files
slave需要这些文件来继续复制任何的中断的LOAD DATA INFILE操作。
17.3.1.3 Backing Up a Master or Slave by Making It Read Only
备份只读的Master或Slave数据
有可能备份master或者slave server 在一个复制阶段通过需要一个全局的read lock 和
操作一个 read_only 的系统变量来改变read-only的状态 进行备份:
1.确保server 只读,让它只处理检索和阻止更新
2.执行备份
注意:
这章的介绍,比如mysqldump 你不能尝试使用那些指令来做一个2进制的copy,
因为server 可能仍旧在修改内存里的data cached 没有刷会磁盘。
下面的操作 描述了如何对master和slave 执行,两种情况的讨论,假设你有下面的复制步骤:
一个master server M1
a slave server S1 M1是它的master
一个client C1 连接到M1
一个client C2 练级到S1
在任何一个场景, 语句需要得到全局的读锁和操作一个read_only 变量是需要被执行的
来备份和不扩大到任何的slave
场景 1: 用read-only 备份master
设置master M1到read-only 模式通过执行下面的语句
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SET GLOBAL read_only = ON;
当M1 是出于只读模式,下面的属性是真实的:
请求update 通过C1 到M1 会被堵塞,因为server 是只读模式
请求从C1发送到M1 会成功
在M1上做备份是安全的
4.在S1上做备份是不安全的,因为server 仍旧在运行,
可能处理binary log或者更新请求来自客户端C2
当M1 是只读,执行备份,比如 你可以使用mysqldump
当backup 操作在M1上已经完成,恢复M1 到它的正常状态通过执行下面的语句:
mysql> SET GLOBAL read_only = OFF;
mysql> UNLOCK TABLES;
尽管你在M1上执行了系安全带的备份(至于备份而言),
这不是最佳的性能,因为客户M1被阻止执行更新
场景2: 在slave上只读备份:
把SLAVE S1 设置为只读模式通过执行下面的语句:
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SET GLOBAL read_only = ON;
当S1 至于只读模式后,下面的属性是真实的:
master M1 会继续操作, 因此在master上备份是不安全的
slave S1 是停止的,在slave S1上备份是安全的
这些特性对于一个流行的备份方案提供依据:
一个slave 执行一个备份用一段时间不是问题,因为它根本不影响整个网络,
但是系统使仍旧运行的在备份期间。特别是,客户端可以仍旧执行更新在master上,这是通过在备份活动不受影响。
当S1 是只读的,执行备份比如,你可以使用mysqldump
当S1上的备份操作完成后,恢复S1 到正常状态通过执行下面的语句:
mysql> SET GLOBAL read_only = OFF;
mysql> UNLOCK TABLES;
17.3.2 Using Replication with Different Master and Slave Storage Engines
使用复制在使用不同的master和slave的存储引擎
对于复制进程它不关心是否在master上的源表和复制的表在slave上使用不同的引擎,
事实上, default_storage_engine and storage_engine 系统变量不是复制的。
这个提供了大量的好处在复制过程中,利用不同存储引擎的优势用于不同的复制从场景。
比如,在一个典型的扩展方案,你要使用一个InnoDB表在master上利用它的事务功能,
但是在slave上使用MyISAM上事务支持是不需要的,因为数据是只读。当在一个数据记录的环境使用复制,
你需要使用归档的存储引擎在slave上。
配置不同的引擎在master和slave上依赖如何设置初始化的复制过程:
1.如果你使用mysqldump 来创建master的数据库快照,你可以编辑dump文本文件来改变每个表的引擎类型
另外的替代是关闭存储引擎选项, 你不使用存储引擎在你salve上导入数据之前。
比如,你可以使用–skip-federated 选项在你的slave上来关闭联邦引擎。
如果一个特别的引擎不存在,MySQL 会使用默认的引擎,通常是MyISAM.
(这个需要NO_ENGINE_SUBSTITUTION SQL模式不启用)
如果你想用这种方式关闭其他的引擎,你需要考虑创建一个特别的2进制备份用于slave,只支持你需要的引擎)
2.如果你使用一个raw 数据文件(a binary backup)来配置slave,你不需要改变初始表的格式。
代替的是,使用ALTER TABLE 来改变表的类型在salve启动之后
3.对于新的master/slave环境配置 ,master里没有表数据,避免在创建新表的时候指定引擎
如果你已经运行了复制解决方案,你需要转换存在的表为另外的引擎,遵循下面的步骤:
1.停止slave
mysql> STOP SLAVE;
这个可以让你改变存储类型在中断的情况
2.Execute an ALTER TABLE … ENGINE=’engine_type’ for each table to be changed.
3.Start the slave replication process again:
mysql> START SLAVE;
尽管 default_storage_engine 变量没有被复制,要知道 CREATE TABLE and ALTER TABLE 语句
包括了存储指定的会复制到slave.
mysql> ALTER TABLE csvtable Engine=’MyISAM’;
上面的语句会复制到slave,slave上的存储引擎会被覆盖为 MyISAM,
尽管你先前改了表的存储引擎。
如果你要保持master和slave的存储引擎不同,你需要小心使用default_storage_engine变量
17.3.3 Using Replication for Scale-Out
使用复制来扩展
你可以使用复制来扩展解决, 也就是说,如果你要分散数据库的查询负载到多个服务器上,
由于一些局限性的原因。
因为复制工作分布在一个master 到多个slaves,使用复制用于扩展适用于有大量read 和小量写的环境。
大多数的网站适合这种场景,当用户浏览网站时,读文章,posts,查看产品。
更新只发生在会话管理的时候,当购买或添加评论/信息论坛。
复制在这种情况可以分散读操作, 但是仍旧可以让你的master接收写的请求。
如果你的代码的一部分,是负责数据库的访问已被正确提取/模块化,
将它与复制的设置应该是非常顺利和容易, 改变你的数据库的实施访问 发送所有的写到master,
发送所有的读到master或者salve. 如果你的代码没有这个抽象层次,设置一个复制系统给你提供机会和动机
来清理它。 首先创建一个包装库或模块,实现了以下功能:
safe_writer_connect()
safe_reader_connect()
safe_reader_statement()
safe_writer_statement()
safe_ 没个函数名字意味着函数照顾 处理所有的错误条件,你可以使用不同的名字。
最重要的是有统一的接口用于连接,读取,和写。
然后把你的客户端代码使用包装库,这可能是一个痛苦和可怕的过程开始,
但从长远来看回报,所有的应用使用方法只描述了利用master/slave的配置,
一旦调用了多个slave. 代码是很容易维护.
如果你写了大量的代码, 你可能需要自动化的转换方法使用replace功能 配备标准的MySQL的分布,
或者写你自己的脚本.
17.3.4 Replicating Different Databases to Different Slaves
复制不同的数据库到不同的slaves
有很多办法,在你只有一个单独的master 需要复制不同的数据库到不同的slaves.
比如, 你可能需要分散不同的sales数据到不同的部门来帮助分散负载在数据分析的时候
你可以通过配置master 和slave,然后限制bianry log语句在每个slave上通过–replicate-wild-do-table
配置在每个slave上。
重要:
你不能使用–replicate-do-db 当基于语句复制时候,这个选项的影响根据数据库是当前选择不同(跨库访问)
然而,你可以安全的使用–replicate-do-db用于如果你是基于行复制的,
这种情况下你选择的数据库不影响操作。
比如, 你可以配置每个slve如下,在启动slave前:
Replication slave 1 should use –replicate-wild-do-table=databaseA.%.
Replication slave 2 should use –replicate-wild-do-table=databaseB.%.
Replication slave 3 should use –replicate-wild-do-table=databaseC.%.
每个slave 在这个配置里接收整个Binary log 从master, 但是只执行包括在 –replicate-wild-do-table
匹配的表
如果你有数据 必须同步到slaves在复制启动前, 你有大量的选择:
1.同步所有的数据到每个slave, 然后删除数据库,表,或者两者
2.使用mysqldump 来创建一个单独的dump文件为每个数据库, 加载到每个slave
17.3.5 Improving Replication Performance
改善复制性能:
当大量的slaves 连接到master,负载,尽管最小化,仍旧在增加,
因为每个slave使用一个连接到Master. 每个slave必须接收到master binary log 的完整的copy
master上的网络负载也会增加 瓶颈。
如果你使用大量的slaves连接到一个master,那个master一直忙于处理请求,那么你需要改善复制的性能。
一种方式来改善性能是增加更深的复制结构 让master 只复制到一个slave,
然后 其他的slave 连接到这个主的slave 来实现它们的复制需求
你必须配置Mysql实例如下:
1.master 1号 是primary master 所有的改变和更新被写入数据库, 这个server 必须启用binary logging
2.master 2号 是master1号的slave,提供复制功能到剩下的slaves在一个复制结构里。
Master 2 是唯一一个允许连到master1的机器,Master 2也启用了binary logging,
–log-slave-updates 选项 可以让从Master 1的复制命令也写到Master 2的binary log
log-slave-updates这个参数用来配置从服务器的更新是否写入二进制日志,这个选项默认是不打开的,但是,如果这
个从服务器B是服务器A的从服务器,同时还作为服务器C的主服务器,那么就需要开发这个选项,这样它的从服务器C才
能获得它的二进制日志进行同步操作
上面的解决方案降低了客户端的负载和primary master 的网络负载,会整理改善primary master
如果你的slaves 很难跟上主的复制过程,这里有大量的方法:
1.如果可能的话, 防止relay log 和数据文件在不同的磁盘
2.如果slave明显的慢于master,你需要分散压力 复制不同的数据库到不同的slaves
3.如果你的master 使用的事务你不关心你的slave 事务支持,使用MyISAM 或者其他的非事务引擎
4.如果你的slaves 不作为master,你有一个潜在的解决方案,以确保你可以带起master 在失败的时候,
那么你可以关闭–log-slave-updates.选项, 这个阻止了无发言权的slaves上写的事件记入到它们自己的binary log.
17.3.6 Switching Masters During Failover
切换Master 在Failover的时候
当使用GTIDs复制的时候,你可以使用mysqlfailover 提供的failover 在master 和slave 由于failure,
是有Mysql提供的功能,如果你使用mysqlfailover,你必须设置一个master 和一个或者多个salves;
你需要写一个应用或者脚本来监控master 是否它是或者的,指示slaves和应用切换到另一个master,
本节讨论一些问题时遇到这样的故障转移设置。
你可以告诉slave 来改变到一个新的master 使用CHANGE MASTER TO 语句,slave不检查master 上的数据库
是否和那些slave兼容, slave只是简单的开始读取和执行events 从master的新的binary log的制定的位置开始。
在failover 情况下,在group里所有的server 通常执行相同的events从相同的binary log 文件,
因此改变改变event的源头不影响数据库的结构和完整性,只要你小心做更改。
Slaves 应该带–log-bin选项运行不带–log-slave-updates。 以这种方式,
slave会变成一个master 在不需要重启slave mysqld的情况下.
在上面的图中,MySQL Master 持有master数据库, MySQL Slave是复制的Slaves,
Web Client 机器是执行数据库的读和写,Web Clients 执行只是读( 被slave 连接)
每个MySQL Slave(Slave 1,Slave 2和Slave 3) 是带–log-bin和不再–log-slave-updates的slave
log-slave-updates这个参数用来配置从服务器的更新是否写入二进制日志,这个选项默认是不打开的,但是,如果这
个从服务器B是服务器A的从服务器,同时还作为服务器C的主服务器,那么就需要开发这个选项,这样它的从服务器C才
能获得它的二进制日志进行同步操作
–log-bin 开启binlog
因为从master 接收到的更新 slave是不写入到bianry log的除非–log-slave-updates 被指定,
每个slave上的binary log 初始是空的,如果MySQL Master 变的不可用,
你可以选择其中的一个slave成为Master.
slave不带–log-slave-updates 运行时为了防止slaves接收更新2次 ,如果你因为一个slave成为master
如果Slave 1启用了–log-slave-updates, 它把任何的更新从Master收到的写入自己的binary log.
这意味着, Slave 2从之前的MASTER 改为Slave1 作为它的master,它可能接收到Slave1的更新,从之前的Master已经接
收的。
确保所有的Slaves 已经处理了relay log里的任何的语句,
在每个Slave上,执行stop slave TO_THREAD,(接收binary
log)
然后检查SHOW PROCESSLIST 的输出 直到你看到 Has all relay log ,当这个真的对于所有的slaves,
它们可以被配置成新的组织。 在Slave slave1 变成master,执行STOP SLAVE and RESET MASTER.。
另一方面 slave 2和slave 3,使用STOP SLAVE 和CHANGE MASTER TO MASTER_HOST=’slave1’
(slave1 表示slave1 真实的地址) 使用CHANGE MASTER TO,增加所有的信息关于如何连接到Slave 1
从Slave2 或者Slave 3(用户,密码,端口). 当执行CHANGE MASTER TO 语句,
这里没有必要来指定slave1的binary log 文件或者log posistion 来开始读
因为 第一个binary log和位置是默认的。最后,执行start slave在slave 2和slave 3上。
一旦新的复制安装到位,你需要告诉Web Client 来直接的陈述到Slave 1
Web Client 发送所有的更新语句给Slave 1 被写入到slave 1的binary log,
slave 1包含了发送给slave 1每次的更新语句 自动之前的master 挂了之后
当Master 再次变的可用,你需要改变Slave1 ,在slav2 和slav3上执行CHANGE MASTER TO 语句
从先前的Master 变为salve1(slave1变为Master)
为了再次创建master(因为它是最重要的机器),使用前面的过程 当salve1 变为不可用,
Master 需要变为一个新的Master,在这个过程中,不要忘记运行RESET MASTER 在slave1 ,slave2和slave 3称为master
你需要当心这里没有不同步在slave之间, 尽管他们共享相同的master,
但是有一些salve可能被认为 比其他slaves超前了。
这意味着,在有些情况下 在前面的例子中列出的程序可能不象预期的那样工作
17.3.8 Semisynchronous Replication
半同步复制
除了内置的异步复制,MySQL 5.6 支持一个半同步复制通过插件。这个章节描述了
什么是半同步,它是怎么工作的。以下部分包括管理接口半同步复制和如何安装,配置和监控
MySQL 复制默认是异步的,master 把event 写入到binary log 但是不知道 是否slave已经接收到了或者处理了他们。
在异步复制下,如果master crashes,已经提交的事务可能不会传输到任何的slave.
因此,在这种情况下,主从切换可能会导致故障转移到服务器丢失相对于主的那些事务。
半同步复制,可以用来作为一种替代异步复制:
2.如果在你的master 端 半同步复制被启用,需要至少一个半同步的slave,
一个thread 在master 上执行事务提交堵塞指导提交成功,至少一个半同步的slave 承认它收到了事务的所有的
events,否则会报超时
4.如果超时发生没有任何的slave确认事务,master会转换为异步复制。如果有任何一个异步的slave追上,
master 回到半同步复制
5.半同步复制必须master和slave都启用,如果半同步在master上关闭了,或者master启用了但是slaves没有,
master仍旧使用异步复制。
当复制被阻塞( 当master执行commit后等待一个salve 确认) 它不返回给SESSION已经执行的事务。
当block借宿后,master返回给session,master可以处理其他的语句。在这个时间点,事务已经在master上提交,
至少一个slave已经确认收到了event.
堵塞也发生在回滚 你写入binary log, 发生在当一个事务修改了非事务表被回滚。
回滚的事务被记录在event 尽管它不影响事务表,因为对非事务表的修改不能被回滚,必须发送到slaves.
语句不在事务上下文中出现(也就是说,没有事务以START TRANSACTION或者SET autocommit=0开始)
自动提交被启用,每个语句隐式的提交。 在半同步环境里, master 阻塞在每个语句提交后,正如它的显式事务提交。
为了了解 半同步复制的意思,相比异步和全同步复制:
1.在异步环境, master 把它的events写入到它的binary log,slave 请求它们。
这里没有强制任何event 必须到达每一个slave
2.全同步复制, 当master 提交一个事务,所有的slaves必须都提交事务 在master 返回SESSION 前
这个缺点是可能会有大量的延迟来完成一个事务。
它不等待所有的slaves 来承认收到,它只是需要接收,不需要slave执行和提交。
相比较异步复制,半同步复制提高了数据的完整性。当一个commit 成功返回时,就意味着数据已经存在至少2个地方。
如果master 提交了但是crash发生了,当master在等待一个slave的确认,可能事务没有到达任何一个slave.
半同步复制也设置了速度限制在繁忙的session上通过限制master发送到slave的速度。
当一个用户是繁忙的, 就会慢下来,在一些调度环境有用。
半同步复制 有一些性能影响,因为提交变慢了 由于需要等待slaves.
这是为增加数据完整性的权衡.
17.3.9 Delayed Replication