mysql从3.23开始提供复制功能,复制指将主库的ddl和dml操做经过binlog文件传送到从库上执行,从而保持主库和从库数据同步。mysql支持一台主库同时向多台从库复制,从库同时也能够做为其余从库的主库,从而实现级联复制功能。mysql复制功能至关于oracle数据库的逻辑dg功能。mysql
mysql复制原理大体以下:linux
1)mysql主库事务提交时会把数据变动做为event记录在binlog文件中,mysql主库的sync_binlog参数控制binlog日志刷新到磁盘。sql
2)从库收集主库binlog中的event到从库的中继日志relay log中,以后从库根据中继日志重作数据变动操做,经过逻辑复制来达到与主库同步的目的。数据库
基本步骤以下:安全
l 主服务器将更新写入binlog文件,并维护文件的一个索引以跟踪日志的循环。服务器
l 从库复制主库的binlog event到本地中继日志(relay log)。网络
l 从库sql线程重放中继日志。session
将从服务器设置为复制主服务器的数据后,它将链接主服务器并等待更新过程。若是主服务器失败,或者从服务器和主服务器之间失去联系,那么从服务器将保持按期尝试重连,直到它可以继续监听为止。由--master-connect-retry选项控制着重试间隔,默认60s。架构
mysql经过3个线程完成复制功能:其中binlog dump线程跑在主库上,io线程和sql线程跑在从库上。当从库启动复制(start slave)时,从服务器首先建立io线程链接主库,主库随后建立binlog dump线程读取event发送给io线程,io线程获取到event后更新到从库中继日志relay log中,以后从库sql线程根据relay log内容在从库从作操做。从而完成mysql复制功能。由此可知,这样读取和执行语句将被分红两个独立的任务。mysql复制结构如图:oracle
主库经过show processlist命令能够看到binlog dump进程,以下:
mysql> show processlist \G;
*************************** 1. row ***************************
Id: 125
User: root
Host: localhost
db: test
Command: Query
Time: 0
State: init
Info: show processlist
*************************** 2. row ***************************
Id: 127 --线程127为主库复制线程
User: rep1
Host: 192.168.80.136:44889
db: NULL
Command: Binlog Dump
Time: 16991
State: Master has sent all binlog to slave; waiting for binlog to be updated --已经发送了全部binlog,等待更新
Info: NULL
2 rows in set (0.00 sec)
从库经过show processlist命令能够看到io线程和sql线程,以下:
mysql> show processlist \G;
*************************** 1. row ***************************
Id: 4
User: root
Host: localhost
db: test
Command: Query
Time: 0
State: init
Info: show processlist
*************************** 2. row ***************************
Id: 7 --从库中的io线程
User: system user
Host:
db: NULL
Command: Connect
Time: 17079
State: Waiting for master to send event --等待主库发送日志状态
Info: NULL
*************************** 3. row ***************************
Id: 8 --从库sql线程
User: system user
Host:
db: NULL
Command: Connect
Time: 17107 --能够显示从服务器比主服务器滞后多长时间
State: Slave has read all relay log; waiting for the slave I/O thread to update it --已经应用了全部relay log
Info: NULL
3 rows in set (0.00 sec)
复制的做用:
复制有不少用途,好比备份、读写分离、软件升级、故障转移等。注意在mysql版本升级过程须要考虑到复制的兼容性问题。
mysql复制涉及到两种文件:binlog和relay log文件。其中根据binlog的不一样设置,mysql复制分为3中模式。
l 基于sql语句级别的复制。
l 基于行的复制
l 混合模式复制
1)基于SQL语句级别的复制
基于语句级的复制,复制将执行主库上所执行的语句,也就是说,从库执行的更新语句和主库执行的同样。基于语句的复制,优势有:
l 相对于基于行的复制,更简单,易实现。
l 数据库产生的二进制日志更少,传输占用带宽更少。
l 二进制日志可读性更好,mysqlbinlog能够方便读取binlog日志内容。
l 有利于排查问题,从库上执行和主库同样。
基于语句的复制,缺点有:
l 主库的某些操做不能正确复制到从库。
l 从库须要锁定更多记录。
l 负载、代价大的sql在从库上须要再次执行。
l 对于非核心功能支持有限。
2)基于行的复制
Mysql5.1开始支持基于行的复制,它的适用范围更广,也可靠地多。基于行的复制其格式比较难以理解。基于行的复制能够处理各类高级功能,好比存储过程、触发器等,若是你想更兼容高级功能,建议采用基于行的复制模式。
基于行的复制优势有:
l 全部改变均被复制,对比与基于语句的复制,这是一种更安全的方式。
l 更少的锁定。
l 对于mysql高级特性兼容良好,好比存储过程、触发器。
l 二进制日志更有利于恢复,由于binlog里记录了更为详细的数据库变动。
l 更容易发现数据的不一致。
基于行复制的缺点有:
l 产生更多的binlog日志。
l Binlog日志内容不易阅读,不方便使用mysqlbinlog工具解读。
l 要求主从表结构一致,这样限制了它的灵活性,由于生产环境有时须要临时修改从库表结构,提高从库为主库。
3)混合复制模式
默认采用基于语句的复制,一旦检测到触发了某些条件,则使用基于行的方式进行复制,这种设计完美的解决了语句级和行级复制的缺点,这也是建议采用的复制方式。
复制的3中常见架构:一主多从、级联复制、双主架构
1)mysql一主多从架构:解决主库读请求压力解决方案。
2)mysql级联架构:解决一主多从架构中主库io和网络压力,缺点时额外增长了主库到从库的应用延迟,其中master2能够设置为blackhold(黑洞)模式来缓解复制延迟。
3)双主复制/dual master架构:
4)双主级联复制架构:
复制相关参数设置:
1)slave_exec_mode
复制冲突解决和错误检测能够采用以下两种模式:
l Strict:默认
l Idempotent:忽略duplicate-key、no-key-found错误,通常在主主复制、环形复制等其余特殊状况下才使用,不推荐使用。
2)max_allowed_packet
默认设置过小,声场环境中建设设置为16m或更大,设置过小可能致使从库不能解释接收主库发送的包,主从库建议设置成同样的值,若是数据库存在大的blob字段,还须要考虑将这个值设置为更大。
3)复制过滤选项
请不要随意使用复制过滤选项,除非你真的有理由这么作,即便使用,也建议在从库进行设置。复制过滤选项主库上主要由参数binlog-do-db和binlog-ignore-db两个参数决定,通常不建议使用,很差的地方是他们可能致使你不能进行基于时间点的恢复或者丢失数据。
Binlog-do-db=db_name:
告诉主服务器,若是当前的数据库是db_name,应该讲更新记录到binlog,其余全部没有明确指定的数据库将被忽略。若是使用了该选线,你应该确保仅对当前数据库进行更新。
Binlog_ignore_db=db_name:
告诉主服务器,若果当前数据库是db_name,那么应该不记录更新到binlog。
在从库上对应有两个参数replicate-do-db和replicate-ignore-db,他们的做用相似于主库设置的binlog-do-db和binlog-ignore-db的做用,不一样点仅在于设置地方不同。
*-do-db和*-ignore-db参数其实都仅仅是针对当前数据库,也就是说,若是咱们use到其余数据库上,而后执行了一条更新其余库的SQL,这些参数将不起做用。
如下是在从库上设置的一些参数:
--replicate-ignore-db=db_name
这个选线告诉从服务器不要复制默认数据库为db_name的语句。要想忽略多个数据库,能够屡次指定该参数,且每一个数据库只能使用一次。若是存在跨数据库更新而且不想复制这些更新,那么久不要使用了。
--replicate-ignore-table=db_name.tb1_name
它将告诉从服务器复制线程不要复制更新指定表的任何语句。要想忽略多个表,须要屡次指定该选项,且每一个表只能指定一次。该选项能够跨数据库更新。
--replicate-wild-ignore-table=foo%.bar%
它告诉从服务器线程不要复制匹配通配符模式的语句,要想忽略多个表,须要屡次指定该选项,且每一个表只能指定一次。该选项能够跨数据库更新。若是必定要指定过滤选项,建议以上参数中仅适用此参数设置。
若是要在session级别禁用复制特性,那么咱们能够在session级别设置变量set sql_log_bin=0,使当前的某些操做不被复制到从库。
4)slave_commpressed_protocol
请慎重对待跨集群复制,跨集群复制时能够采用slave_commpressed_protocol=1压缩传输数据,须要在主库进行压缩,在从库进行解压缩,由于压缩须要额外的cpu,所以须要评审cpu资源。
5)Read-only
能够考虑在从库上设置read-obly,以只读方式启动从库,要注意的是super权限用户依旧能够在从库更新。
6)slave-net-timeout
因为生产环境网络异常,即便show slave status输出正常,但此时可能也已经中止复制,slave-net-timeout默认设置1小时,对于生产来讲太长,很难及时发现网络问题,通常设置1分钟。
7)--slave-skip-errors
一般状况下,当出现错误时复制会中止,这个选项能够给你一次手动解决数据不一致问题的机会。当语句返回slave-skip-errors锁列问题时,该选线会告诉sql线程继续复制。
例如:--slave-skip-errors=1062,1053
--salve-skip-errors=all
8)skip-slave-start
Skip-slave-start能够在命令行下或配置文件中使用,目的是在mysql启动的时候不要启动slave,这在某些故障状况下颇有用。使用--skip-slave-start选项来启动从库,能够防止当从库启动时,sql线程开始工做。
复制相关文件:
1)中继日志:默认状况下中继日志使用host_name-relay-bin.nnnnnn形式命名,其中host_name表示主机名,nnnnnn表示编号。用连续的序列号来建立连续的中继日志文件。从服务器跟踪索引文件中目前正在使用的中继日志文件。中继日志索引文件命名为host_name-relay-bin.index。默认状况下,能够在从服务器的数据目录中建立这些文件。可使用--relay-log和--relay-log-index服务器选项覆盖默认文件名,强烈建议设置这两个参数,这主要有助于之后的迁移及故障处理。
中继日志文件与binlog格式相同,因此可使用mysqlbinlog工具读取中继日志文件内容。Sql线程执行中继日志中的event而且再也不须要中继日志后,会当即自动删除它。没有直接删除中继日志的机制,由于sql线程能够自动完成它。
2)状态文件:从服务器数据目录中存在两个与复制有关的文件,分别为master.info和relay-log.info,它们包含了show slave status语句输出显示的信息。状态文件保存在磁盘上,所以从服务器关闭时不会丢失状态文件。下次启动从服务器,读取这些文件以肯定从服务器已经从主库上读取了多少binlog日志,以及处理了本身的中继日志的成度。
由io线程更新master.info文件,master.info文件中和show slave status显示的列的对应关系以下表所示:
略。
由sql线程更新relay-log.info文件,relay-log.info文件中和show slave status显示的列的对应关系以下表所示:
略。
3)复制下的备份:
当备份从服务器的数据时,你还须要备份状态文件和中继日志文件。他们能够用来恢复从服务器后继续复制。若是丢失中继日志可是还存在relay-log.info文件,那么你能够经过检查该文件来确认sql线程已经执行的主服务器中的二进制日志文件程度。而后咱们可使用master_log_file和master_log_pos选项执行change_master命令来告诉从服务器须要从新从该点读取二进制日志。固然,binlog必须在主服务器上存在才能够。
4)mysql5.1中中继日志和状态文件并非crash-safe的,也就是说,他们默认是不会实时刷新到磁盘的,那么发生故障的状况下,文件的信息可能就是错误的,将会致使复制异常。Mysql5.5,那么能够设置如下选项来确保这些文件刷新磁盘的频率:
Sync_master_info=1
Sync_relay_log=1
Sync_relay_log_info=1
注意这些参数会带来必定开销,对于写频繁的应用,建议不要设置这些参数。
Mysql5.5还有一个参数:relay_log_space_limit,这个参数设置了全部中继日志可使用的空间阈值。意思是若是中间日志占用了空间超过了这个设置,那么io线程就会关闭,等待sql线程应用并删除中继日志释放空间。
复制环境经常使用的命令:
1)show master status命令查看主库状态:该命令用来提供主服务器binlog文件的状态信息,执行它须要super或replacation client权限。
mysql> show master status \G;
*************************** 1. row ***************************
File: dbking-bin.000004 --当前正在读取的binlog文件
Position: 1729 --读取binlog文件的位置
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
2)经过show slave status查看从库状态:该命令用于提供从库线程的关键参数信息。
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.80.133 --当前主服务器主机
Master_User: rep1 --被用于链接主服务器的当前用户
Master_Port: 3306 --链接主服务器端口号
Connect_Retry: 60 --“--master-connect-retry”参数的当前值
Master_Log_File: dbking-bin.000004 --io线程正在读取的主服务器binlog名称
Read_Master_Log_Pos: 1729 --io线程正在读取的主服务器binlog位置编号
Relay_Log_File: chavinking-relay-bin.000010 --sql线程当前正在读取和执行的中继日志名称。
Relay_Log_Pos: 714 --当前relay log文件,sql线程已经读取和执行的位置
Relay_Master_Log_File: dbking-bin.000004 --sql线程执行包含多个近期event的主服务器binlog名称
Slave_IO_Running: Yes --io线程运行状态,正常状态为yes
Slave_SQL_Running: Yes --sql线程运行状态,正常状态为yes
Replicate_Do_DB: --使用--replicate-do-db选项指定的数据库清单
Replicate_Ignore_DB: --使用--replicate-ignore-db选项指定的数据库清单
Replicate_Do_Table: <------------------------------------------------
Replicate_Ignore_Table: 使用期间这些选项指定的表清单
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table: ------------------------------------------------->
Last_Errno: 0 <--多数最近被执行的查询返回错误数和错误消息,Last_Errno为0
Last_Error: 而且Last_Error为null,意味着没有错误,不然从库错误日志会被记录>
Skip_Counter: 0 --最近被使用的用于sql_slave_skip_counter的值
Exec_Master_Log_Pos: 1729 --来自主服务器binlog、由sql线程执行的、上一个时间的位置 (relay_master_log_file).主服务器中binlog中的 (relay_master_log_file,exec_master_log_pos)对
应中继日志中的(relay_log_file、relay_log_pos)。
Relay_Log_Space: 1056 --全部原有中继日志结合起来总大小
Until_Condition: None <------------------------------
Until_Log_File: 在start slave语句的until子句中指定的值
Until_Log_Pos: 0 ------------------- --->
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0 --是从库落后多少的一个指示。通常是基于同一集群内网主从集群,此值应为 0。本字段用于测量从库sql线程和从库io线程之间时间差距,单位以秒计算
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 9b92b2a8-b7e0-11e6-81e4-000c29fa5a95
Master_Info_File: /usr/local/software/mysql-5.6.24-linux-glibc2.5-x86_64/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
1 row in set (0.00 sec)
3)change master命令
这个命令在从库中执行,能够配置所要链接的数据库信息,以及从哪里开始同步。经常使用语法以下:
change master to
master_host='xxx.xxx.xxx.xxx',
master_port=3306,
master_user='replic_user',
master_password='password',
master_log_file='log file name',
master_log_pos=position;
咱们能够在正在运行的从库中动态修改链接主库的信息。例如修改密码:
mysql>stop slave;
mysql>change master to master_password='password';
mysql>start slave;
此更改没有必要指定没有变动的参数。
参数解释:
master_host和master_port:指定主库ip和端口。
master_log_file和master_log_pos:指定主库binlog名称和位置
master_user和master_password:指定复制用户的帐号和密码,从库将使用这个帐号去链接主库,因此主库要为这个帐号授予replication slave的权限。
change master:会删除全部中继日志文件并启动一个新的日志,除非你指定了relay_log_file或relay_log_pos,这种状况下,中继日志将被保持。
change master to:会改变从库master.info和relay-log.info文件内容。
4)start slave和stop slave命令
stop salve命令能够中止io线程和sql线程。而咱们经常使用的start slave语句有3种经常使用用法:
A)start slave不带任何参数
不包含任何参数的start slave命令会同时启动2个从库线程。io线程从主服务器读取查询,并把他们存储到中继日志文件中;sql线程读取中继日志文件,并应用复制。start slave要求super权限。若是start slave成功地启动了从库线程,则会返回,不会出现错误。可是,即便如此,也有可能出现从库线程启动了可是又中止了。start slave对此不发生任何警告,必须检查从库错误日志肯定错误缘由,或者使用show slave status命令检查io线程和sql线程运行状态。
B)start slave启动单个服务器线程
start slave io_thread;
start slave sql_thread;
C)start slave指定到某个位置自动中止
能够在start slave命令中添加until子句,指定从库应启动并运行,直到sql线程达到主服务器二进制日志中一个给定点为止。当sql线程执行到该指定点,它会自动中止。若是在该语句中指定了sql_thread选项,它会仅仅启动sql线程,不然它会同时启动2个线程。通常状况下,这种操做咱们仅操控sql线程。语法以下:
start slave [sql_thread] until master_log_file='binlog_name',master_log_pos='binlog_post'
5)show slave host命令在主库上运行能够查询从库信息