暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL复制原理、参数、状态检查

DBA小记 2020-10-27
570

1、  复制原理

1)在Slave 服务器上执行start slave命令开启主从复制开关,开始进行主从复制。

2)此时,Slave服务器的IO线程会通过在master上已经授权的复制用户权限请求连接master服务器,并请求从执行binlog日志文件的指定位置(日志文件名和位置就是在配置主从复制服务时执行change master命令指定的)之后开始发送binlog日志内容

3Master服务器接收到来自Slave服务器的IO线程的请求后,二进制转储IO线程会根据Slave服务器的IO线程请求的信息分批读取指定binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的IO线程。返回的信息中除了binlog日志内容外,还有在master服务器端记录的新的binlog文件名称,以及在新的binlog中的下一个指定更新位置。

4)当Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件(MySQL-relay-bin.xxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容

5Slave服务器端的SQL线程会实时检测本地Relay Log IO线程新增的日志内容,然后及时把Relay LOG 文件中的内容解析成sql语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行应用这样sql语句,并在relay-log.info中记录当前应用中继日志的文件名和位置点

 

2、  复制相关参数

2.1  基本参数

 

--server_id

是必须设置在master和每个slave上的唯一标识ID,其取值范围是1~4294967295之间,且同一个复制组之内不能重复。.

 

--server_uuid

server_uuid会在GTID复制中使用。当MySQL启动之后,会首先到数据文件目录下的auto.cnf中寻找是否有指定的server_uuid,如果没有找到,则自己生成一个server_uuid并保存到这个文件中。

 

--log_slave_updates

该参数用来控制是否将收到的主库的更新数据的语句也记录在slave自己的bin log中。正常情况下是不需要记录的,但如果是想创建级联复制关系,比如A->B->C,这其中B既要作为A的从库,也要作为C的主库,则需要既开启log-bin参数,也要开启log_slave_updates参数。(开启方式:log_slave_updates=1)

 

--relay-log

中继日志,该参数用来指定relay-log文件的基础名称,默认的名称为host_name-relay-bin.xxxx,其中的xxxx结尾是依次递增的数字。

 

--replicate-do-db

该参数用来指定需要复制的库。在基于语句复制的环境中,指定该参数之后,则slave的SQL thread进程只会应用在本数据库下的对象相关的语句。如果有多个数据库需要复制,则这个参数要使用多次。但如果是涉及到跨库操作语句,则复制会丢失。(指定只复制sourse数据库:replicate-do-db=course)

 

--replicate-ignore-db

 该参数决定了忽略指定数据库的复制,其行为和replicate-do-db正好相反。  

 

--replicate-do-table=db_name.tbl_name

 通过该参数告知slave的SQL thread仅复制指定表上的数据。如果有多个表,则该参数要使用多次。

 

--replicate-wild-do-table=db_name.tbl_name

 通过该参数告知SQL的SQL thread仅复制符合匹配的表,可以使用_和%作为通配符。比如replicate-wild-do-table=foo%.bar%表示复制以foo开头的数据库下所有bar开头的表数据。如果是relpicate-wild-do-table=foo%.%,则表示复制foo开头的所有表的数据,也复制CREATE/DROP/ALTER DATABASE foo开头的命令。

 

--slave-parallel-workers

该参数决定了slave上启动多少个SQL thread线程来并行应用数据的。默认值是0代表不允许并行,取值范围可以是0~1024。当数据量较大,slave和master出现数据延迟较大时,可以考虑调大该值来优化同步效率!(开启方式:slave-parallel-workers=10)

 

--skip-slave-start

 该参数决定了在MySQL启动时是否先不启动slave线程,即暂停复制。(开启方式:需要在[mysqld]中指定 skip-slave-start=1)

 

--slave-parallel-type

 该参数决定了当启动了并行之后,采用什么粒度的并行方式。默认值database表示按照不同的数据库执行并行,LOGICAL_CLOCK则表示按照在binlog中的一组提交的事物作为并行粒度。

 

--slave-skip-errors=[err_code1,err_code2,...|all|ddl_exist_errors]

 该参数决定了当slave的SQL thread执行过程中碰到何种错误时可以忽略并继续接下来的数据复制。正常情况下,当有错误发生时,复制会停止而且需要人工干预修复才能继续进行。除非非常自信可以忽略某些错误,否则不要使用这个参数,不然会导致复制执行正常,但其实内部的数据已经完全不一致!  (开启方式:slave-skip-errors=1062)

 

--sql_slave_skip_counter

 代表在非GTID复制环境下,通过设置此参数来跳过复制事件。设置完该参数并非立即生效,而是等待下次start slave命令的执行生效,并将该参数再次设置为0。

2.2binlog二进制日志参数

--log-bin[=base_name]

 该参数表示是否开启binary log。默认情况下MySQL会使用host_name-bin.xxxx作为文件的名字,其中xxxx是以数字递增的后缀。如果该参数指定了base_name,则二进制会以base_name.xxxx来命名。

--binlog-do-db=db_name

 

--binlog_format=row

binlog的格式,有statement,row、mixed

 

log_bin=/mysql/log/3306/binlog/mysql-bin

log_bin_index=/mysql/log/3306/binlog/mysql-bin.index

 

--binlog_row_query_log_events=on

二进制日志中记录更详细的SQL操作

 

--sync_binlog=1

默认,MySQL每次提交事务之前会将二进制同步到磁盘上

 

--innodb_flush_log_at_trx_commit=1

用来控制从左日志刷新到磁盘的策略。该参数默认为1,每次事务提交时必须调用一次fsync操作,把log Buffer写入log file,并且flush到磁盘。

还可以设置该参数的值为0和2,0表示事务提交时不进行写入重做日志操作,这个操作仅在master thread中完成,而在master thread中每一秒会进行一次重做日志文件的fsync操作。2表示事务提交时将重做日志写入重做日志文件,但仅写入文件系统的缓存中,不进行fsync操作。在这个设置下,当MySQL数据库放生宕机而操作系统不发生宕机时,并不会导致事务的丢失,而当操作系统宕机时,重启数据库后会丢失未从文件系统缓存刷新到重做日志文件的那部分事务。

 

--log_bin_trust_function_creators=1

默认为0,该参数是同步函数和存储过程

 

--max_binlog_size=2048M

默认为1024M

 

--expire_logs_days=7

binlog保留多少天,看具体安排

 

--binlog_cacahe_size=1M

默认32K,binlog缓存大小,设置时要当心,根据业务繁忙情况建议1-4M。

 

--innodb_support_xa=1

这个参数是在主库上设置的,默认自动开启。分布式事务参数。

这个参数确保事务日志写入binlog的顺序是与事务的time-line是一致的。

 

2.3 中继日志参数

relay_log=/mysql/log/3306/relaylog/mysql-relay.log

--relay-log-recover=1

该参数为了实现,I/O thread crash safe #IO线程安全

打开replication中继日志崩溃恢复模式,replication支持中继日志的自我修复功能。

当slave从库宕机后,如果replay-log发生损坏,导致一部分中继日志没有处理,就自动放弃未执行的replay-log。

在slave崩溃或正常启动时,未应用完的relay_log会被删掉,重新从master请求binlog再次生成自上一个完全应用点后的位置拉取relay_log

 

--relay_log_info_repository=table

该参数为了实现,SQL thread crash safe#SQL线程安全

默认是file,SQL线程的数据回放是写数据库操作,relay-info是写文件操作,这2个操作很难保证一致性,relay-info将写入到 mysql.slave_relay_log_info 这张表。

 

--master_info_repository=table

默认是file,IO线程也是接受一个个的event,将接收到的event,通过设置参数#master_info_repository可以将master-info信息写到什么位置,性能上比设置为file有很高的提升,可靠性也得到保证。

设置为table后,master-info将信息保存到mysql.slave_master_info

 

2.4 复制过滤参数

主:

binlog-do-db=db_name

binlog只把该库的操作记录到binlog,每一行一个数据库,多个数据库需要另起行

binlog-ignore-db=db_name

表示忽略某个数据库,除了这个数据库之外都复制,每一行一个数据库,多个数据库需要另起行

 

从:

replicate_do_db=db_name

只复制某个库,每个库一行,多个库需要另起行

replicate_do_db=db_name

不复制某个库,每个库一行,多个库需要另起行

replicate_do_table=table_name

只复制某个表

replicate_wild_do_table=table_name

解决跨库更新问题,需要与replicate_do_table 同时使用

replicate_ignore_table

不复制某个表

replicate_wild_ignore_table

解决跨库更新问题,需要与replicate_ignore_table同时使用

原因是,设置relicate_do_db或relicate_ignore_db后,MySQL执行sql前检查的是当前默认的数据库,所以跨库更新语句会在slave上被忽略。

 如果从库是要在线复制过滤,stop slave;     

CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('erp_ivedeng_com.T_BRAND','erp_ivedeng_com.T_DEPARTMENT_FEE_ITEMS'); 

replicate_rewrite_db=fandb->dudb  

复制到不一样名字的从库

replicate_rewrite_db=a->b 

多条要写多个

 

3、  检查复制状态方法

使用show slave status\G,查看slave的复制状态。

--masterbin_logrelay_log信息

Master_Host:172.16.86.150

Master_User:repl

Master_Port:3306

Master_Log_File:mysql-bin.000020

Read_Master_Log_Pos:1518

Relay_Log_File:mysqld-relay-bin.000022

Relay_Log_Pos:1681

Relay_Master_Log_File:mysql-bin.000020

 

--Slave_IO_State

代表当前slave的状态。

 

--Slave_IO_Running

代表负责读取主库bin log的IO线程是否是运行状态,正常情况下应该是YES。

 

--Slave_SQL_Running

代表负责执行备库relay log 的SQL线程是否是运行状态,正常情况下应该是YES。

 

--Last_IO_Error

代表最后一次IO线程所发生的错误,正常情况下应该是空,代表没有错误。

 

--Last_SQL_Error

代表最后一次SQL线程所发生的错误,正常情况下应该是空,代表没有错误。

Seconds_Behind_Master

“代表备库的SQL线程比主库的bin log晚多少秒。0代表目前没有复制延迟。”

通过show slave status查看到的Seconds_Behind_Master,从字面上来看,他是slave落后master的秒数,一般情况下,也确实这样,我们可以通过Seconds_Behind_Master数字查看slave是否落后于master,但是在一些环境中,他确会让我们产生幻觉。

http://dev.mysql.com/doc/refman/5.5/en/show-slave-status.html中,对Seconds_Behind_Master的有一句话阐述如下:

In essence, this field measuresthe time difference in seconds between the slave SQL thread and the slaveI/O thread.

很清晰的表明,该值是SQL thread I/O thread.之间的差值。

当在很快的网络连接情况下,I/O thread. 能很快的从masterbinlog中同步sqlslaverelay-log里,这样,这个值就能基本确定的slave落后master的秒数

当网络环境特别糟糕的情况下,这个值确会让我们产生幻觉,I/O thread同步很慢,每次同步过来,SQL thread就能立即执行,这样,我们看到的Seconds_Behind_Master0,而真正的,slave已经落后master很多很多。这时业务部门的同志们就会抱怨slavemaster数据不对,而你看到的Seconds_Behind_Master确为0,你就会非常的郁闷了。

其实这个时候,可以看下masterslave就能很好的确定这期间的原因。

可以通过在主上show master status\GPosition,和从执行show slave status\G Read_Master_Log_PosExec_Master_Log_Pos进行比较得出复制是否能跟上主的状态。

 

总结:

根据relaylog中读到的最后一条binlog timestamp sql thread 执行的最新一条binlog timestamp的差值决定。

为什么使用binlog的日志而不是系统时间,是为了保证主从机器系统时间不一致的时候也能得到正确的结果。

 

--Master_Log_file,Read_Master_Log_Pos

代表IO线程在主库bin log中的坐标位置。

 

--Relay_Master_Log_FileExec_Master_Log_Pos

代表SQL线程在主库bin log中的坐标位置。

 

--Relay_Log_File,Relay_Log_Pos

表示SQL线程在备库relay log中的坐标位置。

--SHOW PROCESSLIST

在主库可以通过执行SHOW PROCESSLIST命令查看主库的bin log日志生成进程

 

 


文章转载自DBA小记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论