SequelizeJS批量插入数据时在第1000次循环停止无报错求助
为什么你的数据插入到1000条就停了?
嘿,我来帮你拆解这个问题——你写的代码逻辑看着没问题,但处理1050条数据时卡在第1000条,核心原因是无限制的并发数据库请求加上缺少错误处理,导致后续请求静默失败了。
具体原因分析
- 连接池过载:你的Sequelize连接池设置了
max:5,意味着同一时间最多只能有5个数据库连接在工作。但你用data.map()一次性创建了1050个Data.create()的Promise,相当于同时发起1050条插入请求。这些请求会堆积在队列里,当队列太长时,部分请求会因为超时、数据库资源耗尽等原因被静默终止,而且你看不到报错。 - 未等待所有Promise完成:当前代码只是返回了Promise数组,但没有用
Promise.all来等待所有插入操作完成,程序可能在所有请求执行完毕前就提前结束了。 - 无错误捕获:单个
Data.create()的Promise如果失败,没有被单独捕获,会导致整个Promise链静默失败,你完全不知道哪里出了问题。
修复方案
方案1:分批处理(推荐,适配连接池)
最好的方式是分批插入,每次处理的数量和连接池最大连接数匹配,避免过载。我给你改了代码,加入了分批逻辑:
import data from './data'; const Sequelize = require('sequelize'); const sequelize = new Sequelize('graphql', 'billy', '', { host: 'localhost', dialect: 'postgres', operatorsAliases: false, pool: { max: 5, min: 0, acquire: 30000, idle: 10000 } }); sequelize .authenticate() .then(() => { console.log('Connection has been established successfully.'); }) .catch(err => { console.error('Unable to connect to the database:', err); }); const Data = sequelize.define('data', { name: Sequelize.TEXT, }); // 分批插入函数,每次处理指定数量的数据 const batchInsert = async (items, batchSize) => { for (let i = 0; i < items.length; i += batchSize) { const currentBatch = items.slice(i, i + batchSize); // 等待当前批次所有插入完成再处理下一批 await Promise.all( currentBatch.map((item, index) => { return Data.create({ name: item.name }) .catch(err => { // 单独捕获每条数据的错误,避免整批失败 console.error(`插入第${i + index + 1}条数据失败:`, err); return Promise.resolve(); // 确保Promise.all不会因为单个错误中断 }); }) ); console.log(`已完成 ${Math.min(i + batchSize, items.length)} 条数据插入`); } }; Data.sync({ force: true }) .then(async () => { console.log('表已创建,开始插入数据...'); // 每次处理5条,和连接池最大连接数一致 await batchInsert(data, 5); console.log('所有1050条数据都插入完成啦!'); }) .catch(err => { console.error('表同步或插入过程出错:', err); });
方案2:用bulkCreate批量插入(更高效)
如果只是单纯插入数据,Sequelize的bulkCreate比循环调用create高效太多,它会生成单条INSERT语句插入多条数据,减少数据库交互次数:
// ... 前面的连接和模型定义代码不变 ... const bulkInsert = async (items, batchSize) => { for (let i = 0; i < items.length; i += batchSize) { const batchData = items.slice(i, i + batchSize).map(item => ({ name: item.name })); await Data.bulkCreate(batchData) .catch(err => { console.error(`第${Math.floor(i/batchSize) + 1}批次插入失败:`, err); }); console.log(`已完成 ${Math.min(i + batchSize, items.length)} 条数据插入`); } }; Data.sync({ force: true }) .then(async () => { console.log('表已创建,开始批量插入数据...'); // 每次批量插入100条,这个数字可以根据数据库性能调整 await bulkInsert(data, 100); console.log('所有数据插入完成!'); }) .catch(err => { console.error('操作出错:', err); });
额外小贴士
- 可以在Sequelize配置里加上
logging: console.log,这样能看到生成的SQL语句,方便排查问题。 - 检查PostgreSQL的
max_connections配置(默认是100),确保不会因为连接数耗尽导致失败。 - 永远记得给Promise添加错误捕获,不然静默失败会让你查问题查到崩溃😅
内容的提问来源于stack exchange,提问作者jackdaw
相关产品推荐
相关产品推荐

