首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 查詢效能優化三部曲(三):連接池模式 C++ 實現與線程安全設計

     編輯:MySQL 資料庫相關知識

高併發 MySQL 訪問:連接池設計模式與 C++ 線程安全實現

在大量節點併發訪問 MySQL 時,頻繁建立/銷毀連接是效能殺手。連接池透過預建連接、線程安全借還、生命週期管理,大幅降低延遲並穩定資源消耗。本文給出生產級 C++ 連接池完整實現,含雙佇列架構、互斥鎖保護、RAII 資源管理。

連接池核心架構

  • 空閒佇列:可用連接句柄池
  • 忙碌佇列:正在使用的連接句柄
  • 互斥鎖:保護佇列操作原子性
  • 信號量/條件變量:空池等待、滿池阻塞(可選)

完整 C++ 實現

#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();
    }
};

關鍵設計亮點

使用範例

int main() {
    CDBParameter param{"localhost", "app_user", "pass", "app_db"};
    CDBManager pool(param, 50);
    if (!pool.initialize()) return 1;

    // 併發任務模擬
    std::vector threads;
    for (int i = 0; i < 100; ++i) {
        threads.emplace_back([&pool, i] {
            char sid[32];
            snprintf(sid, sizeof(sid), "session_%d", i);
            if (pool.deleteBySessionId(sid)) {
                // 成功
            }
        });
    }
    for (auto& t : threads) t.join();
    return 0;
}

生產環境擴展建議

  1. 連接健康檢查:定時 mysql_ping() 或 SELECT 1,失效重建
  2. 監控指標:池使用率、等待時間、建立/銷毀頻率、錯誤率
  3. 優雅關閉:停止接收新請求 → 等待忙碌連接歸還 → 關閉所有連接
  4. 多主機支援:主從分離,讀寫連接池隔離
  5. 替代方案:ProxySQL(中間件連接池)、HikariCP (JDBC)、PgBouncer (PostgreSQL)

連接池是高併發資料庫訪問的基石。C++ 實現雖繁瑣,但能精確控制資源生命週期,是效能敏感型系統的最佳選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性實現方式效益
線程安全std::mutex 保護雙佇列 + condition_variable 等待無競態條件,無死鎖
RAII 自動歸還ConnectionGuard 建構函數獲取,解構函數歸還彈性異常安全,無連接洩漏
超時控制wait_for 可配置超時避免無限阻塞,可熔斷降級
連接驗證歸還前可選 mysql_ping() 檢測斷連自動剔除失效連接
動態擴容空池且未達上限時 mysql_real_connect 新建應對突發流量