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

说实话,做了这么多年嵌入式开发,我最大的体会就是——没有哪个数据库能包打天下。你想想看,一个学生管理系统用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