# 数据库 **Repository Path**: canoe_lin/database ## Basic Information - **Project Name**: 数据库 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-10 - **Last Updated**: 2026-06-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # database demos 这个仓库用于记录 C++ 后端数据库学习过程,目前包含两条线: - `mysqlcpp`:一个用于学习 MySQL C API 封装的 C++23 header-only 小库 - `redis_demo`:使用 hiredis 连接 Redis 的最小 C++ 示例 当前目标不是做完整 ORM 或完整 Redis 客户端,而是通过小而清晰的示例理解数据库 API、RAII、异常安全和资源管理。 ## 当前阶段 `mysqlcpp v0.1` 已完成的核心能力: - `Connection`:管理 `MYSQL*`,负责连接、关闭、`Query`、`Execute` - `Result`:管理 `MYSQL_RES*`,析构时自动释放结果集 - `Row`:读取当前行字段,支持 `GetString`、`GetInt`、`Size` - `DbError`:统一抛出数据库相关异常 - `Transaction`:用 RAII 管理 `begin / commit / rollback` - CMake:构建 header-only 库和多个 examples Redis 当前完成: - 使用 hiredis 连接 Redis - 执行 `PING` - 正确释放 `redisReply*` 和 `redisContext*` ## 环境要求 当前优先支持 Linux / WSL Ubuntu。 需要: - C++23 编译器 - CMake 3.20+ - MySQL 客户端开发库 - hiredis 开发库 Ubuntu / WSL 安装依赖: ```bash sudo apt update sudo apt install -y default-libmysqlclient-dev libhiredis-dev build-essential cmake ``` ## 项目结构 ```text database/ CMakeLists.txt README.md include/ mysqlcpp/ mysqlcpp.hpp examples/ mysql_demo/ query_users.cpp execute_users.cpp transaction_transfer.cpp redis_demo/ redis_ping.cpp ``` ## 构建 ```bash cmake -S . -B build cmake --build build ``` 构建后会生成: ```text build/query_users build/execute_users build/transaction_transfer build/redis_ping ``` ## MySQL 基本连接 ```cpp mysqlcpp::Config config("127.0.0.1", "root", "root", "cpp_backend_study"); mysqlcpp::Connection db(config); ``` `Config` 负责保存连接参数: ```text host user password database port ``` ## Query 示例 `Query` 用于执行 `select`,会返回一个 `Result`。 ```cpp auto result = db.Query("select id, username, email, created_at from users"); while (auto row = result.Next()) { for (std::size_t i = 0; i < row->Size(); ++i) { std::print("{} ", row->GetString(i)); } std::println(); } ``` 关系: ```text Connection::Query -> mysql_query -> mysql_store_result -> Result -> Result::Next -> Row ``` 注意:`Result` 是游标式结果集,`Next()` 会不断向后读取。读完以后不能自动回到第一行,如果要看最新数据,需要重新 `Query()`。 ## Execute 示例 `Execute` 用于执行没有结果集的 SQL,比如: ```text insert update delete create table alter table ``` 示例: ```cpp db.Execute( "insert into users (username, email, created_at)" "values ('test', 'test@example.com', now())" ); ``` 关系: ```text Connection::Execute -> mysql_query -> 不调用 mysql_store_result ``` ## Transaction 示例 `Transaction` 用 RAII 管理事务。 ```cpp { mysqlcpp::Transaction tx(db); db.Execute("update accounts set balance = balance + 100 where username = 'alice'"); db.Execute("update accounts set balance = balance - 100 where username = 'bob'"); tx.Commit(); } ``` 行为: ```text 构造 Transaction -> begin Commit() -> commit Rollback() -> rollback 析构时如果没有 Commit / Rollback -> 自动 rollback ``` 设计原则: ```text 显式 Commit 自动 Rollback ``` `Commit()` 是业务确认动作,必须手动写出来。析构函数只负责异常路径下尽力回滚,不能自动提交。 ## Redis hiredis 示例 ```bash ./build/redis_ping ``` 用于演示 hiredis 最小连接: ```cpp redisContext* context = redisConnect("127.0.0.1", 6379); redisReply* reply = static_cast(redisCommand(context, "PING")); std::println("reply: {}", reply->str); freeReplyObject(reply); redisFree(context); ``` 预期输出: ```text reply: PONG ``` ## 示例程序说明 ### query_users ```bash ./build/query_users ``` 用于演示 `Query / Result / Row`。 该示例只负责演示 select 查询、Result 遍历和 Row 字段读取。 ### execute_users ```bash ./build/execute_users ``` 用于演示 `Execute`。 注意:该示例会向 `users` 表插入数据,重复运行会重复插入。 ### transaction_transfer ```bash ./build/transaction_transfer ``` 用于演示 `Transaction`。 注意:该示例会真实修改 `accounts` 表余额,重复运行会重复加减钱。 ### redis_ping ```bash ./build/redis_ping ``` 用于演示 C++ 通过 hiredis 连接 Redis 并执行 `PING`。 ## 错误处理 MySQL 库内部统一抛出: ```cpp mysqlcpp::DbError ``` 示例程序建议使用: ```cpp try { // database code } catch (const mysqlcpp::DbError& e) { std::println(std::cerr, "database error: {}", e.what()); return 1; } ``` Redis hiredis 示例暂时直接检查空指针和 `context->err`: ```cpp if (context == nullptr) { return 1; } if (context->err) { redisFree(context); return 1; } ``` ## 当前限制 `mysqlcpp v0.1` 仍然很轻量,目前还有这些限制: - 还没有 prepared statement,暂时需要自己拼 SQL - 还没有参数绑定,不能防 SQL 注入 - 还没有连接池 - 还没有 `query_all()`,不能自动映射成业务对象 - `Result` 是一次性游标,不能重复遍历 - 示例程序会真实修改数据库,运行前要确认数据状态 - 当前只优先支持 Linux / WSL,跨平台 CMake 后续再处理 Redis 当前只是最小 demo,后续才会封装 `rediscpp::Connection` 和 `rediscpp::Reply`。 ## 后续计划 MySQL 方向: ```text v0.2:prepared statement 和参数绑定 v0.3:query_one / query_all v0.4:Repository 示例 v0.5:连接池 v0.6:跨平台构建 v0.7:C++23 SQL Builder ``` Redis 方向: ```text C++ hiredis SET / GET 封装 rediscpp::Connection 封装 rediscpp::Reply 用 RAII 自动释放 redisContext / redisReply MySQL + Redis 缓存联动 ``` ## 学习目标 这个项目的重点不是“立刻造一个成熟 ORM 或 Redis 客户端”,而是通过亲手封装数据库 C API,理解: ```text RAII 异常安全 move-only 资源管理 数据库查询结果集 事务边界 Redis reply 生命周期 C++ 项目结构 ```