MySQL主从复制架构多次出现复制停滞问题如1032错误和1062错误,其中,1032错误是在主库成功执行后在从库update或delete时发现从库上找不到这条记录,1062错误是在主库insert完成后在从库执行时出现主键冲突无法成功insert,这些问题可通过跳过错误和前面的复制数据校验修复来解决,但是这些问题产生的直接原因都是主从库数据不一致。这种不一致除了逻辑复制本身可能出现的数据不一致,还有个原因是业务侧或开发人员违规在备库上直接进行增删改操作导致的。
在主从复制架构中,主从库通过VIP绑定实现指定库作为主库,提供读写,从库起backup的作用,当主库出现问题时,VIP切换到从库,从库提供读写,否则从库只是backup。正常情况下,我们不允许开发人员直接通过固定IP登录从库操作,但实际工作中往往又难以规避,那么如何从技术角度去避免开发人员在备库操作呢?又如何在避免的同时不影响高可用架构的正常运行和故障切换呢?
2.架构配置优化
(1)直接解决办法
解决上述问题的直接办法是考虑进行架构配置优化,即将从库可读写的状态配置为只读状态。
MySQL官网关于只读有下列描述:
1.Whenthe
read_only system variable is enabled, the server permits no client updatesexcept from users who have
the SUPER privilege.
只读情况下,super权限可读写。
2.Updates performed by
slave threads, if theserver is a replication slave. In replication setups, it can be useful toenable
read_only on slave servers to ensure that slaves accept updates only from themaster server and not from clients.不影响主从复制线程的读写。
开启只读后,除了super权限账户和复制线程等不受影响外,业务侧开发人员和其它人员即使登录备库也无法操作备库数据。
MySQL [db1]> show global variables like'read_only%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only | ON |
+---------------+-------+
1 row in set (0.00 sec)
MySQL [test]> insert child values('1','12');
ERROR 1290 (HY000): The MySQL server is running withthe
--read-only option so it cannot
execute thisstatement
(2)配置为只读后如何进行完美故障切换?
从库只读可避免违规操作,但面临的问题是如果主库发生问题,VIP要切换到从库上,但这时候从库只读会导致数据库对外服务不可用,因此在切换时需要实现取消从库只读同时设置主库只读的功能。
以Keepalived+MySQL双主(主从)架构为例,正常运行时,VIP在Master1上,Master1为可读写状态,Master2为readonly状态,一旦Master1发生问题,VIP要自动切换至Master2,切换前要完成两个步骤:1.将Master1置为readonly;2.取消Master2的readonly。
3.自动化实现思路
对于一主一从架构,故障切换需要手工进行,因此上述两步也可以手工操作;但Keepalived+MySQL双主(主从)架构中,已实现故障的自动监测和VIP自动切换,上述两个步骤也应该植入脚本中实现自动化。
我们主要需在自动监测和切换脚本中植入对数据库开启readonly和关闭readonly的函数,主要写入语句“set
global read_only=ON”和“set globalread_only=OFF”,同时注意在设置状态之前先判断现有状态,shell调用语句“show
variables like 'read_only';”得到读写状态,确认读写状态后再设置readonly参数为所需状态即可,注意这些状态设置的触发定制在监测到故障并执行切换之前。
上述思路现已完成自动化转换,亲测成功,说明思路正确。