前言

准备mysql环境

详细可参考:mysql环境准备

下面是简单步骤。环境是ubuntu20,mysql版本是8.0.30

sudo apt-get install mysql-server # mysql数据库服务端
sudo apt install mysql-workbench-community # mysql数据库图形化客户端
sudo apt install libmysqlcppconn-dev # mysql C++接口的头文件和库

# 数据库root用户默认设置是无法远程登录。系统root用户下,可以免密登录数据库
# 使用系统root免密登录,数据库root用户;在数据库root用户下,创建一个可以远程访问的新用户
su -
mysql -u root
CREATE USER  'dacao'@'%'  IDENTIFIED BY 'qwert';

# 创建数据库
create database message_board

# 将创建的数据库的所有权限给新创建的用户
GRANT ALL privileges  ON message_board.*  TO 'dacao'@'%';

# 这时候,我们可以退出root用户,使用mysql-workbench连接我们上面创建的数据库
# 连接成功后,我们创建一个表
show databases;

USE message_board;

CREATE TABLE message(
    username char(50) NULL,
    message char(50) NULL
)ENGINE=InnoDB;

# INSERT INTO user(username, passwd) VALUES('zhangsan', 'hello world');
# select * from user;

目标-寻找一个C++的mysql数据库连接池

mysql提供了不同语言的连接接口,可见:Connectors and APIs

第一种是MySQL 8.0 C API Developer Guide。网上有不同的封装,大同小异,可参考参考:C++ mysql连接池 附带讲解与详细注释源码qinguoyi/TinyWebServer-sql_connection_pool.cpp。(不明白,既然官方已经提供了mysq的c++ api,为啥还要再封装mysql的C接口。)

第二种是MySQL Connector/C++ 8.0 Developer Guide。第三种是Connector/C/C++ X DevAPI Reference。由于我之前整理过C++连接MySQL数据库,这里不再赘述。

其中,X DevAPI提供了mysql的数据库连接池的api,可参考:2.2.3 Connecting to a Single MySQL Server Using Connection Pooling

2022/11/6修改。我除了mysql官网,我到A list of open source C++ libraries瞅了瞅,看到里面有MySQL/MariaDB的C++库。


X DevAPI - 数据库连接池

没有写多线程测试,只是写了一个简单的demo跑了下。

有两个问题没有仔细考察:

  • 当线程池中没有连接可用时,cli.getSession();是否阻塞。我想应该时阻塞的?Client的接口文档中也没写,只能到源码中找答案了。
  • 抛出异常该如何接收和处理。抛出的异常类型是 mysqlx::Error,可参考Sample code which uses Connector/C++ with X DevAPI
// compile:  g++  test-x-plugin.cpp -o test-x-plugin -I /usr/include/mysql-cppconn-8/  -lmysqlcppconn8

#include <mysqlx/xdevapi.h>
#include <iostream>
#include <list>

/**
 * 数据库连接,并给表插入一列
 */
void unit_test_1(void) {
  mysqlx::Session sess("localhost", 33060, "dacao", "qwert");
  mysqlx::Schema db= sess.getSchema("message_board");
  mysqlx::Table tb = db.getTable("message");

  tb.insert("username", "message")
                               .values("lisi","hello world")
                               .execute();
}

/**
 * 数据库连接池
 */
void unit_test_2(void) {
  using namespace mysqlx;
  // Client cli("user:password@host_name/db_name", ClientOption::POOL_MAX_SIZE, 7);
  Client cli("dacao:qwert@127.0.0.1", ClientOption::POOL_MAX_SIZE, 7);
  Session sess = cli.getSession();

  mysqlx::Schema db= sess.getSchema("message_board");
  mysqlx::Table tb = db.getTable("message");
  mysqlx::RowResult result = tb.select("*").execute();
  std::list<mysqlx::Row> rows = result.fetchAll();
  std::cout<<"name "<<"password "<<std::endl;
  for(auto row : rows) {
    std::cout<<row[0]<<" "<<row[1]<<std::endl;
  }

  cli.close();  // close all Sessions
}


int main(int argc, char** argv)
{
  unit_test_1();
  unit_test_2();
}

上面代码需要提下的是,连接数据库的参考。第一种连接是mysqlx::Session sess("localhost", 33060, "dacao", "qwert");。第二种连接是Client cli("dacao:qwert@127.0.0.1/message_board", ClientOption::POOL_MAX_SIZE, 7);。这两种构造过程是类似的,可以看下xdevapi.h源文件中的注释。

Session from_uri("mysqlx://user:pwd@host:port/db?ssl-mode=disabled");
Session from_options("host", port, "user", "pwd", "db");
Session from_option_list(
    SessionOption::USER, "user",
    SessionOption::PWD,  "pwd",
    SessionOption::HOST, "host",
    SessionOption::PORT, port,
    SessionOption::DB,   "db",
    SessionOption::SSL_MODE, SSLMode::DISABLED
    );

Client from_uri("mysqlx://user:pwd\@host:port/db?ssl-mode=disabled");
Client from_options("host", port, "user", "pwd", "db");
Client from_option_list(
    SessionOption::USER, "user",
    SessionOption::PWD,  "pwd",
    SessionOption::HOST, "host",
    SessionOption::PORT, port,
    SessionOption::DB,   "db",
    SessionOption::SSL_MODE, SSLMode::DISABLED
    ClientOption::POOLING, true,
    ClientOption::POOL_MAX_SIZE, 10,
    ClientOption::POOL_QUEUE_TIMEOUT, 1000,
    ClientOption::POOL_MAX_IDLE_TIME, 500,
);
,
    ClientOption::POOL_MAX_SIZE, 10,
    ClientOption::POOL_QUEUE_TIMEOUT, 1000,
    ClientOption::POOL_MAX_IDLE_TIME, 500,
);
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐