由于MySQL连接池的实现涉及到很多细节,这里只提供一个简单的连接池实现供参考。如果需要更加完整和高效的实现,请参考第三方库或者自行实现。

该连接池实现主要包括以下几个部分:

1.连接池的初始化

2.连接池的连接和断开连接

3.连接池的主备切换

4.连接池中连接的使用

以下是一个简单的实现:

#include <mysql/mysql.h>
#include <queue>
#include <pthread.h>
#include <string>
#include <iostream>
#include <unistd.h>

using namespace std;

class MysqlConnPool {
public:
    MysqlConnPool(string host, string user, string passwd, string db, int port, int max_conn);
    ~MysqlConnPool();
    MYSQL* get_conn();
    void free_conn(MYSQL* conn);
    void switch_master_slave(string new_host);

private:
    string host_;
    string user_;
    string passwd_;
    string db_;
    int port_;
    int max_conn_;
    queue<MYSQL*> conn_queue_;
    pthread_mutex_t lock_;
    pthread_cond_t cond_;
    MYSQL* create_conn();
    void destroy_conn(MYSQL* conn);
    bool is_master_;
};

MysqlConnPool::MysqlConnPool(string host, string user, string passwd, string db, int port, int max_conn) {
    host_ = host;
    user_ = user;
    passwd_ = passwd;
    db_ = db;
    port_ = port;
    max_conn_ = max_conn;
    is_master_ = true;

    pthread_mutex_init(&lock_, NULL);
    pthread_cond_init(&cond_, NULL);

    for (int i = 0; i < max_conn_; i++) {
        MYSQL* conn = create_conn();
        if (conn) {
            conn_queue_.push(conn);
        } else {
            cout << "create mysql connection error!" << endl;
        }
    }
}

MysqlConnPool::~MysqlConnPool() {
    pthread_mutex_lock(&lock_);
    while (!conn_queue_.empty()) {
        MYSQL* conn = conn_queue_.front();
        conn_queue_.pop();
        destroy_conn(conn);
    }
    pthread_mutex_unlock(&lock_);

    pthread_mutex_destroy(&lock_);
    pthread_cond_destroy(&cond_);
}

MYSQL* MysqlConnPool::create_conn() {
    MYSQL* conn = mysql_init(NULL);
    if (conn) {
        conn = mysql_real_connect(conn, host_.c_str(), user_.c_str(), passwd_.c_str(), db_.c_str(), port_, NULL, 0);
        if (conn) {
            mysql_query(conn, "set names utf8");//设置编码格式
        } else {
            cout << "connect to mysql error: " << mysql_error(conn) << endl;
        }
    } else {
        cout << "init mysql error: " << mysql_error(conn) << endl;
    }
    return conn;
}

void MysqlConnPool::destroy_conn(MYSQL* conn) {
    if (conn) {
        mysql_close(conn);
    }
}

MYSQL* MysqlConnPool::get_conn() {
    MYSQL* conn = NULL;
    pthread_mutex_lock(&lock_);
    while (conn_queue_.empty()) {
        pthread_cond_wait(&cond_, &lock_);
    }
    if (!conn_queue_.empty()) {
        conn = conn_queue_.front();
        conn_queue_.pop();
    }
    pthread_mutex_unlock(&lock_);
    return conn;
}

void MysqlConnPool::free_conn(MYSQL* conn) {
    pthread_mutex_lock(&lock_);
    conn_queue_.push(conn);
    pthread_cond_signal(&cond_);
    pthread_mutex_unlock(&lock_);
}

void MysqlConnPool::switch_master_slave(string new_host) {
    pthread_mutex_lock(&lock_);

    while (!conn_queue_.empty()) {
        MYSQL* conn = conn_queue_.front();
        conn_queue_.pop();
        destroy_conn(conn);
    }

    host_ = new_host;
    is_master_ = !is_master_;

    for (int i = 0; i < max_conn_; i++) {
        MYSQL* conn = create_conn();
        if (conn) {
            conn_queue_.push(conn);
        } else {
            cout << "create mysql connection error!" << endl;
        }
    }

    pthread_mutex_unlock(&lock_);
}

int main() {
    MysqlConnPool pool("localhost", "root", "123456", "test", 3306, 5);
    MYSQL* conn = pool.get_conn();
    if (conn) {
        mysql_query(conn, "select * from user");
        MYSQL_RES* res = mysql_store_result(conn);
        if (res) {
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res))) {
                cout << row[0] << " " << row[1] << endl;
            }
            mysql_free_result(res);
        }
        pool.free_conn(conn);
    }

    sleep(5);//等待5秒

    pool.switch_master_slave("192.168.0.1");//切换到备库

    conn = pool.get_conn();
    if (conn) {
        mysql_query(conn, "select * from user");
        MYSQL_RES* res = mysql_store_result(conn);
        if (res) {
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res))) {
                cout << row[0] << " " << row[1] << endl;
            }
            mysql_free_result(res);
        }
        pool.free_conn(conn);
    }

    return 0;
}

该连接池使用一个队列来保存连接,当需要获取连接时,从队列中取出一个连接,如果队列为空,则等待条件变量的通知。当需要释放连接时,将连接放回队列中,并发送条件变量的通知。当需要切换主备库时,先销毁所有连接,然后重新创建连接。需要注意的是,需要在切换主备库时,先加锁,以避免并发问题。

该连接池的主要缺点是,每次获取和释放连接时都需要加锁和解锁,会影响性能。如果用户数量较少,可以考虑使用一个线程来维护连接池,定期检查连接的可用性,并进行主备切换。如果用户数量较多,可以考虑使用多个连接池,并使用负载均衡算法来分配连接。

使用c++编写一个通用的mysql连接池需要支持主备切换

原文地址: https://www.cveoy.top/t/topic/rgS 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录