mysql gno( )_mysql数据的完整性

2ff34e647e2e3cdfd8dca593e17d9b0a.png

大部分业务数据库都是读多写少,我们在实际使用情况上往往会遇到读性能,本章主要讲述如何解决读延迟

一主多从的架构

我们一般会采取一主多从架构,主库承担所有的写和一部分读的任务,丛库根据承担读的任务。

如图:

3a5655c5a4672025963a3b462b1cf176.pngA和A’互为主备

B、C、D是A的从库

下面我们来通论下当主库A发生故障后,A’成为主库,BCD的主库也要都指向A’,下面我们来讨论下遇到这种情况,mysql是如何做主从切换的。

如图:

965a7cad1135b27749d4b3dd4abfa91f.png

基于位点的主备切换

当把B置为A’的从库时候要执行如下命令1

2

3

4

5

6

7CHANGE MASTER TO

MASTER_HOST=$host_name

MASTER_PORT=$port

MASTER_USER=$user_name

MASTER_PASSWORD=$password

MASTER_LOG_FILE=$master_log_name

MASTER_LOG_POS=$master_log_poshost_name、port、user_name、password主库的IP、端口、用于主从同步的数据库用户名、密码

master_log_name,和master_log_pos就是A’库binlog的文件名和位置成为位点;

原来的B是A的从库,所以B中记录的是A的位点,在change master之后,B要将位点置为A’的位点,由于A和A’记录的位点不一样,所以要大概估算出一个靠前一点的位点,在忽略掉主从不同步的情况。为什么要靠前一点的主要是有下面这种情况,下面语句是分析mysqlbinlog找到位点1

2

3mysqlbinlog File

#比如这是看到了pos是123,我们B在chenagemaster时候可以往前一点比如110;在A插入了一行R,同时同步给B和A’这时候A出现故障,B和A’都已经有了R行数据,如果这时候changemaster会提示主键冲突,停止同步。

解决的方案:主动跳过1个事务,如下的命令,每次遇到这样的错误都跳过知道最后没有错误为止

通过设置slave_skip_errors参数,直接跳过指定错误,常见的错误如下,可以直接跳过“1062,1032”1062 错误是插入数据时唯一键冲突;

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

2set global sql_slave_skip_counter=N;

start slave;

注意:前提是这俩种操作是对业务无损的。

GTID– since v5.6

基于位面做主从切换比较复杂且很容易出错,所以mysql在5.6后引入了gtid彻底解决了这个问题。

GTID全程是Global Transaction Identifier,即全局事物ID,即一个事物提交后生成的全局唯一ID,他有俩个部分组成GTID=server_uuid:gno(官方定义:GTID=source_id:transaction_id)

其中:server_uuid是mysql的实例ID

gno是一个递增的整数,

如何启动gtid呢?1

2gtid_mode=on

enforce_gtid_consistency=on

下图就是我在主库上执行了一条插入看到的binlog,其中SET @@SESSION.GTID_NEXT= ‘b01b34d1-25cf-11e9-8e68-9ec1c2413262:1’就是这条事物的GTID1

2

3

4

5

6

7

8

9

10

11

12mysql> show binlog events IN 'mysql-bin.000028';

+------------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------+

| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |

+------------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------+

| mysql-bin.000028 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.25-log, Binlog ver: 4 |

| mysql-bin.000028 | 123 | Previous_gtids | 1 | 154 | |

| mysql-bin.000028 | 154 | Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= 'b01b34d1-25cf-11e9-8e68-9ec1c2413262:1' |

| mysql-bin.000028 | 219 | Query | 1 | 293 | BEGIN |

| mysql-bin.000028 | 293 | Table_map | 1 | 340 | table_id: 108 (liuhao.t) |

| mysql-bin.000028 | 340 | Write_rows | 1 | 384 | table_id: 108 flags: STMT_END_F |

| mysql-bin.000028 | 384 | Xid | 1 | 415 | COMMIT /* xid=23 */ |

+------------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------+

gtid的分配方式:当gtid_next=automatic时候,代表使用默认值:记录binlog时候先记录一行SET @@SESSION.GTID_NEXT=

把这个gtid加入到本地实例的gtid集合中(Executed_Gtid_set)

如果gtid_next=是一个指定的gtid值时候,比如通过set gtid_next=’current_gtid’指定为当前的current_gtid时候,如果current_gtid已经存在于gtid集合,接下来执行这个事务会跳过这个事务;

如果current_gtid不存在于gtid这个集合中,将这个current_gtid分配给新的事务,说明系统不需要分配新的gtid,gno也不需要加1

gtid的使用方法

加入一个库X是有一条数据(1,1),他的的gtid=aaaaaaaa-cccc-dddd-eeee-0000000000000:1

同时X作为了Y的从库,Y写入了一条数据(1,1),他的gtid=aaaaaaaa-cccc-dddd-eeee-ffffffffffff:10

我们在X上执行如下的命令1

2

3

4

5

6

7

8

9#将X的gtid_next置为Y库的aaaaaaaa-cccc-dddd-eeee-ffffffffffff:10

set gtid_next='aaaaaaaa-cccc-dddd-eeee-ffffffffffff:10';

#提交一个空事物,把“aaaaaaaa-cccc-dddd-eeee-ffffffffffff:10”这个gtid置为X的Executed_Gtid_set中,遇到冲突可以跳过

begin;

commit;

#置gtid_next为automatic,下一个事物就变为了“aaaaaaaa-cccc-dddd-eeee-ffffffffffff:11”

set gtid_next=automatic;

#开启从库

start slave;

基于GTID的主备切换

执行如下命令注意,master_auto_position表示的这个主备关系支持GTID协议,我们之前的MASTER_LOG_FILE和MASTER_LOG_POS已经不需要指定了。1

2

3

4

5

6CHANGE MASTER TO

MASTER_HOST=$host_name

MASTER_PORT=$port

MASTER_USER=$user_name

MASTER_PASSWORD=$password

master_auto_position=1

B通过CHANGE MASTER变为A’的从库,B的gtid_set为set_b,A的gtid_set为set_a,在start slave时候逻辑如下:A和B建立主备关系;

B把set_b发个A’;

A’计算set_a和set_b的差集,差集说明是B需要执行的binlog,同时判断A是否包含了这些binlog不包含,直接报错,说明A已经把这些BINLOG删除了

如果全部包含,A’从自己的binlog里找出第一个差集中的binlog开始同步

之后从这个事务开始一直往B同步

这种方式,由之前通过位点同步的,由从库来决定从哪里同步,到主库通过获取从库的gtid来计算出从哪里开始同步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值