MySQL深入——19

读写分离有哪些坑??

一主多从结构就是基本的读写分离结构,主要目的在于分摊主库的压力。

其中一种架构是将数据库的连接信息放在客户端,由客户端选择后端数据库进行查询。

还有一个架构是MySQL与客户端之间有一个中间代理层proxy,客户端只连proxy由proxy决定分发路径。

第一种架构来说,结构金丹,便于维护,只出现主备切换,库迁移时,只需要在客户端调整数据库连接信息

proxy的架构,对客户端较为友好,因为连接是由proxy决定的,proxy的维护成本高,proxy需要高架构。

不论使用什么架构,都有可能碰到主从延迟的事件,这种从从库上读到系统上过期状态的现象,称之为“过期读”。

我们可以通过一下操作来处理

强制走主库

将查询请求做分类,对于需拿到最新结果的请求,就走主库,对于读到旧数据的请求就走从库。

问题在于,在碰到金融类的项目时,要求所有读都不能为过期读,这就得全走主库,导致主库压力过大。

Sleep方案

主库更新后,将从库sleep一下,这个方案假设大多数主备延迟在一秒之内,做一个sleep有很大概率拿到新的数据,但是这个不是很靠谱,因为如果更新的延迟大于一秒就得读旧数据了。

判断主备无延迟方案

1.判断seconds_behind_master是否为0

2.对比位点

Master_log_file和read_master_log_pos(读到主库的最新位点)

Relay_Master_log_file和Exec_Master_log_pos(备库执行的最新位点)

这两组值相同的时候代表同步完成

3.GTID集合

Auto_Position=1 主备使用了GTID协议

Retriered_Gtid_Set(备库收到的GTID集合)和Executed_Gtid_Set(备库已经执行的GTID集合)两个集合相同,代表同步完成。

相比于sleep方案这样的精准度更高,但是还是会出现问题。

有一种情况为主库执行完后写入binlog,返回给客户端的这一刻,还没有将binlog传给备库。

我们可以使用semi_sync来解决

semi_sync做了这样的设计

1.事务提交之后主库binlog给从库

2.从库收到之后,返回一个ack给主库

3.主库收到ack之后才给客户端返回事务已经完成的确认。

一主一备的情况下是成立的,但是一主多从就会出现两种情况

1.查询落到ack从库,相安无事

2.查询的不是ack从库,就有可能出现过期读的情况

其实同步位点的判断还存在着一个问题,比如业务高峰期,主库的GTID更新极快,等到等值判断的时候,是必然不相同的,会造成长时间不响应查询的情况。

等主库位点

看条命令

select master_pos_wait(file , pos[,timeout])

file pos指主库上的文件名和位置

timeout可选,设置为正整数N,表示函数做多等多少秒。

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

其他结果返回:1.执行过程当中,备库同步线程异常,返回Null

                          2.超出N,返回-1

                          3.刚开始执行过这个位置返回0

对于在主库上刚执行完的更新语句,马上执行show master status,得到当前主库的file和position

若返回值为大于等于0的整数,则在这个备库执行查询语言,否则到主库当中执行查询语言。

那么如果超时了,是不是还得去主库呢,其实可以做两个选择:1.超时放弃2.去主库查。

GTID方案

MySQL当中提供了一个类似的命令

select wait_for_executed_gtid_set(gtid_set,1)

这条命令的逻辑是

1.等待1秒,直到这个库执行的事务传给gtid_set,返回0

2.超时返回1

在GTID当中变成

1.trx1事务更新完成后,从返回包当中获取这个事务的GTID记为gtid1

2.选择一个从库进行查询语句

3.在该从库上执行上面那条命令

4.若返回值为0,在这个从库执行查询语句

5.否则就去主库

MYSQL在执行事务后带上GTID需要将参数 session_track_gtids设为OWN_GTID通过API接口msyql_session_track_get_first从返回包查询即可。

你可能感兴趣的:(mysql,数据库)