csv导入mysql_我的投机取巧竟然忘了mysql还有一个最大值的限制

  • Post author:
  • Post category:mysql


前言:项目开发中没有考虑到数据量的问题,在运行阶段突然有一天报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。

546f6bc9c54be0868f4e9a5ad7012e44.png

foreach写法

但是这里有个bug,我没有考虑到mysql中有一个大小限制,即

max_allowed_packet

项目这是运行后,发现有一个大账户,插入一直报错,查看日志发现如图错误。

10ae31b3ca412ee4de903269ac3eaca4.png

报错信息

Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large

意思就是我超过Packet的最大限制了。也就是我上面提到的max_allowed_packet这个参数。查看这个参数:

7c77db0d2ce42c81ba1ab2a9816121e4.png

查看max_allowed_packet

1048576字节=1M,也就是mysql默认的。那么问题来了,我是修改这个参数,还是另寻其它解决办法。我选择了最后一个。原因:

  1. 因为线上数据库不允许重启,网上百度说设置这个参数后,重启才能生效。
  2. 这个值设置多大合适不知道,我这次设置为2M,下次可能出现个3M的情况。

不知道大家有没有实现过采用文件的形式插入数据,即load方式。

我的实现方式,先把数据写入到csv文件里,我通过load把这个文件的数据插入到数据库。

bc9a639be3df4a6fce48c0be5486bb2e.png

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

总结:

  1. 在查询大数据量和插入大数据量数据时,一定要注意max_allowed_packet的值问题,这里我们可以采用分页查询,分页插入。
  2. load方式在处理大数据量问题还是比较容易的,而且速度很快。