综合实战项目:四大数据库系统实战

说实话,做了这么多年嵌入式开发,我最大的体会就是——没有哪个数据库能包打天下。你想想看,一个学生管理系统用SQLite就够了,但电商订单你敢用SQLite?分分钟崩给你看。

今天这个综合实战项目,我把四个最常用的数据库都拉出来遛遛。每个系统我都亲手写过,踩过的坑也不少。咱们一个一个来。

项目一:学生管理系统(SQLite)

SQLite这东西,说白了就是个文件数据库。我最早接触它是在一个手持设备项目上,当时觉得「就这?」后来才发现,轻量级场景下它真香。

学生管理系统的核心就三件事:增删改查。咱们用C语言调用SQLite的API,几行代码就能搞定。

#include <sqlite3.h>

sqlite3 *db;
char *err_msg = 0;

// 打开数据库(没有就自动创建)
sqlite3_open("student.db", &db);

// 建表
const char *sql = 
    "CREATE TABLE IF NOT EXISTS students("
    "id INTEGER PRIMARY KEY AUTOINCREMENT,"
    "name TEXT NOT NULL,"
    "age INTEGER,"
    "score REAL);";

sqlite3_exec(db, sql, 0, 0, &err_msg);

// 插入数据
sql = "INSERT INTO students(name, age, score) VALUES('张三', 20, 88.5);";
sqlite3_exec(db, sql, 0, 0, &err_msg);

sqlite3_close(db);

个人经验:SQLite的并发写入是个坑。我曾经在一个多线程项目里同时写数据库,结果频繁报「database is locked」。后来加了个互斥锁才解决。记住:SQLite适合单线程或低并发场景。

项目二:电商订单系统(MySQL)

电商系统,那数据量可不是闹着玩的。MySQL配合C语言的MySQL Connector/C库,才能扛住高并发。

我记得有一次双十一,订单表瞬间涌入几十万条数据。如果不用连接池,光创建连接就能把服务器拖垮。

#include <mysql/mysql.h>

MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;

conn = mysql_init(NULL);
mysql_real_connect(conn, "localhost", "root", "password", "ecommerce", 0, NULL, 0);

// 创建订单表
mysql_query(conn, 
    "CREATE TABLE orders("
    "order_id BIGINT PRIMARY KEY,"
    "user_id INT,"
    "amount DECIMAL(10,2),"
    "status TINYINT,"
    "create_time DATETIME"
    ") ENGINE=InnoDB;");

// 批量插入(用事务提高性能)
mysql_query(conn, "START TRANSACTION;");
for(int i = 0; i < 1000; i++) {
    char sql[256];
    sprintf(sql, "INSERT INTO orders VALUES(%ld, %d, %.2f, 1, NOW());", 
            order_id, user_id, amount);
    mysql_query(conn, sql);
}
mysql_query(conn, "COMMIT;");

mysql_close(conn);

避坑指南:我曾经在MySQL中直接用单条INSERT插入上万条数据,结果花了十几秒。后来改成批量插入+事务,速度提升了上百倍。另外,记得给order_id加索引,不然查询慢到你怀疑人生。

项目三:实时排行榜(Redis)

Redis做排行榜,那简直是天生一对。它的有序集合(Sorted Set)就是为这个场景设计的。

我做过一个游戏排行榜,玩家分数实时更新。如果用MySQL,每次排序都要全表扫描,延迟高得离谱。换成Redis,毫秒级响应。

#include <hiredis/hiredis.h>

redisContext *c = redisConnect("127.0.0.1", 6379);

// 玩家得分更新
redisCommand(c, "ZADD leaderboard 1000 player_001");
redisCommand(c, "ZADD leaderboard 1500 player_002");
redisCommand(c, "ZADD leaderboard 800 player_003");

// 获取前十名
redisReply *reply = redisCommand(c, "ZREVRANGE leaderboard 0 9 WITHSCORES");
if(reply->type == REDIS_REPLY_ARRAY) {
    for(int i = 0; i < reply->elements; i += 2) {
        printf("玩家: %s, 分数: %s\n", 
               reply->element[i]->str,
               reply->element[i+1]->str);
    }
}

freeReplyObject(reply);
redisFree(c);

小技巧:Redis的数据结构要选对。排行榜用ZSET,缓存用STRING,消息队列用LIST。我见过有人用STRING存排行榜数据,每次更新都全量替换,那效率...嗯,你懂的。

项目四:日志分析系统(MongoDB)

MongoDB处理日志,优势在于它的文档模型。日志本身就是半结构化数据,用关系型数据库反而别扭。

我之前做一个运维平台,每天几百万条日志。用MongoDB的聚合管道,几秒钟就能统计出错误分布。

#include <mongoc/mongoc.h>

mongoc_client_t *client;
mongoc_collection_t *collection;
bson_t *doc;

client = mongoc_client_new("mongodb://localhost:27017");
collection = mongoc_client_get_collection(client, "logs", "system_logs");

// 插入日志
doc = BCON_NEW(
    "timestamp", BCON_DATE_TIME(time(NULL)),
    "level", BCON_UTF8("ERROR"),
    "module", BCON_UTF8("auth"),
    "message", BCON_UTF8("用户登录失败"),
    "ip", BCON_UTF8("192.168.1.100")
);
mongoc_collection_insert_one(collection, doc, NULL, NULL, NULL);
bson_destroy(doc);

// 聚合查询:统计各模块错误数
bson_t *pipeline = BCON_NEW(
    "pipeline", "[",
        "{", "$match", "{", "level", BCON_UTF8("ERROR"), "}", "}",
        "{", "$group", "{", 
            "_id", "$module", 
            "count", "{", "$sum", BCON_INT32(1), "}", 
        "}", "}",
        "{", "$sort", "{", "count", BCON_INT32(-1), "}", "}",
    "]"
);

mongoc_cursor_t *cursor = mongoc_collection_aggregate(
    collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);

mongoc_cursor_destroy(cursor);
mongoc_collection_destroy(collection);
mongoc_client_destroy(client);

核心要点:MongoDB的索引设计很关键。日志查询通常按时间范围,所以给timestamp建索引是必须的。另外,日志数据量大,建议用分片集群,不然单机存不下。

四大数据库对比总结

数据库 适用场景 数据模型 并发能力 我的推荐
SQLite 嵌入式、单机、小数据量 关系型 低 学生管理、配置存储
MySQL Web应用、电商、高并发 关系型 高 订单系统、用户中心
Redis 缓存、排行榜、实时数据 键值对 极高 排行榜、会话管理
MongoDB 日志、物联网、大数据 文档型 高 日志分析、监控系统
四大数据库系统架构图 C语言数据库编程 SQLite 学生管理系统 MySQL 电商订单系统 Redis 实时排行榜 MongoDB 日志分析系统 特性 • 零配置 • 单文件存储 • 嵌入式运行 • 低资源占用 特性 • 高并发支持 • 事务ACID • 主从复制 • 存储过程 特性 • 内存存储 • 丰富数据结构 • 发布订阅 • 持久化可选 特性 • 文档模型 • 水平扩展 • 聚合管道 • 地理空间索引

这四个项目做完,基本上C语言操作主流数据库的套路你就都掌握了。说实话,数据库编程的核心就两点:连接管理和SQL(或命令)执行。剩下的就是针对不同数据库的特性做优化。

我建议你从SQLite开始练手,它最简单。然后挑战MySQL,感受一下高并发下的连接池设计。Redis和MongoDB可以并行学习,它们的数据模型和传统关系型完全不同,能打开你的思路。

最后说一句:数据库选型没有银弹。别听网上说「Redis快就全用Redis」,也别觉得「MongoDB时髦就抛弃MySQL」。合适的才是最好的。我见过太多项目因为选错数据库,后期重构成本高得吓人。

公众号:蓝海资料掘金营,微信deep3321