Mycat批量插入问题

问题重现

使用jmeter测试或JDBC在一条SQL里编写多条SQL语句(以;分隔语句)

创建表
create table travelrecord (id bigint not null primary key,user_id varchar(100),traveldate DATE, fee decimal,days int);

批量插入语句

INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(1,’000001’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(3,’000001’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(11,’110002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(13,’130002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(21,’210003’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(23,’230003’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(31,’310002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(33,’330002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(41,’410002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(43,’430002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(51,’510002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(53,’530002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(61,’610002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(63,’630002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(71,’710002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(73,’730002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(81,’810002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(83,’830002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(91,’910002’,NOW(),1235,6);
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES(93,’930002’,NOW(),1235,6);

Mycat接收到的SQL
Q群文件-Mycat批量插入问题 - 图1

Mycat往后端发送的SQL
Q群文件-Mycat批量插入问题 - 图2

发现mycat只往mysql发送了一条SQL

分析

在一个SQL中可以多个SQL语句,不同于一个MYSQL的情况,mycat对于每个SQL语句最后可能分发到不同的MySQL节点.所以需要对每一条SQL都进行语法分析得出需要路由的节点,然后把每个节点的结果集取回,依照原来SQL的顺序组合成最终结果集作为相应

在发送SQL的时候有两种实现方式


根据经验,在mysql对多条SQL的处理中, 只要当前有一条SQL发生异常,mysql就不会处理后续的SQL所以其后的SQL将不会处理.

按照SQL的顺序依次发送,在这个过程中, 只要当前有一条SQL发生异常,mycat就不会往之后的节点发送SQL.mycat为了与数据库的响应一致,他们的结果集由mycat生成..对于有事务参与的情况,由于插入的节点是在不同的mysql上,所以事务涉及到多个节点参与,该问题演变成分布式事务问题.难以解决.

SQL并行发送,鉴于网络与数据库本身的复杂性,只需把结果集按照SQL的顺序组装就可以完成功能,但是结果集中,包含了正确完成的结果集也包含了错误的结果集.尚不确定jdbc客户端支持这种方式,可能需要与业务情况才能使用.

解决

由于mycat暂不支持多个SQL在一次请求中发送的问题,对于多条insert语句的情况,可以把它写成
INSERT INTO table_name VALUES (value1,value2,value3,…),(value1,value2,value3,…);
的形式
故有

SQL语句:
INSERT INTO travelrecord(id,user_id,traveldate,fee,days) VALUES
(1,’000001’,NOW(),1235,6),
(10000000,’930002’,NOW(),1235,6);
发现mycat能支持而且能正确路由
Q群文件-Mycat批量插入问题 - 图3
通过wireshark抓包查看
INSERT INTO table_name VALUES (value1,value2,value3,…),(value1,value2,value3,…);
的响应
Q群文件-Mycat批量插入问题 - 图4
Q群文件-Mycat批量插入问题 - 图5
发现mycat发送了正确的插入语句并且返回了正确的操作结果.

总结

mycat对一条SQL中包含多条SQL语句的解析和多结果集的响应解析支持有限,对于多条sql 插入的形式不支持,但是可以通过自己组装插入的值域,实现对一个表批量插入数据.