SQLiteC/C++接口详细介绍之sqlite3类(十八)

返回目录:SQLite—免费开源数据库系列文章目录  

上一篇:SQLiteC/C++接口详细介绍之sqlite3类(十七)

下一篇:SQLiteC/C++接口详细介绍sqlite3_stmt类(一)

56.sqlite3_update_hook

函数功能:向应用程序通知每一个 INSERT、UPDATE 或 DELETE 语句。

当INSERT、UPDATE或DELETE语句执行时,SQLite3将检测表或触发器并执行任何相关的操作。最后,SQLite3将调用与sqlite3_update_hook关联的回调函数以通知应用程序。

sqlite3_update_hook函数原型如下:

void sqlite3_update_hook(sqlite3 *db,void (*callback)(void *, int, char const *, char const *, sqlite3_int64),void *arg
);

参数说明:

- db:一个由sqlite3_open或sqlite3_open_v2返回的数据库句柄。
- callback:一个指向回调函数的指针。此回调函数由SQLite3调用以通知应用程序每次执行了INSERT、UPDATE或DELETE语句。该回调函数的声明应该匹配如下:

  void (*callback)(void *, int, char const *, char const *, sqlite3_int64)

  回调函数的第一个参数为表达了被改变的各种值,是由用户提供的Void指针arg决定的 。
  第二个参数是SQL语句的类型,即SQLITE_INSERT、SQLITE_UPDATE或SQLITE_DELETE。
  第三个和第四个参数表明哪个数据库和表被修改了。
  第五个参数是被修改记录的行ID。

- arg:在调用回调函数时,作为其中一个参数把它传递回去的任意类的指针。

下面是一个示例程序,演示了如何使用sqlite3_update_hook函数:

#include <sqlite3.h>
#include <stdio.h>
static void update_callback(void *pArg,int iCmd,char const *zDb,char const *zTableName,sqlite3_int64 rowid
) {printf("UPDATE hook: %s %s id=%lld\n", zDb, zTableName, rowid);
}
int main() {sqlite3 *db;sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);sqlite3_exec(db, "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", NULL, NULL, NULL);sqlite3_update_hook(db, update_callback, NULL);sqlite3_exec(db, "INSERT INTO test (id, value) VALUES (1, 'hello')", NULL, NULL, NULL);sqlite3_exec(db, "UPDATE test SET value = 'world' WHERE id = 1", NULL, NULL, NULL);sqlite3_exec(db, "DELETE FROM test WHERE id = 1", NULL, NULL, NULL);sqlite3_close(db);return 0;
}

该示例中,我们创建了一个名为“test”的表,然后在sqlite3_update_hook中注册了一个回调函数。我们随后在表格中插入一行,更新这一行的记录,再将这一行的记录删除。在每一次执行修改操作时,SQLite3都会调用我们注册的回调函数,它将记录当前执行的操作并输出相关信息。

程序输出的结果为:

UPDATE hook: main test id=1
UPDATE hook: main test id=1
UPDATE hook: main test id=1
可以看到,程序成功使用sqlite3_update_hook函数注册了一个回调函数,然后在每一次执行修改操作时,都会输出钩子的相应信息。

57.sqlite3_wal_autocheckpoint

函数功能:自动调度WAL模式下的日志文件检查点。

在WAL模式下,混合使用事务和独立表锁,事务使用WAL日志文件,在 WAL 模式下,删除语句不再真正执行删除,而仅在 WAL 日志文件中形成删除记录。WAL记录将在另外的线程或进程读取和删除。当WAL日志文件变得非常大时,它将占用大量磁盘空间,这将影响性能。

SQLite3允许通过自动检查点机制来控制WAL日志文件的增长。当应用程序不再使用WAL日志文件时,可以让SQLite3自动检查点。在自动检查点机制的帮助下,SQLite3将创建一个新的数据库文件,将WAL日志文件中的相关内容复制到新的数据库文件中,并将WAL日志文件重命名为删除状态。由于复制数据到新文件和删除旧的WAL日志文件都是涉及磁盘I / O的操作,因此要小心进行自动检查点机制的配置。

sqlite3_wal_autocheckpoint函数用于设置WAL文件的自动检查点算法。它将一个整数值设置为一个逻辑步骤数。在WAL模式下,每当写日志文件达到nSize个逻辑步骤时,将自动运行检查点。

sqlite3_wal_autocheckpoint函数原型如下:

int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);

参数说明:

- db:由sqlite3_open或sqlite3_open_v2打开的数据库连接句柄。
- N:表示WAL日志文件中的逻辑步骤数。

返回值:设置和清除自动检查点提醒程序的SQLITE_OK,或一个错误代码。

下面是一个示例程序,演示了如何使用sqlite3_wal_autocheckpoint函数。该程序使用WAL模式编写“test”表中的几个条目,然后在自动检查点机制的帮助下设置检查点。在程序退出之前,它还回滚了最后一个此插入操作。注意,设置的逻辑步骤数只是一个量级,实际值取决于数据库的大小和预计的WAL日志文件大小。

#include <sqlite3.h>
#include <stdio.h>
int main() {sqlite3 *db;char *zErrMsg = 0;sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI, NULL);sqlite3_exec(db, "PRAGMA journal_mode=WAL;", NULL, NULL, NULL);sqlite3_exec(db, "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT);", NULL, NULL, &zErrMsg);char *sql_insert = "INSERT INTO test VALUES (null, 'Hello World!');";sqlite3_stmt *stmt;sqlite3_prepare_v2(db, sql_insert, -1, &stmt, NULL);for (int i = 0; i < 100; i++) {sqlite3_step(stmt);sqlite3_reset(stmt);if (i == 50) {sqlite3_wal_checkpoint_v2(db, NULL, SQLITE_CHECKPOINT_TRUNCATE, NULL, NULL);printf("Automatically set checkpoint\n");}}sqlite3_finalize(stmt);sqlite3_exec(db, "ROLLBACK TO savepoint1;", NULL, NULL, &zErrMsg);printf("Rolled back transaction\n");sqlite3_close(db);return 0;
}

以上程序会创建一个名为“test”的表,使用WAL模式编写数百个条目。然后,当编写WAL日志时,程序将设置一个自动检查点,该检查点会在30个事务步骤后运行。有趣的是,我们将会回滚最后一次插入操作。在自动检查点触发之前,程序将移动到"savepoint1"保存点。

程序输出的结果如下:

Automatically set checkpoint
Rolled back transaction
可以看到,在程序的自动检查点算法处顺利地运行。执行WAL日志会在某些时候具有显著的性能和稳定性优势。如果在许多并发连接到相同的数据库时,可以使用WAL日志来避免数据库连接争用的情况。

58.sqlite3_wal_checkpoint与sqlite3_wal_checkpoint_v2

函数功能:在WAL模式下手动调用日志文件检查点。这些函数在WAL模式时可以调用。调用这些函数不是必需的,因为SQLite3会定期自动运行检查点以降低WAL日志文件的大小。但是,如果您的应用程序将使用WAL模式长时间运行,建议使用这些函数。手动调用日志文件检查点可以确保日志文件保持足够小,从而提高应用程序的性能。

sqlite3_wal_checkpoint函数适用于SQLite3 version 3.7.4 至 3.7.14.2 和 3.8.0 至 3.8.1之间的版本。sqlite3_wal_checkpoint_v2函数是3.7.14.2版本之后的版本引入的。两个函数在功能上非常相似,都可以用于手动触发WAL检查点,但sqlite3_wal_checkpoint_v2中加入了一些新的标志供选择使用。

sqlite3_wal_checkpoint_v2函数原型如下:

int sqlite3_wal_checkpoint_v2(sqlite3 *db,const char *zDb,int eMode,int *pnLog,int *pnCkpt
);

参数说明:

- db:由sqlite3_open或sqlite3_open_v2函数打开的一个数据库连接实例。
- zDb:将连接到 WAL 文件的数据库名称。如果为NULL,则连接到所有数据库。如果不是NULL,则只连接到指定数据库的 WAL 文件。
- eMode:当此参数设置为 SQLITE_CHECKPOINT_PASSIVE 时,在 WAL 文件中找到所有活动的奇偶交错帧并将它们排序交错以便将单个帧作为 SQLite 数据库中的单个页面写入。否则,如果设置为 SQLITE_CHECKPOINT_RESTART 或 SQLITE_CHECKPOINT_TRUNCATE,则在 WAL 文件中找到所有活动的奇偶交错帧并将它们写入 SQLite 数据库中。如果它设置为 SQLITE_CHECKPOINT_FULL,则查找所有WAL文件,并找出其中活动的奇偶交错帧并将其写入SQLite数据库。
- pnLog:指向一个int的指针,如果不想接收WAL文件的大小,则传递NULL。
- pnCkpt:指向一个int的指针,如果不需要接收检查点的总页数,则传递NULL。

sqlite3_wal_checkpoint函数原型如下:

int sqlite3_wal_checkpoint(sqlite3 *db,const char *zDb
);

参数说明:

- db:由sqlite3_open或sqlite3_open_v2函数打开的一个数据库连接实例。
- zDb:将连接到 WAL 文件的数据库名称。如果为NULL,则连接到所有数据库。如果不是NULL,则只连接到指定数据库的 WAL 文件。

示例程序演示了如何使用sqlite3_wal_checkpoint_v2函数手动触发WAL检查点。

#include <sqlite3.h>
#include <stdio.h>
int main() {sqlite3 *db;char *err_msg = 0;sqlite3_open(":memory:", &db);sqlite3_exec(db, "PRAGMA journal_mode=WAL;", NULL, NULL, &err_msg);sqlite3_exec(db, "CREATE TABLE test (a, b, PRIMARY KEY(a, b));", NULL, NULL, &err_msg);sqlite3_exec(db, "BEGIN;", NULL, NULL, &err_msg);for (int i = 0; i < 10; i++) {char sql_insert[100];sprintf(sql_insert, "INSERT INTO test VALUES (%d, %d);", i, i);sqlite3_exec(db, sql_insert, NULL, NULL, &err_msg);}printf("WAL file size before: %d bytes\n", sqlite3_wal_checkpoint_v2(db, NULL, SQLITE_CHECKPOINT_FULL, NULL, NULL));sqlite3_exec(db, "COMMIT;", NULL, NULL, &err_msg);printf("WAL file size after: %d bytes\n", sqlite3_wal_checkpoint_v2(db, NULL, SQLITE_CHECKPOINT_FULL, NULL, NULL));sqlite3_close(db);return 0;
}

以上程序首先使用“PRAGMA journal_mode=WAL;”指令开启WAL模式,然后创建一个表“test”,并在其中添加一些数据。然后,通过sqlite3_wal_checkpoint_v2函数使用SQLITE_CHECKPOINT_FULL标志触发了一个手动检查点,并记录WAL日志文件的大小。最后提交事务并再次记录WAL日志文件大小。

程序输出的结果为:

WAL file size before: 12288 bytes
WAL file size after: 4096 bytes

可以看到,手动调用日志文件检查点已将WAL文件的大小从12288字节缩小到4096字节。这是一种有效节省空间的方法。

59.sqlite3_wal_hook

函数功能:可以在WAL模式下注册一个回调函数。当需要在WAL文件中写入数据时,该回调函数将被调用。

在WAL模式下,数据更改是在WAL文件中记录的。sqlite3_wal_hook回调函数允许应用程序检测正在写入到WAL日志文件的数据,可以自定义要写入到WAL日志文件的内容。这可以用于记录应用程序相关的元数据或其他一些额外的信息。

sqlite3_wal_hook函数原型如下:

void (*sqlite3_wal_hook)(sqlite3*, int(*)(void *,sqlite3*,const char*,int),void*
);

参数说明:

- db:一个打开的数据库连接。
- xCallback:一个回调函数,由SQLite3调用以在WAL文件中写入数据。
- pArg:回调函数的第3个参数是指向此指针的。它是对回调函数的额外自定义数据,当回调函数被调用时,它作为第3个参数(完全解释由回调函数协议确定的额外数据)的值传递给回调函数。

其中,xCallback参数为回调函数的指针。

回调函数原型如下:

int (*xCallback)(void *pArg, sqlite3 *db, const char *zWal, int n)

参数说明:

- pArg:由sqlite3_wal_hook函数传递的第3个参数。
- db:数据库连接句柄。
- zWal:指向写入的数据的指针。
- n:写入的数据的长度。

该回调函数可以返回零或一个非零值。如果它返回非零,则将导致WAL日志文件上的写入被撤消,不会写入磁盘。

以下示例程序演示了在WAL文件中注册回调函数sqlite3_wal_hook。

#include <sqlite3.h>
#include <string.h>
#include <stdio.h>
static int wal_write_callback(void *pArg, sqlite3 *db, const char *zWal, int n) {printf("WAL write callback: %s (size=%d)\n", zWal, n);// 将二进制数据解析为int类型并输出if (n == sizeof(int)) {int data = 0;memcpy(&data, zWal, sizeof(int));printf("Data: %d\n", data);}return 0;
}
int main() {sqlite3 *db;sqlite3_open(":memory:", &db);sqlite3_wal_hook(db, wal_write_callback, NULL);// 将数据写入WAL文件中int data = rand();printf("Write data to WAL file: %d\n", data);sqlite3_wal_hook(db, NULL, NULL);  // 禁用回调以避免死循环sqlite3_wal_write(db, &data, sizeof(int));sqlite3_wal_hook(db, wal_write_callback, NULL);sqlite3_close(db);return 0;
}

以上程序打开一个in-memory数据库,使用sqlite3_wal_hook函数注册回调函数“wal_write_callback”,然后随机生成一个整数并使用sqlite3_wal_write函数将该整数写入WAL文件中。使用memcpy函数将二进制数据解析为int类型并输出。

运行该程序,输出如下:

Write data to WAL file: 1710216883
WAL write callback: �4� (size=4)
Data: 1710216883
以上程序通过调用sqlite3_wal_hook函数为WAL文件注册回调函数“wal_write_callback”,该函数在数据写入到WAL文件时会被调用。该函数被调用时,输出写入WAL文件的数据。

注意:回调函数中执行的操作不应太耗时,否则可能会影响系统的性能。

至此sqlite3类的所有函数介绍完成了,本类是sqlite数据库的核心,也是最重要的函数后续将陆续介绍其他的类与成员函数相关内容。敬请期待《我很快会回来的》。

后记:

本系列文章工作量太大,本人水平严重不足文章中错漏再所难免,也希望看到错误的朋友给与及时指正(在此先行谢过)。赶稿时间很冲忙也很累,希望大佬们不要太叫真,本文献给与我相同碰到一些问题无处找解答的人,若能帮助到您一点点,吾心深感荣幸!愿我们的技术一起进步!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/279618.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue.js前端开发零基础教学(二)

目录 前言 2.1 单文件组件 2.2 数据绑定 2.2.2 响应式数据绑定 2.3 指令 2.3.1 内容渲染指令 2.3.2 属性绑定指令 ​编辑 2.3.3 事件绑定指令 2.3.4 双向数据绑定指令 2.3.5 条件渲染指令 2.3.6 列表渲染指令 2.4 事件对象 2.5 事件修饰符 学习目标&am…

【CKA模拟题】学会JSONPath,精准定位Pod信息!

题干 For this question, please set this context (In exam, diff cluster name) kubectl config use-context kubernetes-adminkubernetesyou have a script named pod-filter.sh . Update this script to include a command that filters and displays the label with the…

STM32-DMA数据转运

DMA进行转运的条件 1&#xff1a;开关控制&#xff0c;DMA_CMD必须使能2&#xff1a;传输计数器必须大于03&#xff1a;触发源必须有触发的信号

【c++】c++背景(c++的前世今生)

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;c_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1. 什么是C 2. C发展史 3. C的重要性 3.1 语言的使用广泛度 3.2在工作邻域 1. 操作系统以及大型系统软件开发 2. 服务器端开发 3. …

OSPF路由汇总

OSPF只要是环回接口&#xff08;默认P2P网络类型&#xff09;&#xff0c;默认都是32位的叶子信息。手动修改&#xff0c;[R1-LoopBack0]ospf network-type broadcast&#xff1b;修改网络类型。 OSPF不支持自动汇总&#xff0c;需要手动汇总。 一、OSPF路由汇总 使用CIDR技术…

java数据结构与算法刷题-----LeetCode135. 分发糖果

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 左右遍历2. 进阶&#xff1a;常数空间遍历&#xff0c;升序降…

【四 (6)数据可视化之 Grafana安装、页面介绍、图表配置】

目录 文章导航一、Grafana介绍[✨ 特性]二、安装和配置1、安装2、权限配置&#xff08;账户/团队/用户&#xff09;①用户管理②团队管理③账户管理④看板权限 3、首选项配置4、插件管理①数据源插件②图表插件③应用插件④插件安装方式一⑤安装方式二 三、数据源管理1、添加数…

内表-ABAP开发从入门到精通笔记

内表 概念 内表是在程序内部定义的表。是定义在内存中&#xff0c;所以运行速度会比磁盘中是实体表快很多。 内表的定义&#xff0c;可以通过type来定义&#xff0c;也可以通过变量来定义。 例如&#xff1a;先定义一个结构体&#xff0c;然后再通过结构体定义内表 先顶一个结…

合合信息扫描全能王亮相静安区3·15活动,AI扫描带来绿色消费新体验

保护消费者的合法权益&#xff0c;是全社会的共同责任。为优化消费环境、促进品质消费高地建设&#xff0c;打造安全优质和谐的消费环境&#xff0c;上海静安区消保委于3月15日举办静安区2024年“315”国际消费者权益日活动。 “激发消费活力&#xff0c;绿色低碳同行”是本次3…

蓝桥杯每日一题——棋盘

问题描述 小蓝拥有 n xn 大小的棋盘&#xff0c;一开始棋盘上全都是白子。小蓝进行了 m 次操作&#xff0c;每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色&#xff0c;黑色棋子变为白色)请输出所有操作做完后棋盘上每个棋子的颜色。输入格式 输入的…

智能合约语言(eDSL)—— 使用rust实现eDSL的原理

为理解rust变成eDSL的实现原理&#xff0c;我们需要简单了解元编程与宏的概念,元编程被描述成一种计算机程序可以将代码看待成数据的能力&#xff0c;使用元编程技术编写的程序能够像普通程序在运行时更新、替换变量那样操作更新、替换代码。宏在 Rust 语言中是一种功能&#x…

3.19作业

1、思维导图 2、模拟面试题 1&#xff09;TCP通信中的三次握手和四次挥手 答&#xff1a;三次握手 客户端向服务器发送连接请求 服务器向客户端回复应答并向客户端发送连接请求 客户端回复服务端&#xff0c;并建立联系 四次挥手 进程a向进程b发送断开连接请求…

Linux 磁盘的一生

注意&#xff1a;实验环境都是使用VMware模拟 ​ 磁盘接口类型这里vm中是SCSI&#xff0c;扩展sata,ide(有时间可以看看或者磁盘的历史) ​ 总结&#xff1a;磁盘从有到无—类似于建房子到可以住 ————————————————————————————————————…

【linux】环境变量(进程二)

这里写目录标题 命令行参数&#xff1a;环境变量&#xff1a; 命令行参数&#xff1a; 不谈命令行参数就谈环境变量就是耍流氓。 相信我们在C语言阶段都在main函数里见过参数。 例如int main(int argc, char* argv[]) 这是什么东西呢&#xff1f; 话不多说我们直接打印一下看…

OSPF特殊区域(stub\nssa)

stub区域——只有1类、2类、3类&#xff1b;完全stub区域——只有1类、2类 NSSA区域&#xff1a;本区域将自己引入的外部路由发布给其他区域&#xff0c;但不需要接收其他区域的路由 在NSSA区域的路由器上&#xff0c;引入外部路由时&#xff0c;不会转换成5类LSA&#xff0c…

物资管理系统建设方案

二、 项目概述 2.1 项目背景 2.2 现状分析 2.2.1 业务现状 2.2.2 系统现状 三、 总体需求 3.1 系统范围 3.2 系统功能 3.3 用户分析 3.4 假设与依赖关系 四、 功能需求 五、 非功能性需求 5.1 用户界面需求 5.2 软硬件环境需求 5.3 产品质量需求 5.4 接口需求 …

第二门课:改善深层神经网络<超参数调试、正则化及优化>-超参数调试、Batch正则化和程序框架

文章目录 1 调试处理2 为超参数选择合适的范围3 超参数调试的实践4 归一化网络的激活函数5 将Batch Norm拟合进神经网络6 Batch Norm为什么会奏效&#xff1f;7 测试时的Batch Norm8 SoftMax回归9 训练一个SoftMax分类器10 深度学习框架11 TensorFlow 1 调试处理 需要调试的参…

《计算机考研精炼1000题》为你考研之路保驾护航

创作背景 在这个充满挑战与竞争的时代&#xff0c;每一位考生在备战研究生考试的过程中&#xff0c;都希望通过更多符合考纲要求的练习题来提高自己的知识和技能。为了满足这一需求&#xff0c;我们精心策划和编辑了这本《计算机考研精炼1000题》。在考研政治和考研数学领域&a…

教务管理系统(java+mysql+jdbc+Druid+三层架构)

1、项目要求 1.1数据库表描述 设计一个教务管理系统&#xff0c;要求如下&#xff1a; 系统涉及的表有 account表&#xff08;账号表&#xff09; teacher表&#xff08;教师表&#xff09; student表&#xff08;学生表&#xff09; course表 (课程表) score表&#xff08;成…

杰发科技AC7801——读取Flash数据做CRC校验

查看Keil的编译结果发现总共6160个字节。计算结果如下&#xff0c; 代码如下 #include "ac780x_crc.h" #include "ac780x.h" #include "ac780x_debugout.h" #include "string.h" #include "ac780x_eflash.h"#define TestSi…