sqlite内存数据库和文件数据库的同步[转]
由于sqlite对多进程操作支持效果不太理想,在项目中,为了避免频繁读写 文件数据库带来的性能损耗,我们可以采用操作sqlite内存数据库,并将内存数据库定时同步到文件数据库中的方法。
实现思路如下:
1、创建文件数据库;
2、创建内存数据库(文件数据库、内存数据库的内幕表结构需要一致);
3、在内存数据库中attach文件数据库,这样可以保证文件数据库中的内容在内存数据库中可见;
4、对于insert、select操作,在内存数据库中完成,对于delete、update操作,需要同时访问内存、文件数据库;
5、定时将内存数据库中的内容flush到文件数据库。
通过sqlite的cAPI实现代码如下:
- const char* file_database_path = "/home/tom/test/database/filedb"; //文件数据库存放路径
- const char* sql_create_data = "CREATE TABLE testinfo (id TEXT PRIMARY KEY, message TEXT, offset INTEGER, timestamp INTEGER);";
- const char* sql_insert_data = "INSERT OR REPLACE INTO MAIN.testinfo VALUES('%s', '%s', %d, %d);";
- const char* sql_delete_data = "DELETE FROM MAIN.testinfo WHERE id = '%s'; DELETE FROM filedb.testinfo WHERE id = '%s';"; //删除数据库,需同时删除内存、文件数据库中的内容
- const char* sql_update_data = "UPDATE MAIN.testinfo SET message = '%s', offset = %d, timestamp = %d where id = '%s'; UPDATE filedb.testinfo SET message = '%s', offset = %d, timestamp = %d where id = '%s';";//更新数据库,需同时更新内存、文件数据库中的内容
- const char* sql_search_data = "SELECT * FROM MAIN.testinfo WHERE timestamp BETWEEN %d AND %d union SELECT * FROM testdb.testinfo WHERE timestamp BETWEEN %d AND %d;"; //查找数据库,将内存、文件数据库中查找出的内容合并
- const char* sql_transfer_data = "INSERT OR REPLACE INTO filedb.testinfo SELECT * FROM testinfo;"; //将内存数据库中的信息同步到文件数据库中
- const char* sql_delete_memory_table = "DELETE FROM testinfo;"; //内存数据库中的内容同步结束后,清空
- int InsertRecord(DATA_TYPE type, const char* id, const char* message, int offset, int timestamp)
- {
- int rc = 0;
- char* errMsg = NULL;
- char sqlcmd[512] = {0};
- time_t insertTimestamp = 0;
- snprintf(sqlcmd, sizeof(sqlcmd), sql_insert_data, id, message, offset, timestamp);
- rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't add record to memory database %s, sqlcmd=%s, err:%s\n", map_data_table[type].data_table_name, sqlcmd, errMsg);
- return -1;
- }
- return 0;
- }
- int UpdateRecord(DATA_TYPE type, const char* id, const char* message, int offset, int timestamp)
- {
- int rc = 0;
- char* errMsg = NULL;
- char sqlCmd[512] = {0};
- snprintf(sqlCmd, sizeof(sqlCmd), sql_update_data, message, offset, timestamp, id, message, offset, timestamp, id);
- rc = sqlite3_exec(memdb, sqlCmd, NULL, NULL, &errMsg);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't update record %s:%s\n", map_data_table[type].data_table_name, errMsg);
- return -1;
- }
- return 0;
- }
- int DeleteRecord(DATA_TYPE type, const char* id)
- {
- int rc = 0;
- char* errMsg = NULL;
- char sqlcmd[512] = {0};
- snprintf(sqlcmd, sizeof(sqlcmd), sql_delete_data, id, id);
- rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't delete record %s:%s\n", map_data_table[type].data_table_name, errMsg);
- return -1;
- }
- return 0;
- }
- int QueryMessage(DATA_TYPE type, int startTime, int endTime)
- {
- int rc = 0;
- char *errMsg = NULL;
- sqlite3 *filedb = NULL;
- char** pRecord = NULL;
- int row = 0;
- int column = 0;
- char sqlcmd[512] = {0};
- if (type > VEP_NELEMS(map_data_table) || type < 0) {
- return -1;
- }
- rc = sqlite3_open(file_database_path, &filedb);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't open database:%s\n", sqlite3_errmsg(filedb));
- sqlite3_close(filedb);
- return -1;
- }
- snprintf(sqlcmd, sizeof(sqlcmd), sql_search_data, startTime, endTime, startTime, endTime);
- rc = sqlite3_get_table(filedb, sqlcmd, &pRecord, &row, &column, &errMsg);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't get table from%s:%s\n", map_data_table[type].data_table_name, errMsg);
- return -1;
- }
- int i;
- printf("row = %d, column = %d\n", row, column);
- for(i = 0; i < 2*column; i++)
- {
- printf("%s ", pRecord[i]);
- }
- printf("\n");
- return 0;
- }
- //定时调用此函数将内存数据中的内容同步到文件数据库
- int Flush(){
- int i = 0;
- int rc = 0;
- char* errMsg = NULL;
- char sqlcmd[512] = {0};
- snprintf(sqlcmd, sizeof(sqlcmd), sql_transfer_data);
- rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't transfer memory database %s to file databasede:%s\n", map_data_table[i].data_table_name, sqlite3_errmsg(memdb));
- sqlite3_close(memdb);
- return -1;
- }
- snprintf(sqlcmd, sizeof(sqlcmd), sql_delete_memory_table);
- rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
- return 0;
- }
- //创建文件数据库
- int CreateDbOnFile()
- {
- sqlite3 *db = NULL;
- int rc = 0;
- char* errMsg = NULL;
- char sqlcmd[512] = {0};
- int i = 0;
- rc = sqlite3_open(file_database_path, &db);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't open database:%s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- return -1;
- }
- snprintf(sqlcmd, sizeof(sqlcmd), sql_create_data);
- rc = sqlite3_exec(db, sqlcmd, NULL, NULL, &errMsg);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't create file database testinfo:%s\n", errMsg);
- sqlite3_close(db);
- return -1;
- }
- sqlite3_close(db);
- return 0;
- }
- //创建内存数据库
- int CreateDbOnMemery()
- {
- int rc = 0;
- char* errMsg = NULL;
- char sqlcmd[512] = {0};
- int i = 0;
- rc = sqlite3_open(":memory:", &memdb);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't open database:%s\n", sqlite3_errmsg(memdb));
- sqlite3_close(memdb);
- return -1;
- }
- snprintf(sqlcmd, sizeof(sqlcmd), sql_create_data);
- rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't create memory database %s\n", errMsg);
- sqlite3_close(memdb);
- return -1;
- }
- return 0;
- }
- //解绑数据库
- int DetachDb()
- {
- int rc = 0;
- char* errMsg = NULL;
- char sqlcmd[512] = {0};
- snprintf(sqlcmd, sizeof(sqlcmd), "DETACH '%s'", "filedb");
- rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "detach file database failed:%s:%s\n", file_database_path, errMsg);
- sqlite3_close(memdb);
- return -1;
- }
- return 0;
- }
- //将文件数据库作为内存数据库的附加数据库
- int AttachDb()
- {
- int rc = 0;
- char* errMsg = NULL;
- char sqlcmd[512] = {0};
- snprintf(sqlcmd, sizeof(sqlcmd), "ATTACH '%s' AS %s", file_database_path, "filedb");
- rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
- if (SQLITE_OK != rc) {
- fprintf(stderr, "cat't attach database %s:%s\n", file_database_path, errMsg);
- sqlite3_close(memdb);
- return -1;
- }
- return 0;
- }
- //初始化数据库,分别创建文件数据库、内存数据库并把文件数据库attach到内存数据库上
- int InitSqliteDb()
- {
- int retval = 0;
- retval = CreateDbOnFile();
- if (retval != 0) {
- return retval;
- }
- retval = CreateDbOnMemery();
- if (retval != 0) {
- return retval;
- }
- retval = AttachDb();
- if (retval != 0) {
- return retval;
- }
- return 0;
- }
sqlite内存数据库和文件数据库的同步[转]的更多相关文章
- FIREDAC操作SQLITE内存数据库
SQLite不仅可以把数据库放在硬盘上,还可以放在内存中,经测试,同样条件下数据库放在内存中比放在硬盘上插入记录速度快差不多3倍. 但数据库放在内存中时有如下缺陷: 1.断电或程序崩溃后数据库就会消失 ...
- DBImport v3.5 中文版发布:数据库定时同步及文档生成工具(IT人员必备)
前言: 趁着最近的休息时间,只能多勤快些:多写代码,多更新文章. 因为一旦投入新的工作,估计博客又会恢复到一年才产几篇的状态. 对于DBImport,因为用户的意见,增加了一个亮点功能,让软件B格升为 ...
- SymmetricDS 数据库双向同步开源软件入门
一句话概括该软件:SymmetricDS是一个文件和数据库同步软件,开源的,支持多主复制,同步时过滤和在异构的网络环境中进行数据转换传输.它支持单向和双向上的多个订阅者,异步的数据复制. 以下是从CS ...
- SQLite内存数据库
[转]SQLite内存数据库 http://www.cnblogs.com/liuyong/archive/2010/09/14/1826152.html SQLite 介绍 一. SQLite 是实 ...
- 【原创】System.Data.SQLite内存数据库模式
对于很多嵌入式数据库来说都有对于的内存数据库模式,SQLite也不例外.内存数据库常常用于极速.实时的场景,一个很好的应用的场景是富客户端的缓存数据,一般富客户端的缓存常常需要分为落地和非落地两种,而 ...
- mysql数据库主从同步
环境: Mater: CentOS7.1 5.5.52-MariaDB 192.168.108.133 Slave: CentOS7.1 5.5.52-MariaDB 192.168. ...
- .NET平台开源项目速览(3)小巧轻量级NoSQL文件数据库LiteDB
今天给大家介绍一个不错的小巧轻量级的NoSQL文件数据库LiteDB.本博客在2013年也介绍过2款.NET平台的开源数据库: 1.[原创]开源.NET下的XML数据库介绍及入门 2.[原创]C#开源 ...
- mysql主从数据库不同步的2种解决方法(转)
今天发现Mysql的主从数据库没有同步 先上Master库: mysql>show processlist; 查看下进程是否Sleep太多.发现很正常. show master status; ...
- Mysql的主从数据库没有同步的解决办法
Mysql的主从数据库没有同步的解决办法 今天发现Mysql的主从数据库没有同步 先上Master库: mysql>show processlist; 查看下进程是否Sleep太多.发现很正常. ...
随机推荐
- jQuery三——筛选方法、事件
一.jquery常用筛选方法 以下为jquery的常用筛选方法: 代码示例如下: <!DOCTYPE html> <html lang="en"> < ...
- Java NIO(六) Selector
Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管理多个网络连接. 下面是 ...
- DrawerLayout侧滑
DrawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说DrawerLayout是因为第三方控件如SlidingMenu等出现之后,google借鉴而出现的产物.D ...
- EPS 转 pdf 在线
EPS 转 pdf 在线网站 https://convertio.co/zh/eps-pdf/
- SQL Server现有表上自增属性增删原理研究
项目需求:线上有一张表,数据类型为int类型,现在由于项目变更,需要这一列添加自增属性,而且,为了保证能尽快完成,希望使用脚本来实现,而不是在表设计中通过GUI窗口来实现. 问题来了:SQL Serv ...
- Perl Unicode全攻略
Perl Unicode全攻略 耐心看完本文,相信你今后在unicode处理上不会再有什么问题. 本文内容适用于perl 5.8及其以上版本. perl internal form 在Perl看来, ...
- HDU-3092 Least common multiple---数论+分组背包
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3092 题目大意: 有一个数字n,现在要把它分解成几个数字相加!然后这几个数字有最小公倍数,题目目的是 ...
- Android进阶笔记10:ListView篇之ListView显示多种类型的条目(item)
ListView可以显示多种类型的条目布局,这里写显示两种布局的情况,其他类似. 1. 这是MainActivity,MainActivity的布局就是一个ListView,太简单了这里就不写了,直接 ...
- Python:运算与循环
1.格式化输出 name = input("请输入你的名字:") age =input("请输入你的年龄:") job =input("请输入你的工作 ...
- 【LOJ2461】「2018 集训队互测 Day 1」完美的队列(分块+双指针)
点此看题面 大致题意: 让你维护\(n\)个有限定长度的队列,每次区间往队列里加数,求每次加完后的队列里剩余元素种类数. 核心思路 这道题可以用分块+双指针去搞. 考虑求出每个操作插入的元素在队列中被 ...