踩风火轮的乌龟 2019-12-02
去年年底发了一篇博客,关于mycat的入门配置【最后一行的补充不准确】。
当时公司出了一系列有关数据库的诡异事件,总结下来,无非是开发人员技术、经验不到家的时候不要小孩骑大马,套不住。单库挺好。
https://www.cnblogs.com/feixuefubing/p/10191237.html
最近开发时(springcloud:springboot+mybatis)本以为对mycat有了一些了解,结果使用读写分离功能之后又蹦出一些疑似并发的问题。明明程序中做了控制加了锁、为什么还出问题?小猫还是太不老实。
简明扼要,在事务中,读写操作都会分发到写节点执行,在log4j2.xml中将日志级别更改为debug,重启服务后查看日志可以确认这一点。
但是,注意到日志中有release connection。。字样,实际上,直到事务中执行了insert、update、delete等dml语句,mycat在分发select(确实到写节点了)、返回客户端结果后就会“释放连接”。
这里应该开启写节点的mysql查询日志(general log)进一步验证,我懒了一下没有开,恐怕执行完select事务就提交了。
于是,如果事务中上来执行的是select for update锁行记录、实际上表现为获取之后马上释放,其他sql还是可以获取锁、导致悲观锁机制失效。
经历了一个方法一个方法的调试,在排除变量之后问题仍然存在,单库环境下又符合程序逻辑,说明只可能是mycat中间件做的乱。
期间,甚至采用在事务中先调用update (table) set id=id where id=-1这种方式“告知”mycat(id索引高效率、没有update目标不会锁任何记录任何表,简直就像发过去一个标签)发现之后select for update可以成功锁行记录,说明mycat的确做了一些特殊判断:如果事务中首先执行select语句则立即提交(这难道是什么思想吗,我翻阅了mycat权威指南也没有发现,如果是优化,给出一个配置我马上把他关了)。
但这种方法距离优雅十万八千里。
查阅资料偶然间看到这样一行评论:“给我一个继续使用mycat的理由(一个链接)”,才知道原来mycat两年间已被踏上一万只脚。试验dble之后发现表现很正常。
配置结构大体与mycat相同、解决了我遇到的奇葩问题、开源社区持续维护、转换成本较低,umm。。
毕竟目前只用到读写分离,确实没有一个继续使用mycat的理由。
附:试验路径
环境:mycat(锁不住)、单库(成功)、dble(成功)
变量控制:
1、mybatis-plus(证明无关,其表现确实更像一个装饰者,除方便开发外不改变mybatis逻辑)
2、druid连接池(证明无关,有说法称他的默认自动提交会覆盖spring事务管理,从mysql日志并未看出)
3、spring事务管理也没啥问题。。