由于sqlite对多进程操作支持效果不太理想,在项目中,为了避免频繁读写 文件数据库带来的性能损耗,我们可以采用操作sqlite内存数据库,并将内存数据库定时同步到文件数据库中的方法。

实现思路如下:

1、创建文件数据库;

2、创建内存数据库(文件数据库、内存数据库的内幕表结构需要一致);

3、在内存数据库中attach文件数据库,这样可以保证文件数据库中的内容在内存数据库中可见;

4、对于insert、select操作,在内存数据库中完成,对于delete、update操作,需要同时访问内存、文件数据库;

5、定时将内存数据库中的内容flush到文件数据库。

通过sqlite的cAPI实现代码如下:

  1. const char* file_database_path = "/home/tom/test/database/filedb"; //文件数据库存放路径
  2. const char* sql_create_data = "CREATE TABLE testinfo (id TEXT PRIMARY KEY, message TEXT, offset INTEGER, timestamp INTEGER);";
  3. const char* sql_insert_data = "INSERT OR REPLACE INTO MAIN.testinfo VALUES('%s', '%s', %d, %d);";
  4. const char* sql_delete_data = "DELETE FROM MAIN.testinfo WHERE id = '%s'; DELETE FROM filedb.testinfo WHERE id = '%s';"; //删除数据库,需同时删除内存、文件数据库中的内容
  5. 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';";//更新数据库,需同时更新内存、文件数据库中的内容
  6. 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;"; //查找数据库,将内存、文件数据库中查找出的内容合并
  7. const char* sql_transfer_data = "INSERT OR REPLACE INTO filedb.testinfo SELECT * FROM testinfo;";   //将内存数据库中的信息同步到文件数据库中
  8. const char* sql_delete_memory_table = "DELETE FROM testinfo;";  //内存数据库中的内容同步结束后,清空
  9. int InsertRecord(DATA_TYPE type, const char* id, const char* message, int offset, int timestamp)
  10. {
  11. int      rc              =  0;
  12. char*    errMsg          =  NULL;
  13. char     sqlcmd[512]     =  {0};
  14. time_t   insertTimestamp =  0;
  15. snprintf(sqlcmd, sizeof(sqlcmd), sql_insert_data, id, message, offset, timestamp);
  16. rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
  17. if (SQLITE_OK != rc) {
  18. fprintf(stderr, "cat't add record to memory database %s, sqlcmd=%s, err:%s\n", map_data_table[type].data_table_name, sqlcmd, errMsg);
  19. return -1;
  20. }
  21. return 0;
  22. }
  23. int UpdateRecord(DATA_TYPE type, const char* id, const char* message, int offset, int timestamp)
  24. {
  25. int      rc              = 0;
  26. char*    errMsg          = NULL;
  27. char     sqlCmd[512]  = {0};
  28. snprintf(sqlCmd, sizeof(sqlCmd), sql_update_data, message, offset, timestamp, id, message, offset, timestamp, id);
  29. rc = sqlite3_exec(memdb, sqlCmd, NULL, NULL, &errMsg);
  30. if (SQLITE_OK != rc) {
  31. fprintf(stderr, "cat't update record %s:%s\n", map_data_table[type].data_table_name, errMsg);
  32. return -1;
  33. }
  34. return 0;
  35. }
  36. int DeleteRecord(DATA_TYPE type, const char* id)
  37. {
  38. int      rc              =  0;
  39. char*    errMsg          =  NULL;
  40. char     sqlcmd[512]     =  {0};
  41. snprintf(sqlcmd, sizeof(sqlcmd), sql_delete_data, id,  id);
  42. rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
  43. if (SQLITE_OK != rc) {
  44. fprintf(stderr, "cat't delete record %s:%s\n", map_data_table[type].data_table_name, errMsg);
  45. return -1;
  46. }
  47. return 0;
  48. }
  49. int QueryMessage(DATA_TYPE type, int startTime, int endTime)
  50. {
  51. int      rc              = 0;
  52. char     *errMsg         = NULL;
  53. sqlite3  *filedb         = NULL;
  54. char**   pRecord         = NULL;
  55. int      row             = 0;
  56. int      column          = 0;
  57. char     sqlcmd[512]     = {0};
  58. if (type > VEP_NELEMS(map_data_table) || type < 0) {
  59. return -1;
  60. }
  61. rc = sqlite3_open(file_database_path, &filedb);
  62. if (SQLITE_OK != rc) {
  63. fprintf(stderr, "cat't open database:%s\n", sqlite3_errmsg(filedb));
  64. sqlite3_close(filedb);
  65. return -1;
  66. }
  67. snprintf(sqlcmd, sizeof(sqlcmd), sql_search_data,  startTime, endTime,  startTime, endTime);
  68. rc = sqlite3_get_table(filedb, sqlcmd, &pRecord, &row, &column, &errMsg);
  69. if (SQLITE_OK != rc) {
  70. fprintf(stderr, "cat't get table from%s:%s\n", map_data_table[type].data_table_name, errMsg);
  71. return -1;
  72. }
  73. int i;
  74. printf("row = %d, column = %d\n", row, column);
  75. for(i = 0; i < 2*column; i++)
  76. {
  77. printf("%s ", pRecord[i]);
  78. }
  79. printf("\n");
  80. return 0;
  81. }
  82. //定时调用此函数将内存数据中的内容同步到文件数据库
  83. int Flush(){
  84. int      i            = 0;
  85. int      rc           = 0;
  86. char*    errMsg       = NULL;
  87. char     sqlcmd[512]  = {0};
  88. snprintf(sqlcmd, sizeof(sqlcmd), sql_transfer_data);
  89. rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
  90. if (SQLITE_OK != rc) {
  91. fprintf(stderr, "cat't transfer memory database %s to file databasede:%s\n", map_data_table[i].data_table_name, sqlite3_errmsg(memdb));
  92. sqlite3_close(memdb);
  93. return -1;
  94. }
  95. snprintf(sqlcmd, sizeof(sqlcmd), sql_delete_memory_table);
  96. rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
  97. return 0;
  98. }
  99. //创建文件数据库
  100. int CreateDbOnFile()
  101. {
  102. sqlite3 *db           = NULL;
  103. int      rc           = 0;
  104. char*    errMsg       = NULL;
  105. char     sqlcmd[512]  = {0};
  106. int      i            = 0;
  107. rc = sqlite3_open(file_database_path, &db);
  108. if (SQLITE_OK != rc) {
  109. fprintf(stderr, "cat't open database:%s\n", sqlite3_errmsg(db));
  110. sqlite3_close(db);
  111. return -1;
  112. }
  113. snprintf(sqlcmd, sizeof(sqlcmd), sql_create_data);
  114. rc = sqlite3_exec(db, sqlcmd, NULL, NULL, &errMsg);
  115. if (SQLITE_OK != rc) {
  116. fprintf(stderr, "cat't create file database testinfo:%s\n", errMsg);
  117. sqlite3_close(db);
  118. return -1;
  119. }
  120. sqlite3_close(db);
  121. return 0;
  122. }
  123. //创建内存数据库
  124. int CreateDbOnMemery()
  125. {
  126. int      rc           = 0;
  127. char*    errMsg       = NULL;
  128. char     sqlcmd[512]  = {0};
  129. int      i            = 0;
  130. rc = sqlite3_open(":memory:", &memdb);
  131. if (SQLITE_OK != rc) {
  132. fprintf(stderr, "cat't open database:%s\n", sqlite3_errmsg(memdb));
  133. sqlite3_close(memdb);
  134. return -1;
  135. }
  136. snprintf(sqlcmd, sizeof(sqlcmd), sql_create_data);
  137. rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
  138. if (SQLITE_OK != rc) {
  139. fprintf(stderr, "cat't create memory database %s\n", errMsg);
  140. sqlite3_close(memdb);
  141. return -1;
  142. }
  143. return 0;
  144. }
  145. //解绑数据库
  146. int DetachDb()
  147. {
  148. int      rc           =  0;
  149. char*    errMsg       =  NULL;
  150. char     sqlcmd[512]  =  {0};
  151. snprintf(sqlcmd, sizeof(sqlcmd), "DETACH '%s'", "filedb");
  152. rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
  153. if (SQLITE_OK != rc) {
  154. fprintf(stderr, "detach file database failed:%s:%s\n", file_database_path, errMsg);
  155. sqlite3_close(memdb);
  156. return -1;
  157. }
  158. return 0;
  159. }
  160. //将文件数据库作为内存数据库的附加数据库
  161. int AttachDb()
  162. {
  163. int      rc           =  0;
  164. char*    errMsg       =  NULL;
  165. char     sqlcmd[512]  =  {0};
  166. snprintf(sqlcmd, sizeof(sqlcmd), "ATTACH '%s' AS %s", file_database_path, "filedb");
  167. rc = sqlite3_exec(memdb, sqlcmd, NULL, NULL, &errMsg);
  168. if (SQLITE_OK != rc) {
  169. fprintf(stderr, "cat't attach database %s:%s\n", file_database_path, errMsg);
  170. sqlite3_close(memdb);
  171. return -1;
  172. }
  173. return 0;
  174. }
  175. //初始化数据库,分别创建文件数据库、内存数据库并把文件数据库attach到内存数据库上
  176. int InitSqliteDb()
  177. {
  178. int retval = 0;
  179. retval =  CreateDbOnFile();
  180. if (retval != 0) {
  181. return retval;
  182. }
  183. retval =  CreateDbOnMemery();
  184. if (retval != 0) {
  185. return retval;
  186. }
  187. retval =  AttachDb();
  188. if (retval != 0) {
  189. return retval;
  190. }
  191. return 0;
  192. }

sqlite内存数据库和文件数据库的同步[转]的更多相关文章

  1. FIREDAC操作SQLITE内存数据库

    SQLite不仅可以把数据库放在硬盘上,还可以放在内存中,经测试,同样条件下数据库放在内存中比放在硬盘上插入记录速度快差不多3倍. 但数据库放在内存中时有如下缺陷: 1.断电或程序崩溃后数据库就会消失 ...

  2. DBImport v3.5 中文版发布:数据库定时同步及文档生成工具(IT人员必备)

    前言: 趁着最近的休息时间,只能多勤快些:多写代码,多更新文章. 因为一旦投入新的工作,估计博客又会恢复到一年才产几篇的状态. 对于DBImport,因为用户的意见,增加了一个亮点功能,让软件B格升为 ...

  3. SymmetricDS 数据库双向同步开源软件入门

    一句话概括该软件:SymmetricDS是一个文件和数据库同步软件,开源的,支持多主复制,同步时过滤和在异构的网络环境中进行数据转换传输.它支持单向和双向上的多个订阅者,异步的数据复制. 以下是从CS ...

  4. SQLite内存数据库

    [转]SQLite内存数据库 http://www.cnblogs.com/liuyong/archive/2010/09/14/1826152.html SQLite 介绍 一. SQLite 是实 ...

  5. 【原创】System.Data.SQLite内存数据库模式

    对于很多嵌入式数据库来说都有对于的内存数据库模式,SQLite也不例外.内存数据库常常用于极速.实时的场景,一个很好的应用的场景是富客户端的缓存数据,一般富客户端的缓存常常需要分为落地和非落地两种,而 ...

  6. mysql数据库主从同步

    环境: Mater:   CentOS7.1  5.5.52-MariaDB  192.168.108.133 Slave:   CentOS7.1  5.5.52-MariaDB  192.168. ...

  7. .NET平台开源项目速览(3)小巧轻量级NoSQL文件数据库LiteDB

    今天给大家介绍一个不错的小巧轻量级的NoSQL文件数据库LiteDB.本博客在2013年也介绍过2款.NET平台的开源数据库: 1.[原创]开源.NET下的XML数据库介绍及入门 2.[原创]C#开源 ...

  8. mysql主从数据库不同步的2种解决方法(转)

    今天发现Mysql的主从数据库没有同步 先上Master库: mysql>show processlist; 查看下进程是否Sleep太多.发现很正常. show master status; ...

  9. Mysql的主从数据库没有同步的解决办法

    Mysql的主从数据库没有同步的解决办法 今天发现Mysql的主从数据库没有同步 先上Master库: mysql>show processlist; 查看下进程是否Sleep太多.发现很正常. ...

随机推荐

  1. scss-变量作用域

    SCSS之所以便利,是因为它具有了编程语言的某些特性. 让原本规则刻板的CSS变的灵活起来,下面介绍一下SCSS中的作用域概念. 几乎所有编程语言都有作用域概念的涉及,原理大同小异,SCSS中的也是如 ...

  2. 为 Drupal 7 构建一个新主题

    主题解释了 Drupal 网站的用户界面 (UI).虽然主题结构并没有明显的变化,但 Drupal 版本 7 配备了一个新的主题实现方法.本文演示了如何创建一个新的 Drupal 7 主题. Drup ...

  3. mac的svn

    http://xclient.info/s/cornerstone.html?t=c5242a66e53f1d866afe8c42aace2738c04ce9ee#versions 破解版的地址 打开 ...

  4. Hyperledger Fabric SDK use case 1

    ///////////////////////////////////////////////////////////////////////:End2endAndBackAgainIT 1.Crea ...

  5. 利用actionscript访问wfs服务

    以后整理……</> private function search_clickHandler():void{ op="search"; var urlLoader:UR ...

  6. linux下的动态链接库管理

    LD_LIBRARY_PATH Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径.(该路径在默认路径之前查找) 移植程序时的经常碰到需要使用一些特定的动 ...

  7. log4j 配置详解

    参考如下两个网址,讲的很详细,先看第一个再看第二个: log4j使用介绍:http://swiftlet.net/archives/683 java日志处理组件log4j--log4j.xml配置详解 ...

  8. Enumeration 接口的使用

          Enumeration是一个接口,定义了两个规则,可以获取连续的数据,对数据结构非常重要.       接口源码: publicinterfaceEnumeration<E>{ ...

  9. Microsoft Translator:打破语言障碍 拓展全球沟通新机遇

    作者:Olivier Fontana, 微软研究院Microsoft Translator产品战略总监 世界越来越小,全球协作.共同创新已经成为常态.在微软研究院,我们对此尤为感同身受——从北京到雷德 ...

  10. java--内存管理的几点小技巧

    今天看一本书,书上提到了内存泄露,后面也提到了内存管理的小技巧,在这里记下来,以免以后忘记. 1.尽量使用直接量.比如:String str = "I can play!";而不是 ...