笔记-连接池

笔记-连接池

池化技术

池化技术能够减少资源对象的创建次数, 减少对象创建和销毁的事件

原理

  1. 正常一个MySQL的操作流程: TCP三次握手->MySQL认证->SQL执行->MySQL关闭->四次挥手
  2. 将TCP三次握手和MySQL认证创建后的连接放到连接容器(连接池)中
  3. 池化后的MySQL操作流程: 从连接池取出一个连接->MySQL执行->归还MySQL连接

连接池设计

  1. DBConnection, 数据库的连接对象, 同时数据库的操作由DBConnection实现
  2. DBConnectionPool, 数据库连接对象的池化管理类, 主要是对DBConnection的管理
    • m_free_list, 空闲的连接, 通过链表管理
    • m_used_list, 被使用的连接, 通过链表管理
    • int m_max_conn_cnt, 线程池最大容纳连接数
    • int m_cur_conn_cnt, 当前创建的连接数
    • m_abort_request, 退出连接池
    • std::mutex m_mutex, 互斥量
    • std::condition_variable m_cond, 通知陷入超时等待getDBConnect函数可以取连接对象
    • int init(), 创建m_cur_conn_cnt大小的连接数, m_cur_conn_cnt需要在构造函数中赋值最小连接数
    • DBConnection* getDBConnection(const int timeout_ms), 获取连接
      • 空闲队列为空, 当前连接大于等于最大连接, timeout不大于0, m_cond.wait()
      • 空闲队列为空, 当前连接大于等于最大连接, timeout大于0, m_cond.wait_for()
      • 空闲队列为空, 当前连接小于最大连接, 创建新的连接, 添加到空闲队列中
      • 从空闲队列中取除连接, 然后将连接放到m_used_list中
    • void relDbConnection(DBConnection* conn), 归还连接, 用完连接之后必须归还
      • 将conn从m_used_list中删除
      • 将conn添加到m_free_list中
      • 通过m_cond.notufy_one()通知陷入m_cond.wait()的线程
    • ~DBConnectionPool
      • 将m_abort_request=true
      • 利用m_cond.notify_all()通知所有等待超时的线程
      • 删除m_free_conn;

MySQL连接重连机制

  • 方法
    • 每次操作之前先去测试链路是否通
    • 先执行任务
      • 执行失败后mysql_ping
      • 执行失败后释放资源, mysql_close(mysql); mysql = NULL;, 这样情况下需要对free_conn_list中的conn进行if=NULL判断
  • 设置启用(当发现连接断开时的)自动重连
    my_bool reconnect = true;
    mysql_options(m_mysql, MYSQL_OPT_RECONNECT, &reconnect); // 配合mysql_ping实现自动重连
  • 检测连接是否正常
    int STDCALL mysql_ping(MYSQL *mysql);
    检查与服务端的连接是否正常。连接断开时,如果自动重新连接功能未被禁用,则尝试重新连接服务器。该函数可被客户端用来检测闲置许久以后,与服务端的连接是否关闭,如有需要,则重新连接。
    返回值:
    连接正常,返回0;如有错误发生,则返回非0值。返回非0值并不意味着服务器本身关闭掉,也有可能是网络原因导致网络不通.
  • 每一次执行MySQL语句都先用mysql_ping进行检测

其他

  1. 线程池和连接池有什么区别? 线程池, 主动操作, 主动去执行任务; 连接池, 被动操作, 池的对象被任务获取, 执行完任务后归还.
  2. 每个线程绑定一个连接的方法缺点? 代码耦合性高
  3. 长连接和短连接的区别? 连接池使用的是长连接.
  4. 同步连接和异步连接? 同步连接池,存在IO阻塞; 异步连接池, 效率高, 但会增加编程难度.
上一篇:压缩sql server 数据库的空间,清理日志.ldf


下一篇:7.文件重定向和管道