【sqlite】WAL初探

打开数据库后可以PRAGMA journal_mode;查看

事实上journal_mode一共有6种:

DELETE/TRUNCATE/PERSIST:类似的,都是journal模式,把原始内容先备份出来,再往.db里面写

.

MEMORY:小事务频繁写入提交很快,断电就会出问题

.

WAL:大事务批量写入比MEMORY快,读取速度极快,综合能力最好,使用最广

.

OFF:写入极快,安全性等于无

以上6种,在设置PRAGMA journal_mode=xxx;时,只有设置WAL会持久化,其它的都会在下一次打开db时变回DELETE。

.db头中也可以看到端倪,其实也就是0x12开始,WAL模式是0x0202,其它模式都是0x0101:

offset size description
18 1 File format write version. 1 for legacy; 2 for WAL.
19 1 File format read version. 1 for legacy; 2 for WAL.

OK。我们来研究一下WAL

看看deepseek的总结:

WAL (Write-Ahead Logging) - 大多数现代应用的推荐选择

.

读取速度: ★★★★★ (极快)

读操作不会与写操作竞争数据库文件的锁。读操作直接读主数据库文件,而写操作在WAL文件上进行。

支持高并发读取,一个线程在写入时,其他线程可以无阻塞地读取(读取器看到的是写入开始前的快照)。

.

写入速度: ★★★★☆ (很快)

写入是"追加"到WAL文件末尾,这通常比随机写入主数据库文件更快,尤其是在HDD上。

缺点是提交事务时,需要调用fsync确保数据落盘,并且需要定期执行检查点 将WAL内容写回主数据库。

.

适用场景:

需要高并发读写的应用(如Web服务器、桌面应用)。

读远多于写的场景。

追求最佳综合性能的通用场景。

db-wal/db-shm与db-journal的生命周期对比

db-wal/db-shm db-journal
open db 后 不存在 不存在
create table; 后 存在 不存在
insert; 后 存在 存在
commit; 后 存在 不存在
close db 后 不存在 不存在

可以看到db-wal/db-shm的生命周期比db-journal要长的。

代码如下:

cpp 复制代码
#include <stdio.h>
#include "sqlite3.h"

// 回调函数用于显示PRAGMA查询结果
static int callback(void* data, int argc, char** argv, char** azColName) {
    for (int i = 0; i < argc; i++) {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    return 0;
}

int main() {
    sqlite3* db;
    char* err_msg = NULL;
    int rc;

    // 删除之前的测试数据库(如果存在)
    remove("int.db");

    // 打开数据库连接
    rc = sqlite3_open("int.db", &db);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db));
        return 1;
    }
    printf("1. 数据库连接已建立\n");

    // 先查询当前的日志模式
    printf("2. 当前日志模式: ");
    rc = sqlite3_exec(db, "PRAGMA journal_mode;", callback, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "查询日志模式失败: %s\n", err_msg);
        sqlite3_free(err_msg);
        return 1;
    }

    // 启用WAL模式
    printf("3. 设置WAL模式: ");
    rc = sqlite3_exec(db, "PRAGMA journal_mode=WAL;", callback, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "启用WAL模式失败: %s\n", err_msg);
        sqlite3_free(err_msg);
        return 1;
    }

    // 创建测试表
    const char* create_table_sql =
        "CREATE TABLE test_ints ("
        "tiny INT,"
        "small INT, "
        "medium INT,"
        "large INT,"
        "negative INT"
        ")";

    rc = sqlite3_exec(db, create_table_sql, NULL, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "创建表失败: %s\n", err_msg);
        sqlite3_free(err_msg);
        return 1;
    }
    printf("4. 测试表已创建\n");

    // 开始一个事务(显式开始)
    rc = sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "开始事务失败: %s\n", err_msg);
        sqlite3_free(err_msg);
        return 1;
    }
    printf("5. 事务已开始\n");

    // 插入数据但不提交
    const char* insert_sql =
        "INSERT INTO test_ints VALUES (1, 128, 32768, 2147483647, -1);"
        "INSERT INTO test_ints VALUES (127, 255, 65535, 4294967295, -128);"
        "INSERT INTO test_ints VALUES (0, 16384, 1000000, 1000000000, -32768);";

    rc = sqlite3_exec(db, insert_sql, NULL, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "插入数据失败: %s\n", err_msg);
        sqlite3_free(err_msg);
        return 1;
    }
    printf("6. 数据已插入但未提交\n");

    // 提交事务
    rc = sqlite3_exec(db, "COMMIT;", NULL, NULL, &err_msg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "提交事务失败: %s\n", err_msg);
        sqlite3_free(err_msg);
    }
    else {
        printf("7. 事务已提交\n");
    }

    sqlite3_close(db);

    return 0;
}
相关推荐
国服第二切图仔4 小时前
鸿蒙应用开发之实现键值型数据库跨设备数据同步
数据库·wpf·harmonyos
盒马coding5 小时前
PostgreSQL18新功能COPY命令变得更加用户友好
数据库·postgresql
️️(^~^)5 小时前
触发器,存储过程
数据库
罗光记5 小时前
Quantinuum 发布新型量子计算机“Helios“
数据库·经验分享·其他·百度·twitter
友友马6 小时前
『 数据库 』MySQL索引深度解析:从数据结构到B+树的完整指南
数据库·mysql
SelectDB6 小时前
替换 ClickHouse,查询并发提升 7 倍!高途教育基于阿里云 SelectDB 构建秒级实时报表
数据库·apache
JamSlade6 小时前
优化用户体验的小点:乐观更新链路 双数据库查询
数据库·ux
一 乐6 小时前
个人博客|博客app|基于Springboot+微信小程序的个人博客app系统设计与实现(源码+数据库+文档)
java·前端·数据库·spring boot·后端·小程序·论文
小二·7 小时前
用 eBPF 实现 MySQL 慢查询实时追踪(终极实战版):零侵入、毫秒级、全上下文捕获
数据库·mysql·adb
云飞云共享云桌面7 小时前
三维设计办公资源如何共享集中和安全管控?
运维·服务器·数据库·安全·自动化·制造