在大量節點併發訪問 MySQL 時,頻繁建立/銷毀連接是效能殺手。連接池透過預建連接、線程安全借還、生命週期管理,大幅降低延遲並穩定資源消耗。本文給出生產級 C++ 連接池完整實現,含雙佇列架構、互斥鎖保護、RAII 資源管理。
#include
#include
#include
#include
#include
class CDBParameter {
public:
std::string host, user, password, database;
unsigned int port = 0;
const char* unix_socket = nullptr;
unsigned int client_flag = 0;
};
class CDBManager {
using HandleList = std::list;
using HandleIter = HandleList::iterator;
HandleList m_idleList; // 空閒連接
HandleList m_busyList; // 忙碌連接
std::mutex m_mutex; // 佇列鎖
std::condition_variable m_cv; // 等待可用連接
CDBParameter m_param;
const size_t m_maxSize;
public:
explicit CDBManager(const CDBParameter& param, size_t maxSize = 100)
: m_param(param), m_maxSize(maxSize) {}
~CDBManager() { destroyAll(); }
// 初始化:預建所有連接
bool initialize() {
std::lock_guard lock(m_mutex);
for (size_t i = 0; i < m_maxSize; ++i) {
MYSQL* handle = mysql_init(nullptr);
if (!handle || !mysql_real_connect(handle,
m_param.host.c_str(), m_param.user.c_str(),
m_param.password.c_str(), m_param.database.c_str(),
m_param.port, m_param.unix_socket, m_param.client_flag)) {
if (handle) mysql_close(handle);
destroyAll();
return false;
}
m_idleList.push_back(handle);
}
return true;
}
// 獲取空閒連接(阻塞直到可用或超時)
MYSQL* acquire(std::chrono::milliseconds timeout = std::chrono::seconds(10)) {
std::unique_lock lock(m_mutex);
if (m_cv.wait_for(lock, timeout, [this]{ return !m_idleList.empty(); })) {
MYSQL* handle = m_idleList.front();
m_idleList.pop_front();
m_busyList.push_back(handle);
return handle;
}
return nullptr; // 超時
}
// 歸還連接
void release(MYSQL* handle) {
std::lock_guard lock(m_mutex);
auto it = std::find(m_busyList.begin(), m_busyList.end(), handle);
if (it != m_busyList.end()) {
m_busyList.erase(it);
m_idleList.push_back(handle);
m_cv.notify_one();
}
}
// RAII 守衛:自動歸還
class ConnectionGuard {
CDBManager& pool;
MYSQL* handle;
public:
ConnectionGuard(CDBManager& p) : pool(p), handle(p.acquire()) {}
~ConnectionGuard() { if (handle) pool.release(handle); }
MYSQL* operator->() { return handle; }
operator MYSQL*() { return handle; }
bool valid() const { return handle != nullptr; }
};
// 業務操作範例:按 SessionID 刪除
bool deleteBySessionId(const std::string& sessionId) {
ConnectionGuard conn(*this);
if (!conn.valid()) return false;
char sql[256];
snprintf(sql, sizeof(sql),
"DELETE FROM HostCache WHERE SessionID = '%s'",
sessionId.c_str());
return mysql_query(conn, sql) == 0;
}
private:
void destroyAll() {
std::lock_guard lock(m_mutex);
for (auto h : m_idleList) mysql_close(h);
for (auto h : m_busyList) mysql_close(h);
m_idleList.clear();
m_busyList.clear();
}
};
| 特性 | 實現方式 | 效益 |
|---|---|---|
| 線程安全 | std::mutex 保護雙佇列 + condition_variable 等待 | 無競態條件,無死鎖 |
| RAII 自動歸還 | ConnectionGuard 建構函數獲取,解構函數歸還 | 彈性異常安全,無連接洩漏 |
| 超時控制 | wait_for 可配置超時 | 避免無限阻塞,可熔斷降級 |
| 連接驗證 | 歸還前可選 mysql_ping() 檢測斷連 | 自動剔除失效連接 |
| 動態擴容 | 空池且未達上限時 mysql_real_connect 新建 | 應對突發流量 |