Skip to content

MySQL Connector/C++

MySQL Connector/C++ 是 MySQL 官方 C++ 驱动,支持传统 C API 和现代 X DevAPI,提供完整的 MySQL 访问能力。

安装

bash
# Ubuntu
sudo apt install libmysqlcppconn-dev

# vcpkg
vcpkg install libmysql

# CMake
find_package(MySQL REQUIRED)
target_link_libraries(myapp PRIVATE MySQL::MySQL)

基本连接与查询

cpp
#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>
#include <cppconn/exception.h>

int main() {
    try {
        sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();

        std::unique_ptr<sql::Connection> conn(
            driver->connect("tcp://127.0.0.1:3306", "root", "password"));
        conn->setSchema("mydb");

        // 普通查询
        std::unique_ptr<sql::Statement> stmt(conn->createStatement());
        std::unique_ptr<sql::ResultSet> res(
            stmt->executeQuery("SELECT id, name, age FROM users"));

        while (res->next()) {
            int id = res->getInt("id");
            std::string name = res->getString("name");
            int age = res->getInt("age");
            std::cout << id << " " << name << " " << age << "\n";
        }

    } catch (const sql::SQLException& e) {
        std::cerr << "MySQL 错误: " << e.what() << "\n";
        std::cerr << "错误码: " << e.getErrorCode() << "\n";
        std::cerr << "SQL 状态: " << e.getSQLState() << "\n";
    }
}

预处理语句

cpp
// 预处理语句:防 SQL 注入 + 性能更好
std::unique_ptr<sql::PreparedStatement> pstmt(
    conn->prepareStatement(
        "INSERT INTO users (name, email, age) VALUES (?, ?, ?)"));

pstmt->setString(1, "Alice");
pstmt->setString(2, "alice@example.com");
pstmt->setInt(3, 30);
pstmt->execute();

// 查询
std::unique_ptr<sql::PreparedStatement> select_stmt(
    conn->prepareStatement(
        "SELECT * FROM users WHERE age > ? AND name LIKE ?"));

select_stmt->setInt(1, 18);
select_stmt->setString(2, "%Alice%");

std::unique_ptr<sql::ResultSet> res(select_stmt->executeQuery());
while (res->next()) {
    std::cout << res->getString("name") << "\n";
}

// 获取最后插入的 ID
std::unique_ptr<sql::Statement> stmt(conn->createStatement());
stmt->execute("INSERT INTO users (name) VALUES ('Bob')");
std::unique_ptr<sql::ResultSet> id_res(
    stmt->executeQuery("SELECT LAST_INSERT_ID()"));
if (id_res->next()) {
    std::cout << "新 ID: " << id_res->getInt(1) << "\n";
}

事务

cpp
conn->setAutoCommit(false);  // 关闭自动提交

try {
    std::unique_ptr<sql::PreparedStatement> debit(
        conn->prepareStatement(
            "UPDATE accounts SET balance = balance - ? WHERE id = ?"));
    debit->setDouble(1, 100.0);
    debit->setInt(2, 1);
    debit->execute();

    std::unique_ptr<sql::PreparedStatement> credit(
        conn->prepareStatement(
            "UPDATE accounts SET balance = balance + ? WHERE id = ?"));
    credit->setDouble(1, 100.0);
    credit->setInt(2, 2);
    credit->execute();

    conn->commit();
    std::cout << "转账成功\n";

} catch (const sql::SQLException& e) {
    conn->rollback();
    std::cerr << "转账失败,已回滚: " << e.what() << "\n";
}

conn->setAutoCommit(true);

批量插入

cpp
conn->setAutoCommit(false);

std::unique_ptr<sql::PreparedStatement> pstmt(
    conn->prepareStatement(
        "INSERT INTO users (name, age) VALUES (?, ?)"));

for (int i = 0; i < 10000; ++i) {
    pstmt->setString(1, "User" + std::to_string(i));
    pstmt->setInt(2, 20 + i % 50);
    pstmt->addBatch();  // 添加到批次

    if (i % 1000 == 999) {
        pstmt->executeBatch();  // 每 1000 条提交一次
        conn->commit();
    }
}
pstmt->executeBatch();
conn->commit();

连接池(简单实现)

cpp
class MySQLPool {
    sql::mysql::MySQL_Driver* driver_;
    std::vector<std::unique_ptr<sql::Connection>> pool_;
    std::queue<sql::Connection*> available_;
    std::mutex mtx_;
    std::condition_variable cv_;

public:
    MySQLPool(const std::string& host, const std::string& user,
              const std::string& pass, const std::string& db, size_t size) {
        driver_ = sql::mysql::get_mysql_driver_instance();
        for (size_t i = 0; i < size; ++i) {
            auto conn = std::unique_ptr<sql::Connection>(
                driver_->connect(host, user, pass));
            conn->setSchema(db);
            available_.push(conn.get());
            pool_.push_back(std::move(conn));
        }
    }

    sql::Connection* acquire() {
        std::unique_lock lock(mtx_);
        cv_.wait(lock, [this] { return !available_.empty(); });
        auto* conn = available_.front();
        available_.pop();
        return conn;
    }

    void release(sql::Connection* conn) {
        std::lock_guard lock(mtx_);
        available_.push(conn);
        cv_.notify_one();
    }
};

关键认知

MySQL Connector/C++ 的预处理语句(prepareStatement)是防 SQL 注入的标准方式。批量插入时关闭自动提交(setAutoCommit(false)),每批次手动 commit,性能提升 10-100x。生产环境必须使用连接池。

系统学习 C++ 生态,深入底层架构