首页 > 其他分享 >mycat 数据丢失的几种原因

mycat 数据丢失的几种原因

时间:2023-02-20 17:27:01浏览次数:26  
标签:语句 rollback mycat 几种 丢失 MySQL MyCAT 连接

https://github.com/MyCATApache/Mycat-Server/issues/2589

问题
交流群里面很多同学反馈批量Insert 丢数据,此单集中处理

问题可能原因
1、应用用法错误,因为mycat 最新的1.6.7.4及之前的版本都不支持以逗号分隔的批量语句,形如insert aa...;insert bb...;insert cc....;
此时,应用的SQL里面包含这种语句,或者连接mycat的驱动url里面带有allowMultiQueries=true参数,都会触发这种问题。
请务必设置allowMultiQueries=false. 群里面反馈的用navicat导入insert 文件,mycat 日志里面出现but no handler大体都是属于这类问题。
2、mycat自身问题
2.1 后端连接连管理有问题,连接被共用。 目前review代码,没有发现这个问题。
2.2 NIO buffer管理有问题,存在多次释放,导致共用,引起包错乱。AbstractConnection.cleanup()这个方法存在并发调用的问题,有这种风险。待加锁解决
2.3 其他,问题待补充
解决方案
1、allowMultiQueries=true问题,创建连接时候直接拦截报错。另外, SQL解析时候遇到多语句直接报错。
2、AbstractConnection.cleanup() 加锁

原因二

在做读写分离时,我们采用了以下方案,在dataHost上配置了balance=0, 默认禁用读写分离。然后只有带有/*#mycat:db_type=slave*/这样hint的语句才会被分发到readHost,后续会逐渐通过添加hint到新的hint语句来来放开更多的流量,希望这样逐步放开读流量可以避免一次性全部迁移带来的影响。

 <dataHost name="masterFirst" maxCon="100" minCon="50" balance="0" tempReadHostAvailable="1"
            writeType="0" dbType="mysql" dbDriver="native" switchType="-1"  slaveThreshold="10">
      <writeHost host=mysqla>
            <readHost host=mysqlb/>
      </writeHost>
....
但是测试发现部分事务会丢失记录,通过分析发现部分经过MyCAT的事务会被一条rollback回滚。经过分析,是以下模式的事务会被回滚:

set autocommit=0;
INSERT INTO tablea ...
/*#mycat:db_type=slave*/SELECT xx from tableb
COMMIT
在MySQL端看到以上序列会变为以下模式,在writeHost上

set autocommit=0;INSERT INTO tablea ...
ROLLBACK
在readHost上

SELECT xx from tableb
这样,插入到表tablea的数据就丢了。而此时,业务服务器,MyCAT服务器和MySQL端都无任何错误日志。
经过分析,发现是MyCAT对以上场景的处理逻辑如下

MyCAT在一个连接到MySQL writeHost的连接内碰到一个到readHost的语句
MyCAT释放writeHost连接回连接池,而释放连接会发起rollback(这是为什么会多一个rollback的原因)
MyCAT新建到readHost的连接,并执行到readHost的语句
这个逻辑应该是没有问题的,因为MyCAT要保证在一个前端事务边界内(面向应用)任一时刻只能关联同一个后端连接(到MySQL)。而根源是应用程序做读写分离用法上的问题。但是NonBlockingSession.java代码在释放并切换连接只产生了一行debug日志,导致我们在丢失数据的时候在所有地方都找不到错误日志。所以debug级别明显不利于排查。已经在MyCAT GitHub提醒进行改正。

总结MyCAT的前后端连接管理策略。

MyCAT以事务为单元来请求和使用后端MySQL连接池
开始事务即可从MySQL连接池中拿连接(后端连接),关闭事务即释放连接到后端连接池
释放MySQL连接回连接池前会在MySQL连接上发一个rollback指令。这会使在应用发一个commit时,经过MyCAT,MySQL收到commit和rollback两条语句。而应用发一个rollback,经过MyCAT,MySQL会收到rollback和rollback两条语句
一个后端MySQL连接上出现事务内的SQL错误(比如主键冲突)后,应用如果不进行rollback就在别的线程复用前端MyCAT连接,那么应用新的SQL全部都会失败。
如果MySQL连接所在事务处于异常状态,前端关闭连接,对应MySQL连接会被关闭

 

标签:语句,rollback,mycat,几种,丢失,MySQL,MyCAT,连接
From: https://www.cnblogs.com/gaoyuechen/p/17138192.html

相关文章