使用cron定时任务时Scheduler报QueryFailedError: read ECONNRESET错误
问题原因分析
这个错误是MySQL服务端主动断开了空闲过久的数据库连接导致的:
- MySQL默认的
wait_timeout参数值为8小时,当应用侧连接池中的连接连续8小时没有任何请求交互,MySQL会主动关闭该连接 - 你的测试场景(接口调用、5分钟定时)连接一直处于高频活跃状态,不会触发超时回收;而每天凌晨1点执行的任务,和上一个工作日的业务请求间隔通常超过8小时,连接池里保存的旧连接已经失效,拿失效连接发起查询就会报
ECONNRESET错误
解决方案
- 方案1:配置数据库连接池自动校验连接有效性(最推荐)
从代码的Repository用法判断你使用的是TypeORM,在数据库配置中添加以下参数即可:
TypeOrmModule.forRoot({ // 保留其他原有配置 extra: { // 开启连接保活 keepAlive: true, // 从连接池取连接时先校验是否有效 testOnBorrow: true, // 校验用的轻量查询 validationQuery: 'SELECT 1', } })
- 方案2:定时任务执行前主动触发连接重连
在定时任务的业务逻辑前先执行一次无意义的轻量查询,自动触发连接池重建有效连接,同时可以优化原有的循环更新逻辑,减少数据库交互次数:
@Cron(CronExpression.EVERY_DAY_AT_1AM) async setValideFileRemainder() { // 新增:先执行轻量查询校验连接,失效会自动重连 await this.healthFileRepository.query('SELECT 1') // 原有日期计算逻辑 var date = new Date(); let dateToday = date.toISOString().split('T')[0]; // 优化:直接批量更新,无需先查询再循环逐个save await this.healthFileRepository.update( { remainder_date: dateToday }, { is_valide: 1 } ) }
可选优化:注意new Date().toISOString()输出的是UTC时间,如果你业务用北京时间,需要手动加8小时偏移,避免日期匹配和预期不符
- 方案3:调整MySQL超时参数(需数据库操作权限,按需选择)
修改MySQL配置文件my.cnf,将超时时间拉长到24小时以上,适配你的凌晨定时任务间隔:
wait_timeout = 86400 interactive_timeout = 86400
修改后重启MySQL生效。
内容的提问来源于stack exchange,提问作者DevHomie
相关产品推荐
相关产品推荐

