mysql复制学习笔记

复制

主从复制原理

1.master将改变的数据记录在本地的二进制日志中,binary,该过程称为二进制事件

2.slave将master的binary log拷贝到自己的中继日志文件relay log

3,中继日志事件将数据读取到自己的数据库中

复制异步的,串行化的,有延迟

master配置,在my.cnf的[mysqld]节点

server-id=1

log-bin=“bin log全路径及文件名”

log-error=“错误日志文件名”

binlog-ingore-db=mysql

binlog-do-db=test

授权从数据库

grant replaction slave,reload,super on *.* to user@192.168.2.8% identified by “密码”

flush privileges

show master status查看相关信息,得到file和position值,在slave的配置中会用到

 

slave 配置,在my.cnf的[mysqld]节点

server-id=2

log-bin=可以写相对路径

replicate-do-db=test

授权哪台机子是自己的主计算机

change master to

master_host='ip'

master_user='sss'

master_password='sssdd'

master_port='122'

master_log_file='上面保存的文件名sssd-bin.001'

master_log_pos='上面保存的位置107'

 

stop slave ;start slave;show slave status

在mysql5.5版本中可能会出现错误,如果发现主从的server id相同,先stop slave再用set global server-id=2,再啥start slave

 

当从库执行完成当前中继日志后relay log中的事件后,SQL线程会自动删除当前中继日志文件relay log。

 

 

mysql是如何保持主备一致的

备库B跟主库A之间维持了一个长连接,主库A内部有一个线程,专门用于服务备库B的这个长连接,一个事务日志同步的完整过程是这样的:

1、在备库B上通过change master命令设置主库A的ip,端口、用户名、密码,以及要从哪个位置开始请求binlog,这个位置包含文件名和日志偏移量。

2、在备库B上执行start slave命令,这时备库会启动两个线程io_thread和sql_thread,其中io_thread负责与主库建立连接

3、主库A校验完用户名、密码后,开始按照B库传过来的位置,从本地取binlog发给B

4、备库B拿到binlog后,写到本地文件,称为中转日志或中继日志

5、sql_thread读取中继日志,解析日志里的命令,并执行

 

 

但是,双 M 结构还有一个问题需要解决。

业务逻辑在节点 A 上更新了一条语句,然后再把生成的 binlog 发给节点 B,节点 B 执行完这条更新语句后也会生成 binlog。(我建议你把参数 log_slave_updates 设置为 on,表示备库执行 relay log 后生成 binlog)。

那么,如果节点 A 同时是节点 B 的备库,相当于又把节点 B 新生成的 binlog 拿过来执行了一次,然后节点 A 和 B 间,会不断地循环执行这个更新语句,也就是循环复制了。这个要怎么解决呢?

从上面的图 6 中可以看到,MySQL 在 binlog 中记录了这个命令第一次执行时所在实例的 server id。因此,我们可以用下面的逻辑,来解决两个节点间的循环复制的问题:

1、规定两个库的 server id 必须不同,如果相同,则它们之间不能设定为主备关系;

2、一个备库接到 binlog 并在重放的过程中,生成与原 binlog 的 server id 相同的新的 binlog;

3、每个库在收到从自己的主库发过来的日志后,先判断 server id,如果跟自己的相同,表示这个日志是自己生成的,就直接丢弃这个日志。

按照这个逻辑,如果我们设置了双 M 结构,日志的执行流就会变成这样:

1、从节点 A 更新的事务,binlog 里面记的都是 A 的 server id;

2、传到节点 B 执行一次以后,节点 B 生成的 binlog 的 server id 也是 A 的 server id;

3、再传回给节点 A,A 判断到这个 server id 与自己的相同,就不会再处理这个日志。所以,死循环在这里就断掉了。

 

 

主备延迟

与数据同步有关的时间点主要包括以下三个:

1、主库A执行完成一个事务,写入binlog,这个时刻记为T1

2、之后传给备库B,备库接收完这个binlog时刻记为T2

3、备库执行这个事务,记为时刻T3

主备延迟就是同一个事务在备库执行的时间和主库执行的时间之间的差值,也就是T3-T1

你可以在备库上执行 show slave status 命令,它的返回结果里面会显示 seconds_behind_master,用于表示当前备库延迟了多少秒。

seconds_behind_master 的计算方法是这样的:

1、每个事务的 binlog 里面都有一个时间字段,用于记录主库上写入的时间;

2、备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到 seconds_behind_master

 

可以看到,其实 seconds_behind_master 这个参数计算的就是 T3-T1。所以,我们可以用 seconds_behind_master 来作为主备延迟的值,这个值的时间精度是秒。

 

你可能会问,如果主备库机器的系统时间设置不一致,会不会导致主备延迟的值不准?

其实不会的。因为,备库连接到主库的时候,会通过执行 SELECT UNIX_TIMESTAMP() 函数来获得当前主库的系统时间。如果这时候发现主库的系统时间与自己不一致,备库在执行 seconds_behind_master 计算的时候会自动扣掉这个差值。

网络正常情况下,T2-T1是非常小的。

主备延迟的主要表现是备库消费中继日志relay log的速度比主库生产binlog的速度慢。

来源1:备库机器性能比主库机器性能碰巧

来源2:备库压力大,在备库进行大量耗费io,cpu资源的操作

来源3:大事务。在主库上执行完成一个大事务耗费几分钟才传到从库,从而导致延迟

来源4:大表DDL,建议方式为ddl online 采用gh-ost方案

来源5:备库的并行复制能力

 

主库影响业务,大家使用起来会比较克制,反而忽视了备库的压力控制。结果就是,备库上的查询耗费了大量的 CPU 资源,影响了同步速度,造成主备延迟。

这种情况,我们一般可以这么处理:

一主多从。除了备库外,可以多接几个从库,让这些从库来分担读的压力。

通过 binlog 输出到外部系统,比如 Hadoop 这类系统,让外部系统提供统计类查询的能力。

可靠性优先策略:

双M结构下

1、判断备库B现在的seconds_behind_master,如果小于某个(比如5秒)继续下一步,否则持续重试这一步

2、把主库A改成只读状态,即把readonly设置为true

3、判断备库B的seconds_behind_master的值,直到这个值变成0为止

4、把备库B改成可读写状态,也就是把readonly 设为false

5、把业务请求切到备库B

比较耗时是第3步

可用性优先策略易造成数据不一致,不采用。

 

备库并行复制能力

协调器coordinator就是之前的sql_thread,现在只负责读取中继中日志和分发事务,真正更新日志的变成了worker线程,而worker线程的个数由参数slave_parallel_workers决定的,在分发事务时满足以下两个基本原则:

1、不能造成更新覆盖,这就要求更新同一行的两个事务必须分发到同一个worker中

2、同一个事不能被拆开,必须放到同一个worker中

 

相比于按表并行分发策略,按行并行策略在决定线程分发的时候,需要消耗更多的计算资源。约束条件:

1、要能够从binlog里面解析出表名,主键值和唯一索引的值,也就是主库的binlog格式是row

2、表必须有主键

3、不能有外键,表上如果有外键,级联更新的行不会记录在binlog中,这样冲突检测不准确

这三条约束就是DBA要求业务开发人员必须遵守的线上使用规范。

 

mysql 5.6支持按库并行复制。有两个优势

1、构造hash值的时候很快,只需要库名;而且一个实例上db数也不会很多,不会有100万个

2、不要求binlog的格式,因为statement格式binlog也可能很容易拿到库名

 

mariaDB并行复制策略

1、能够在同一组提交的事务,一定不会修改同一行;

2、主库上可以并行执行的事务,备库上可一定是可以并行执行的。

 

逻辑如下:

1、在一组里面一起提交的事务,有一个相同的commit_id,下一组就是commit_id+1

2、commit_id直接写到binlog里面

3、传到备库应用的时候,相同的commit_id的事分发到多个worker执行

4、这一组全部执行完成后,coordinator再去取下一批

 

 

mysql5.7并行复制策略,由参数slave-parallel-type来控制并行复制策略

1、配置为database,表示使用mysql5.6版本的按库并行策略

2、配置为logical_clock,表示的就是类似mariaDB的策略,不过mysql 5.7这个策略针对并行度做了优化:同时处于执行状态的所有事务是不可能并行执行的。

在两阶段提交过程中,只能够达到redolog prepare阶段,就表示事务已经通过锁冲突的检验了。

mysql 5.7并行复制策略思想是:

1、同时处于prepare状态的事务在备是可以并行

2、处于prepare状态的事务,与处于commit状态的事务之间,在备库执行时也是可以并行的。

 

binlog组提交有两个参数:

binlog_group_commit_sync_delay表示延迟多少微秒后才调用fsync

binlog_group_commit_sync_no_delay_count表示累积多少次以后才调用fsync

这两个参数是故意拉长binlog从write到fsync的时间,以减少写盘的次数,在这里可以用来制造更多的处于prepare阶段的事务,这样就增加了备库复制的并行度。这两个参数既可以主库提交慢些,也可以让备库执行的快些。

 

mysq 5.7.22增加并行复制策略,基于wirteset的并行复制,相应的增加一个参数binlog_transaction_dependency_tracking用来控制是否启用这个新策略

1、commit_order,表示就是前面介绍的根据同时进行prepare和commit来判断是否可并行的策略

2、writeset表示的是对于事务涉及更新的每一行计算出这一行的hash值,组成集合writeset。如果两个事务没有操作相同的行,也就是说它们的writeset没有交集,就可以并行。

3、writeset_session,是在wrieset的基础上多了一个约束,即在主库上同一个线程先后执行的两个事务在备库执行的时候,要保证相同的先顺序。

hash值是通过库名+表名+索引名+值 计算出来的。

相比mysql 5.5的按行分发策略有如下优势

1、writeset是在主库生成后直接写入到binlog里面的,这样在备库执行的时候不需要解析binlog内容,(event的行数据),节省了很多计算量

2、不需要把整 个事务的binlog都扫一遍才能决定分发哪个worker,更节省内存

3、由于备库的分发策略不依赖于binlog内容,所以binlog是statement格式也是可以的。

 

 

 

主库出问题了,从库怎么办

基于位点的主备切换,把节点B设置成节点A'的从库的时候需要执行的一条change master命令:

change master to

master_host =$host_name

master_port=$port

master_user=$use_name

master_password=$password

master_log_file=¥master_log_name

master_log_pos=$master_log_pos

相同的日志,A的点位和A'的位点是不同的,因此从库B库切换的时候就需要先经过找同步点的这个逻辑,这个点位很难精确取到,只能取一个大概位置。

取同步点位的方法一

1、等待新主库A'把中继日志relay log全部同步完成

2、在A'上执行show master status命令,得到当前A'上最新的File和position

3、取原主库A故障的时刻T

4、用mysqlbinlog工具解析A'的File得到T时刻的位点

myssqlbinlog file --stop-datetime=T --start-datetime=T

end_log_pos后面的值表示的就是A'这个实例,在T时刻写入新的binlog的位置,然后把end_log_pos后面的值作为$master_log_pos。这种方式可能会存在重复的数据,因为end_log_pos不精确。就是A在传完给A'和B后突然断电导致。

通常情况下,我们在切换时要主动跳过这些错误,有两种常用方法:

方法一:主动跳过一个事务,跳过命令写法:

set global sql_slave_skip_counter=1;start slave;因为切换过程中,可能会不止重复执行一个事务,所以需要在从库B刚开始接到新主库A'时,持续观察,每次碰到错误停下来,执行一次跳过命令。

方法二:通过设置slave_skip_erros参数,直接设置跳过指定的错误。

在主备切换时有这么两类错误是经常遇到的。

1062:错误的插入数据时唯一键冲突

1032:错误是删除数据时找不到行

因此,可以把slave_skip_errors设置为1032,1063,这样遇到这两个错误直接跳过。

等到主备切换完成后,并执行稳定一段时间需要把这个参数设置为空,以免真的出现主从数据不致,也跳过了。

 

以上两种方式操作复杂,mysql 5.6引入GTID--global Transaction identifier也就是全局事务id,是一个事务在提交的时候生成的,是这个事务的唯一标识,由两部分组成,格式如下:

GTID=server_uuid:gno

server_uuid是一个实例第一次启动时自动生成的,是一个全局的唯一值

gno是一个整数,初始值是1,每次提交事务的时候分配给这个事务,并加1

在mysql 官方文档里,GTID是这么定义的:

GTID=source_id:transaction_id,gno是在事务提交的时候才会分配。transaction_id与mysql中的事务混淆,mysql中的事务是在事务执行过程中分配的,如果这个回滚了,事务id也会递增。

启动GTID模式:在mysql启动一个实例时加上参数,gtid_mode=on和enforce_gtid_consistency=on就可以了。

在GTID模式下,每个事务都会跟一下GTID一一对应。这个GTID有两种生成方式,而使用哪种方式取决于session变量gtid_next的值。

1、如果gtid_next=automatic,使用默认值,这时mysql会把server_uuid:gno分配给这个事务

a:记录binlog的时候,先记录一行SET @@session.gtid_next=‘server_uuid:gno’

b:把这个gtid加入本实例的GTID集合

2、如果gtid_next是一个指定的GTID的值,比如通过set gtid_next='current_gtid'指定为current_gtid,那么就有两种可能:

a:如果current_gtid已经存在于实例的GTID集合中,接下来执行的这个事务会直接被系统忽略

b:如果current_gtid没有存在于实例的GTID集合中,就将这个current_gtid分配给系统接下来要执行的事务,也就是说系统不需要给这个事务生成新的GTID,因此gno也不用加1.

注意,一个current_gtid只能给一个事务使用,这个事务提交后,如果要执行下一个事务,就要执行set命令,把gtid_next设置成另外一个gtid或者automatic。

这样,每个mysql实例都维护了一个GTID集合,用来对应这个实例执行过的所有事务。

 

按这种方式从库复制时出现主键冲突时,处理方法:

set gtid_next='aaa:10' 将此gtid加入从库的gtid set中。

begin;commit;

set gtid_next=automatic 恢复gtid的默认分配行为

start slave;

现在在GTID模式下,备库B要设置为新主库A'的从库的语法如下:

change master to

master_host=$host_name

master_port=$port

master_user=$user_name

master_password=$password

master_auto_position=1 这个就表示这个主备关系使用的是GTID协议。现在在实例B上执行start slave命令取binlog的逻加是这样的。

1、实例B指定主库A',基于主备协议建立连接

2、实例B把set_b发给主库A'

3、实例A'算出set_a与set_b的差集,也就是所有存在于set_a,但是不存于Set_b的gtid集合,判断A'本地是否包含了这个差集需要的所有binlog事务

a:如果不包含,表示A'已经把实例 B需要的binlog给删掉了,直接返回错误

b:如果确认全部包含,A'从自己的binlog文件里面,找出第一个不在set_b的事务,发给B

4、之后就从这个事务开始往后读文件,按顺序取binlog发给B去执行。

如果之前从库B的GTID集合格式是server_uuid_of_A:1——N,那么切换之后就变成server_uuid_of_A:1-N,server_uuid_of_A':1-M

 

在双M架构下,在线给备库加索引。

1、在主库执行stop slave

2、在备库执行ddl加索引,这里不需要关闭binlog

3、执行完成后,查出这个ddl语句对应的gtid,并记为server_uuid_of_Y:gno

4、到实例X上执行以下语句序列

set gtid_next='server_uuid_of_Y:gno';

begin;commit;set gtid_next=automatic;

start slave;

 

主库是单线程压力模式,从库在追主库时将binlo-transaction-dependency-tracking设为writeset,由于主库是单线程压力模式要,所以每个事务的commit_id都不同,那么设置为commit_order模式的话,从库也只能单线程执行,由于writeset_session模式要求在备库应用日志的时候,同一个线程的日志必须与主库上执行先后顺序相同,也会导致主库单线程压力模式下退化为单线程复制。

 

 

 

 

 

怎么判断一个数据库是否出现问题

设置innodb_thread_concurrency参数的目的是控制innodb的并发线程上线。一旦并发的线程数达到这个值 ,在接收新请求时,就会进行到等待状态,直到有线程退出。 这是指的并发查询。并不是指的并发连接。一般设为64-128,太高容易引起cpu上下文切换。在线程进行锁等待后,并发线程数计数会减1,也就是等行锁是不算在128里面的。进行等待的线程已经不吃cpu了。这么设计避免整个系统锁死。

一般的做法是在系统库mysql中中创建一个表只放一行数据,然后定期执行:select * from mysql.health_check .或是在表中加两行数据, update t set time=current_timestamp();两行数据有主备server的id.

在mysql 5.6后, 在performance_schema库file_summary_by_event_name表里统计了每次IO请求的时间。

 

打开redo log 监控时间,update setup_instruments set enabled='yes',timed='yes' where name like '%wait/io/file/innodb/innodb_log_file%'。通过max_timer的值来判断数据库是否出了问题。比如.超过200毫秒。select event_name,max_timer_wait from performance_schema.file_summary_by_event_name where event_name in ('wait/io/file/innodb/innodb_log_file','wait/io/file/sql/binlog') and max_timer_wait>200*1000000000;

如果发现在异常,则取到信息;再通过truncat table performance_schema.file_summary_by_event_name;把之前的统计信息清空,这样如果后面的监控中再次出现了这个异常,就可以加入监控累计值了。

 

 

 

 

读写分离的相关问题

读写分离主要目标是分摊主库的压力。

1、强制走主库方案

 

2、sleep方案

3、判断主备无延迟方案

每次从库执行查询前先判断 seconds_behind_master是否已经等于0。通过show slave status得到结果。对比 master_log_file、read_master_log_pos和relay_master_log_file、exec_master_log_pos这两组值 完全相同,则表示日志已同步。

对比GTID集合,如果auto_position=1,表示这对主备关生活费使用了gtid协议,retrieved_gtid_set是备库收到的所有日志的gtid 集合。executed_gtid_set是备库所有已经执行的完成的gtid集合。如果这两个集合完全相同,则表示所有日志同步完成。

4、配合semi-sync方案

引入半同步复制问题,semi-sync replication

a:事务得交的时候,主库把binlog发给从库;

b:从库收到binlog后,发回主库一个ack,表示收到了

c:主库收到这个ack以后,才能给客户端返回 “事务完成”的确认

也就是说用了 semi-sync表示所有给客户端发送过确认的事务,都确保了备库已经收到了这个日志。

如果主库掉电,有些binlog还来不及发给从库,会导致系统数据丢失,但是如果使用了普通的异步复制模式,使用了semi-sync就可以解决这个问题。

 

存在两个问题

1、一主多从时,在某些从库执行查询请求会存在过期读的现象

2、在持续延迟的情况下,可以出现过度等待的问题

 

 

5、等主库位点方案

select master_pos_wait(file,pos[,timeout]);

a:这是在从库执行的

b:参数file和pos指的是主库上的文件名和位置

c:timeout可选,设置为正整数N表示这个函数 最多等待N秒

这个命令正常返回的结果是一下正整数M表示从命令开始执行,到应用完file和pos表示的binlog位置,执行了多少事务。

 

6、等GTID方案

select wait_for_executed_gtid_set(gtid_set,1)

这个命令的逻辑是

1、等待,直到这个库执行的事务中包含传的gtid_set,返回0

2、超时返回1

从5.7.6开始,在执行完更新类事务后,把这个事务的gtid返回给客户端,这样等gtid的方案就可减少一次查询。

这时,等gtid的执行流程就变成了,

a、trx1事务更新完成后,从返回包直接获取这个事务的gtid,记为gtid1

b、选定一个从库执行查询语句

c、在从库上执行select wait_for_executed_gtid_set(gtid1,1)

d、如果返值 是0,则在这个从库执行查询语句

e、否则,到主库执行查询语句

跟等主库位点的方案一样,等待超时后是否直接到主库查询,需要业务做限流策略。

 

 

 

binlog三种格式

statement,row,mixed,采用Mixed模式下默认statement,某些情况下会切换到row模式。

 

show binlog events in 'binlog file' from position

set binlog_format='row'仅影响当前会话

set global binlog_format='ROW'全局

mysqlbinlog -vv binlog_file --base64-output=decode-rows --start-pos=起始位置

 

双M架构的主从复制,在M2上选择BLACKHOLE,写入blackhole表的数据并不会写回到磁盘上,blackhole表永远都是一个空表。insert update delete操作仅在binlog中记录。

此引擎非常适合二级主库Master 2的场景。M2并不承担读写请求,仅负责将binlog日志传送给从库。

 

 

双M架构,互为主从。双M架构能够大减轻一主多从架构下对主库进行维护带来的额外搭建从库的工作。

可以m2下搭建从库,分担读取压力。

在主库上设置一个复制使用的账户,并授予replication slave权限

grant replication slave on *.* to 'rep1'@'192.168.7.200' indentified by 'testreplication';

 

 

在从数据库使用--skip-slave-start选项启动数据库,这样不会立即启动从数据库服务上的复制进程,方便对从数据库的服务进行进一步配置。

 

在从库上start slave。

sync_binlog:此参数控制write和fsync的时机。

设置为1时表示每次事务提交binlog都持久化到磁盘,即执行fsync。设置1可以保证mysql异常重启之后的binlog不丢失。

0:每次提交事务只write,即写到page cache中,并没有持久化到磁盘,不fsync;

sync_binlog=N(N>1),表示每次提交事务都write,即写到page cache中,但累积N个事务后才fsync,即持久化到磁盘。比较常见的是将其设置为100到1000中的某个数值。

 

mysql 5.5引入半同步复制 semi-synchronous replication

为了保证主库上的每个binlog事务都能够被可靠的复制从库上,主库在每次事务成功提交时,并不及时反馈给前端用户,而是等待其中一个从库也接收到binlog事务并成功写入中继日志后,主库才返回commit操作成功给客户端。半同步复制保证了事务成功提交后,至少有两份日志记录,一份在主库的binlog日志上,另一份在至少一个从库的中继日志relay log上,从而更进一步保证了数据的完整性。

主库上等待一段时间由 rpl_semi_sync_master_timeout设置的毫秒数决定,如果binlog在这段时间内都无法成功推送到从库上,则mysql自动调整为异步模式,事务正常返回提交结果给客户端。

半同步复制插件

select @@have_dynamic_loading;

安装半同步插件

 

主库安装:install plugin rpl_semi_sync_master soname 'semisync_master.so';

 

从库安装:install plugin rpl_semi_sync_master soname 'semisync_slave.so';

 

 

分别在主库和从库上配置参数打开半同步semi-sync,默认半同步设置是不打开的,

set global rpl_semi_sync_master_enabled=1

set global rpl_semi_sync_master_timeout=3000;

 

从库上一样配置参数

set global rpl_semi_sync_slave_enabled=1;

重启从库上的I/O线程(如果是全新配置的半同步复制则不需要)

 

stop slave IO_thread;

start slave IO_Thread;

 

show status like '%semi_sync%';

一旦有一次半同步复制失败,会自动切换为异步复制。待恢复后,又会自动切换为半同步状态。

虽然主库和从库的binlog日志是同步的,但是主库不等待从库应用这部分日志就返回提交结果,这部分操作是异常的。从库的数据并不是和主库实时同步的,所以只能称为半同步,而不是完全同步的。

 

log-slave-updates用来配置从库上的更新操作是否写二进制日志,默认是不打开的,但是这个从库也要成为其他服务器的主库,那么就需要打开这个选项。需要和参数--logs-bin参数一起使用。

 

master-connect-retry:是用来设置在和主库连接丢失时重试的时间间隔,默认是60秒,即每60秒重试一次。

 

read-only用来设置从库只能接受超级用户的更新操作。从而限制应用程序的错误对从库的更新操作。

 

replicate-do-db、replicate-do-table、replicate-ignore-db、replicate-ignore-table或replicate-wild-do-table来指定从主数据库复制到从数据库的数据库或者表。在从数据库启动时指定replicate-do-table=test1.repl_test.

 

slave-skip-errors是用来定义复制过程从库可自动跳过的错误号;

 

日常管理维护:

查看从库状态

show slave status;

主要注意slave_IO_running负责从库从主库上读取binlog并写入从库上的中继日志,和slave_sql_running读取并执行中继日志中的binlog.只要其中有一个进程的状态是no,则表示复制进程停止,错误原因可以从last_errno字段值可以看到。

 

主从同步维护:

在负载较低时暂时阻塞主数据库的更新,强制主从数据库更新同步。

1、在主库上执行flush tables with read lock;

show master status;记录输出的日志名和偏移量,这些是从库复制的目的坐标。

2、在从库上执行

select master_pos_wait(上面得到的文件名,偏移量);

这个语句会阻塞直到从库达到指定的日志文件和偏移量后,返回0表示主从同步,如果返回-1,则表

示超时退出,

3、在主库上unlock tables;

 

从库复制出错的处理

set global sql_slave_skip_counter=n,n取1或2,如果来自主库的更新语句不使用auto_increment或last_insert_id(),n为1,否则n为2 。原因是auto_increment或last_insert_id()的语句需要从二进制日志中取两个事件,

 

log event entry exceeded max_allowed_packet的处理,这是因为含有大文本的记录无法通过网络进行传输,增加max_allowed_packet参数的大小。默认是1MB,

set @@ global.max_allowed_packet=1024*1024同时在my.cf中,设置max_allowed_packet=16MB,保证下次数据库重新启动后参数继续有效。

 

 

多主复制时,自增主键的冲突

在m1上,auto_increment_increment=2,auto_increment_offset=1;(1,3,5,7,9)

在m2上,auto_increment_increment=2,auto_increment_offset=0(0,2,4,6,8)

 

查看从库复制进度

二进制日志中的每个语句通过设置时间戳来保证执行时间和顺序的正确性,所以每个语句之前都会首先设置时间戳,而通过查询这个进程的time就可以知道最后设置的时间戳和当前时间的差距。

show process list在从库上执行

 

 

如何提高复制性能

方案一 通过设置不同replicate-do-db,replicate-do-table,replicate-ignore-db,replicate-ignore-table或replicate-wild-do-table参数,使得不同的从库复制不同的库/表,减少每个从库上需要写入的数据。

 

方案二 mysql5.6提供了基于schema的多线程复制,允许从库并行更新。通过设置参数slqve_parallel_workers为2 ,让mysql从库在复制时启动两个SQL线程。

 

切换主从库:

1、首先确保所有的从数据库都已经执行了relay log中的全部更新,在每个从库上,执行stop slave IO_Thread,然后检查show processlist,直到看到状态has read all relay log,表示更新都执行完毕。

 

2、在从数据S1上执行stop slave 以停止从服务,然后执行reset master以重置成主数据库

3、在s2上执行 stop slave以停止从服务,然后执行change mastr to master_host='s1',再执行start salve以启动复制。

change master to master_host='192.168.1.1'

start slave.

4、通知所有的客户端将应用指向S1,这样客户端发送的所有更新语法写入到SQ的binlgo

5、删除新的主数据库服务器上的master.info和relay-log.info文件,否则下次重启还会按照从库启动。

6、最后,如果M服务器可以修改,则可以按照S2的方法配置成S1的从库。

 

s1的log-bin是打开的,s1上没有打开log-slave-updates,否则重置成主数据库后,可能会将已经执行过的二进制日志重复传输给S2,导致s2同步错误。

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值