• [问题][已解决] 并发场景下 "mysql: too many connections" 原因


    问题出现是这样的,用node写爬虫, 之前每条数据都是await插入,并且是阻塞的,后来改成了非阻塞,可以并行插入操作,结果一直找不到原因。

    后来在日志中找到了 too many connections,分析如下:

    用nodejs写爬虫的时候,使用了类似这样的函数

    let conn = null;

    try{

      conn = await pool.getConnection();

      await conn.begin()

      let rst = await .conn.query('xxxx',params);

      // 处理rst

      ...

      await conn.commit()

    }catch(e){

      if(conn) await conn.rollback(); 

    }finally{

      if(conn) await conn.release();

    }

    乍一看没有问题,执行爬虫之后,我会调用这段代码把分析过的数据存在数据库里。

    但是由于我是使用非阻塞的形式进行抓取数据的,如下

    emitter.on('url_found', async (url)=>{

      // 请求url地址,获取返回的response body

      let res = await request(url);

      // 处理res

      ...

      // 后面调用上面的第一段代码

    })

    这里会发生一件事,就是可能同时触发了1000个这样的事件,然后一起获取链接,但是还没有释放,然后报错: too many connections

    ============================ 解决方案 ===============================

    改造获取sql连接的函数

    1. 判断当前连接数是否达到最大,如果否,则直接返回连接池内连接,连接数++

    2. 如果上述判断为true,则等待一个promise,将该promise的resolve函数推入等待队列

    3. 当某一个连接release的时候,连接数--

    4. release中调用pool的notifyFirstWaiting方法,每次取出队列第一个resolve并执行,然后该resolve出列

    5. 第二步中的promise的resolve被执行后,则会执行后续代码,此时等待的promise被唤醒,尝试重新获取连接返回

  • 相关阅读:
    Mysql -- SQL常用命令实例
    JavaWeb -- 文件上传下载示例
    Java -- 利用反射 操作任意数组,包括对象数组 和 基本数据类型的数组
    JavaWeb -- 自定义标签实例, 防盗链, JSTL 核心标签
    JavaWeb -- Jsp 自定义标签的使用
    JavaWeb -- http-equiv=refresh跳转的时候出现Session 丢失, 解决办法。。
    JavaScript -- 正则表达式 检验表单提交的内容
    FSG压缩壳和ImportREC的使用
    愉快的开始
    学习Python的捷径
  • 原文地址:https://www.cnblogs.com/kazetotori/p/9333465.html
Copyright © 2020-2023  润新知