千家信息网

怎么保证快速且安全大批量插入数据到数据库

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容主要讲解"怎么保证快速且安全大批量插入数据到数据库",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么保证快速且安全大批量插入数据到数据库"吧!前言
千家信息网最后更新 2026年11月01日怎么保证快速且安全大批量插入数据到数据库

本篇内容主要讲解"怎么保证快速且安全大批量插入数据到数据库",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"怎么保证快速且安全大批量插入数据到数据库"吧!

前言

最近有个需求解析一个订单文件,并且说明文件可达到千万条数据,每条数据大概在20个字段左右,每个字段使用逗号分隔,需要尽量在半小时内入库。

思路

1.估算文件大小

因为告诉文件有千万条,同时每条记录大概在20个字段左右,所以可以大致估算一下整个订单文件的大小,方法也很简单使用FileWriter往文件中插入一千万条数据,查看文件大小,经测试大概在1.5G左右;

2.如何批量插入

由上可知文件比较大,一次性读取内存肯定不行,方法是每次从当前订单文件中截取一部分数据,然后进行批量插入,如何批次插入可以使用insert(...)values(...),(...)的方式,经测试这种方式效率还是挺高的;

3.数据的完整性

截取数据的时候需要注意,需要保证数据的完整性,每条记录最后都是一个换行符,需要根据这个标识保证每次截取都是整条数,不要出现半条数据这种情况;

4.数据库是否支持批次数据

因为需要进行批次数据的插入,数据库是否支持大量数据写入,比如这边使用的mysql,可以通过设置max_allowed_packet来保证批次提交的数据量;

5.中途出错的情况

因为是大文件解析,如果中途出现错误,比如数据刚好插入到900w的时候,数据库连接失败,这种情况不可能重新来插一遍,所有需要记录每次插入数据的位置,并且需要保证和批次插入的数据在同一个事务中,这样恢复之后可以从记录的位置开始继续插入。

实现

1.准备数据表

这里需要准备两张表分别是:订单状态位置信息表,订单表;

CREATE TABLE `file_analysis` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `file_type` varchar(255) NOT NULL COMMENT '文件类型 01:类型1,02:类型2',  `file_name` varchar(255) NOT NULL COMMENT '文件名称',  `file_path` varchar(255) NOT NULL COMMENT '文件路径',  `status` varchar(255) NOT NULL COMMENT '文件状态  0初始化;1成功;2失败:3处理中',  `position` bigint(20) NOT NULL COMMENT '上一次处理完成的位置',  `crt_time` datetime NOT NULL COMMENT '创建时间',  `upd_time` datetime NOT NULL COMMENT '更新时间',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
CREATE TABLE `file_order` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `file_id` bigint(20) DEFAULT NULL,  `field1` varchar(255) DEFAULT NULL,  `field2` varchar(255) DEFAULT NULL,  `field3` varchar(255) DEFAULT NULL,  `field4` varchar(255) DEFAULT NULL,  `field5` varchar(255) DEFAULT NULL,  `field6` varchar(255) DEFAULT NULL,  `field7` varchar(255) DEFAULT NULL,  `field8` varchar(255) DEFAULT NULL,  `field9` varchar(255) DEFAULT NULL,  `field10` varchar(255) DEFAULT NULL,  `field11` varchar(255) DEFAULT NULL,  `field12` varchar(255) DEFAULT NULL,  `field13` varchar(255) DEFAULT NULL,  `field14` varchar(255) DEFAULT NULL,  `field15` varchar(255) DEFAULT NULL,  `field16` varchar(255) DEFAULT NULL,  `field17` varchar(255) DEFAULT NULL,  `field18` varchar(255) DEFAULT NULL,  `crt_time` datetime NOT NULL COMMENT '创建时间',  `upd_time` datetime NOT NULL COMMENT '更新时间',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=10000024 DEFAULT CHARSET=utf8
2.配置数据库包大小
mysql> show VARIABLES like '%max_allowed_packet%';+--------------------------+------------+| Variable_name            | Value      |+--------------------------+------------+| max_allowed_packet       | 1048576    || slave_max_allowed_packet | 1073741824 |+--------------------------+------------+2 rows in setmysql> set global max_allowed_packet = 1024*1024*10;Query OK, 0 rows affected

通过设置max_allowed_packet,保证数据库能够接收批次插入的数据包大小;不然会出现如下错误:

Caused by: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (4980577 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.    at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3915)    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2598)    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778)    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2834)
3.准备测试数据
    public static void main(String[] args) throws IOException {        FileWriter out = new FileWriter(new File("D://xxxxxxx//orders.txt"));        for (int i = 0; i < 10000000; i++) {            out.write(                    "vaule1,vaule2,vaule3,vaule4,vaule5,vaule6,vaule7,vaule8,vaule9,vaule10,vaule11,vaule12,vaule13,vaule14,vaule15,vaule16,vaule17,vaule18");            out.write(System.getProperty("line.separator"));        }        out.close();    }

使用FileWriter遍历往一个文件里插入1000w条数据即可,这个速度还是很快的,不要忘了在每条数据的后面添加换行符(\n\r);

4.截取数据的完整性

除了需要设置每次读取文件的大小,同时还需要设置一个参数,用来每次获取一小部分数据,从这小部分数据中获取换行符(\n\r),如果获取不到一直累加直接获取为止,这个值设置大小大致同每条数据的大小差不多合适,部分实现如下:

ByteBuffer byteBuffer = ByteBuffer.allocate(buffSize); // 申请一个缓存区long endPosition = batchFileSize + startPosition - buffSize;// 子文件结束位置long startTime, endTime;for (int i = 0; i < count; i++) {    startTime = System.currentTimeMillis();    if (i + 1 != count) {        int read = inputChannel.read(byteBuffer, endPosition);// 读取数据        readW: while (read != -1) {            byteBuffer.flip();// 切换读模式            byte[] array = byteBuffer.array();            for (int j = 0; j < array.length; j++) {                byte b = array[j];                if (b == 10 || b == 13) { // 判断\n\r                    endPosition += j;                    break readW;                }            }            endPosition += buffSize;            byteBuffer.clear(); // 重置缓存块指针            read = inputChannel.read(byteBuffer, endPosition);        }    } else {        endPosition = fileSize; // 最后一个文件直接指向文件末尾    }    ...省略,更多可以查看Github完整代码...}

如上代码所示开辟了一个缓冲区,根据每行数据大小来定大概在200字节左右,然后通过遍历查找换行符(\n\r),找到以后将当前的位置加到之前的结束位置上,保证了数据的完整性;

5.批次插入数据

通过insert(...)values(...),(...)的方式批次插入数据,部分代码如下:

// 保存订单和解析位置保证在一个事务中        SqlSession session = sqlSessionFactory.openSession();        try {            long startTime = System.currentTimeMillis();            FielAnalysisMapper fielAnalysisMapper = session.getMapper(FielAnalysisMapper.class);            FileOrderMapper fileOrderMapper = session.getMapper(FileOrderMapper.class);            fileOrderMapper.batchInsert(orderList);            // 更新上次解析到的位置,同时指定更新时间            fileAnalysis.setPosition(endPosition + 1);            fileAnalysis.setStatus("3");            fileAnalysis.setUpdTime(new Date());            fielAnalysisMapper.updateFileAnalysis(fileAnalysis);            session.commit();            long endTime = System.currentTimeMillis();            System.out.println("===插入数据花费:" + (endTime - startTime) + "ms===");        } catch (Exception e) {            session.rollback();        } finally {            session.close();        }        ...省略,更多可以查看Github完整代码...

如上代码在一个事务中同时保存批次订单数据和文件解析位置信息,batchInsert通过使用mybatis的标签来遍历订单列表,生成values数据;

总结

以上展示了部分代码,完整的代码可以查看Github地址中的batchInsert模块,本地设置每次截取的文件大小为2M,经测试1000w条数据(大小1.5G左右)插入mysql数据库中,大概花费时间在20分钟左右,当然可以通过设置截取的文件大小,花费的时间也会相应的改变。

到此,相信大家对"怎么保证快速且安全大批量插入数据到数据库"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

数据 文件 大小 保证 位置 数据库 批次 订单 代码 时间 部分 同时 完整性 换行符 更新 测试 安全 大批量 万条 事务 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 百单网互联网科技有限公司怎么样 关于新基建和互联网科技 汇久创客互联网科技 猫创互联网科技 科技互联网创业计划书 互联网养老 桔豆科技 联恩商钥互联网科技有限公司 互联网公司会议桌创意科技软装饰 贵州叶脉互联网科技有限公司所属行业 宁夏科技产业互联网案例 宜昌元轩互联网科技有限公司 华夏恒生科技与互联网科技 领航科技大厦互联网公司 互联网科技股为什么大涨 互联网领先科技活动 三亚科技创新互联网基地 互联网大会出现的黑科技 六子台科技互联网展会 利用互联网等科技手段 每日互联网科技新闻 互联网巨头反垄断金融科技 互联网 科技创新 华宇互联网科技 兼蜜互联网科技 衡水科技产业互联网平台 创业天下互联网科技有限公司 广西互联网科技孵化中心 四川慕妮娅互联网科技有限公司 互联网科技圈年度人物 神州科技互联网有限公司
0