前言:项目开发中没有考虑到数据量的问题,在运行阶段突然有一天报Packet for query is too large错误。这里先说个例子,比如有10条数据需要插入到数据库。我们通常的实现是:
List list = new ArrayList<>();for(int i=0;i
而我不想在循环list了,我想一条sql搞定,因为mysql不是可以insert into table values(?,?),(?,?),(?,?)这样写吗。我在mybatis中使用foreach就可以实现了。
List list = new ArrayList<>();Map map = new HashMap();map.put("list",list);insert(map);
如下mybatis中foreach的写法,collection中的list就是我map中的list。
但是这里有个bug,我没有考虑到mysql中有一个大小限制,即
max_allowed_packet
。
项目这是运行后,发现有一个大账户,插入一直报错,查看日志发现如图错误。
Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large
意思就是我超过Packet的最大限制了。也就是我上面提到的max_allowed_packet这个参数。查看这个参数:
1048576字节=1M,也就是mysql默认的。那么问题来了,我是修改这个参数,还是另寻其它解决办法。我选择了最后一个。原因:
- 因为线上数据库不允许重启,网上百度说设置这个参数后,重启才能生效。
- 这个值设置多大合适不知道,我这次设置为2M,下次可能出现个3M的情况。
不知道大家有没有实现过采用文件的形式插入数据,即load方式。
我的实现方式,先把数据写入到csv文件里,我通过load把这个文件的数据插入到数据库。
这里呢一定要注意编码问题,不然会乱码还有数据之间是采用什么分隔的,如csv就是使用“,”分隔。
csv文件导入的sql:
LOAD DATA LOCAL INFILE 'E:/1111.csv' ignore into table qwe1231 CHARACTER SET utf8 fields terminated by ',' enclosed by "" IGNORE 1 LINES
总结:
- 在查询大数据量和插入大数据量数据时,一定要注意max_allowed_packet的值问题,这里我们可以采用分页查询,分页插入。
- load方式在处理大数据量问题还是比较容易的,而且速度很快。