mycat,阿里的mysql中间件,提供读写分离和分库分表方案。项目中主要使用的是其读写分离功能
问题:执行行级锁失败
1 |
SELECT * FROM QRTZ_LOCKS WHERE SCHED_NAME = 'schedulerFactoryBean' AND LOCK_NAME = 'TRIGGER_ACCESS' FOR UPDATE; |
查看下日志:
分析:
1 2 3 |
简单说下,在事务中读写操作都会分发到写节点执行。你可以将日志级别调整为debug,在日志中可以确认这一点。 但是,注意到日志中有release connection字样,实际上,直到事务中执行了select,update,delete等dml语句,mycat在分发select确实到写(R)节点了。返回客户端后他就会释放连接. 这里应该开启写(W)节点的mysql查询日志general log,太麻烦我没有开启,估计执行完select事务就提交了。 |
得出结果:
1 |
如果事务中上来执行的是select for update锁行记录、实际上表现为获取之后马上释放,其他sql还是可以获取锁、导致悲观锁机制失效。 |
但是在单库环境下又正常,符合程序逻辑,这说明是mycat中间件搞得事情
1 2 3 4 |
SELECT * FROM QRTZ_LOCKS WHERE SCHED_NAME = 'schedulerFactoryBean' AND LOCK_NAME = 'TRIGGER_ACCESS' FOR UPDATE; 期间换了个办法,采用在事务中先调用update QRTZ_LOCKS set SCHED_NAME ='schedulerFactoryBean' where LOCK_NAME = 'TRIGGER_ACCESS' 这种方式“告知”mycat(LOCK_NAME 索引高效率、没有update目标不会锁任何记录任何表,简直就像发过去一个标签)发现之后select for update可以成功锁行记录,说明mycat的确做了一些特殊判断:如果事务中首先执行select语句则立即提交(这玩意是什么思想吗,我翻阅了mycat权威指南也没有发现,如果是优化,给出一个配置我马上把他关了)。 但这种方法距离优秀差一个筋斗云。 |
查看官方最新文档:
主要查看mycat事务这一块内容(因为这块涉及我们上面的问题)
先来说说XA 事务原理(出自官方文档)
1 2 3 4 5 6 7 |
分布式事务处理指一个程序或程序段,在一个或多个资源 如数据库或文件上为完成某些功能的执行过程的集合,分布式事务处理的关键是必须有一种方法可以知道事务在 任何地方所做的所有动作,提交或回滚事务的决定必须产生统一的结果(全部提交或全部回滚)。X/Open 组织 (即现在的 Open Group )定义了分布式事务处理模型。 X/Open DTP 模型( 1994 )包括应用程序( AP )、 事务管理器( TM )、资源管理器( RM )、通信资源管理器( CRM )四部分。一般,常见的事务管理器 ( TM )是交易中间件,常见的资源管理器( RM )是数据库,常见的通信资源管理器( CRM )是消息中间件, 下图是 X/Open DTP 模型: |
一般在编程中使用的方式是这样的:
- 1.配置 TM,通过 TM 或者 RM 提供的方式,把 RM 注册到 TM。可以理解为给 TM 注册 RM 作为数据源。 一个 TM 可以注册多个 RM。
- 2. AP 从 TM 获取资源管理器的代理(例如:使用 JTA 接口,从 TM 管理的上下文中,获取出这个 TM 所管 理的 RM 的 JDBC 连接或 JMS 连接)
- 3.AP 向 TM 发起一个全局事务。这时,TM 会通知各个 RM。XID(全局事务 ID)会通知到各个 RM。
- 4.AP 通过 TM 中获取的连接,直接操作 RM 进行业务操作。这时,AP 在每次操作时把 XID(包括所属分支的 信息)传递给 RM,RM 正是通过这个 XID 与 第二步中的 XID 关联来知道操作和事务的关系的。
- 5.AP 结束全局事务。此时 TM 会通知 RM 全局事务结束。
- 6. 开始二段提交,也就是 prepare – commit (准备提交)的过程。
- 7.XA 协议(XA Specification) :解释如下
1 2 3 4 5 |
XA 协议(XA Specification),指的是 TM 和 RM 之间的接口,其实这个协议只是定义了 xa_和 ax_系列的 函数原型以及功能描述、约束和实施规范等。至于 RM 和 TM 之间通过什么协议通信,则没有提及,目前知名的 数据库,如 Oracle, DB2 等,都是实现了 XA 接口的,都可以作为 RM。Tuxedo、TXseries 等事务中间件可以通 过 XA 协议跟这些数据源进行对接。JTA(Java Transaction API)是符合 X/Open DTP 的一个编程模型,事务管理 和资源管理器支架也是用了 XA 协议。 |
下面两个图片分别给出了 XA 成功与失败的两种情况,首先是 XA 事务成功的流程图:
然后,是 XA 事务失败的流程图:
XA 事务的关键在于 TM 组件,其中的难点技术点如下:
1 2 3 4 |
**第二段提交时,当 RM1 commit 完成了,而 RM2 commit 还没有完成,这时 TM 需要进行协调,当 RM2 恢复以后,重新提交之前没有 Commit 的事务,或者自动回滚之前 Rollback 的事务。 **因此 TM 需要记录 XA 事务的状态,以及在各个 RM 上的执行情况,这个日志文件需要存储在可靠的地方, 用来进行 XA 事务异常之后的补救工作。 |
TM 是一定要把事务的信息,比如 XID,哪个 (数据库)RM 已经完成了等保存起来的。只有当全部的 RM 提交或者回 滚完后,才能丢弃这些事务的信息。
于是我们明白 TM 是一个单点,要非常可靠才行。
1 2 3 |
Mycat 从1.6.5 版本开始支持标准 XA 分布式事务,考虑到 mysql5.7 之前版本 xa 的2 个bug,所以推荐最佳搭配 XA 功能使用 mysql 5.7 版本。 Mycat 实现 XA 标准分布式事务,mycat 作为 xa 事务协调者角色,即使事务过程中 mycat 宕机挂掉,由于 mycat 会记录事务日志,所以 mycat 恢复后会进行事务的恢复善后处理工作。 考虑到分布式事务的性能开销比较大,所以只推荐在全局表的事务以及其他一些对一致性要求比较高的场景。 |
XA 操作说明
1 2 3 4 5 6 7 8 9 |
1. set autocommit=0; XA 事务 需要设置手动提交 2. set xa=on; 使用该命令开启 XA 事务 3. insert into travelrecord(id,name) values(1,'N'),(6000000,'A'),(321,'D'),(13400000,'C'),(59,'E'); 执行相应的 SQL 语句部分 4.commit; 对事务进行提交,事务结束 |
保证 repeatable read (划重点)
1 2 |
mycat 有一个特性,就是开事务之后,如果不运行 update/delete/select for update 等 更新类语句 SQL 的话,不会将当前连接与当前 session 绑定。如下图所示: |
这样做的好处是可以保证连接可以最大限度的复用,提升性能。
1 2 3 4 |
但是,这就会导致两次 select 中如果有其它的事务在提交的话,会出现两次同样的 select查询,而结果却不一致的现象,即不能 repeatable read,这会让人直连 mysql 的人很困惑,可能会在依赖 repeatable read 的场景出现问题。所以做了一个开关,当 server.xml 的system 配置了strictTxIsolation=true 的时候(true),会关掉这个特性,以保证 repeatable read,加了开关 后如下图所示: |
问题原因说完了:下来修改
我当前的问题有2个
- 1.需要将mycat升级到1.6.5版本后,因为我当前是1.6不支持XA事务隔离
- 2. 将service.xml配置文件中的strictTxIsolation=true
上面2部修改都进行完成后,再次select form update
成功解决。
总结这次项目事件原因:
1 2 3 4 |
在一般事务中读写操作都会分发到写节点执行。而mycat1.6.5 版本之前,不支持AX事务隔离.默认innerDB表的隔离级别是repeatable read .而又因为mycat1.6.5之前不支持事务.所以在执行 SELECT * FROM QRTZ_LOCKS WHERE SCHED_NAME='schedulerFactoryBean' AND LOCK_NAME = 'TRIGGER_ACCESS' FOR UPDATE; 这条语句的时候并没有认为他在事务当中,而是把select分发到读的机器当中。所以造成了ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement 解决办法就是让 mycat支持AX事务操作,严格事务隔离.让这句sql执行在写操作执行。就不会出现此错误。 |
关于mysql事务隔离级别 请看这篇 传送门
- 本文固定链接: https://www.yoyoask.com/?p=2876
- 转载请注明: shooter 于 SHOOTER 发表