• database is locked和SQLITE_BUSY


    下面我做了几个实验:

    1、多个线程(pthread),使用同一个句柄(一次sqlite3_open,同一个数据库文件),在多个线程中同时使用此句柄,这些线程中有的是进行select操作的,有的是进行update操作的,使用的都是sqlite3_exec函数;结果是没有发现database is locked错误;

    程序源码(mutitrhead.c ):

     

    1. #include <sqlite3.h>  
    2. #include <stdio.h>  
    3. #include <pthread.h>  
    4. #include <string.h>  
    5. #include "main.h"  
    6.   
    7. #ifdef _WIN32  
    8. #include <windows.h>  
    9. #define sleep(x) Sleep((x)*1000)  
    10. #else  
    11. #define sleep(x) sleep(x)  
    12. #endif  
    13.   
    14. #define CREATE_SQL        
    15.         "CREATE TABLE IF NOT EXISTS "mutiprocess" ("                
    16.         ""id"  INTEGER NOT NULL PRIMARY KEY,"         
    17.         ""src"  TEXT(1024),"                     
    18.         ""videotype"  INTEGER NOT NULL,"                
    19.         ""postfiledir"  TEXT(1024)"                     
    20.         ");"  
    21. #define REPLACE_SQL "REPLACE INTO mutiprocess (id,src,videotype,postfiledir) VALUES(NULL,%d,%d,%d)"  
    22. #define UPDATE_SQL "UPDATE mutiprocess SET videotype = '2' WHERE id = 1"  
    23. #define SELECT_SQL "SELECT * FROM mutiprocess"  
    24.   
    25. static void* select_cf(void *param)  
    26. {  
    27.         int rc = -1;  
    28.         sqlite3 *db = (sqlite3*)param;  
    29.         char *szErrMsg;  
    30.         pthread_t tid;  
    31.   
    32.         tid = pthread_self();  
    33.         while(1){  
    34.                 rc = sqlite3_exec(db ,SELECT_SQL, 0, 0, &szErrMsg);  
    35.                 if (rc != SQLITE_OK) {  
    36.                         printf("tid %u -- select error.[%s] -- rc=[%d] ", tid, szErrMsg, rc);  
    37.                         if(strstr(szErrMsg, "database is locked")){  
    38.                                 printf("<database is locked> when executing [%s], retry after 1 second. ", SELECT_SQL);  
    39.                         }  
    40.                 }else{  
    41.                         printf("tid %u -- successfully execute [%s]. ", tid, SELECT_SQL);  
    42.                 }  
    43.                 sleep(1);  
    44.         }  
    45. }  
    46.   
    47. static void* update_cf(void *param)  
    48. {  
    49.         int rc = -1;  
    50.         sqlite3 *db = (sqlite3*)param;  
    51.         char *szErrMsg;  
    52.         pthread_t tid;  
    53.   
    54.         tid = pthread_self();  
    55.         while(1){  
    56.                 rc = sqlite3_exec(db ,UPDATE_SQL, 0, 0, &szErrMsg);  
    57.                 if (rc != SQLITE_OK) {  重生之大文豪www.dwhao.com
    58.                         printf("tid %u -- update error.[%s] -- rc=[%d] ", tid, szErrMsg, rc);  
    59.                         if(strstr(szErrMsg, "database is locked")){  
    60.                                 printf("<database is locked> when executing [%s], retry after 1 second. ", UPDATE_SQL);  
    61.                         }  
    62.                 }else{  
    63.                         printf("tid %u -- successfully execute [%s]. ", tid, UPDATE_SQL);  
    64.                 }  
    65.                 sleep(1);  
    66.         }  
    67. }  
    68.   
    69. int main()  
    70. {  
    71.         pthread_t pid[20];  
    72.         int rc;  
    73.         sqlite3 *db = 0;  
    74.         char *szErrMsg;  
    75.         int i = 0;  
    76.         char sql[1024] = {0};  
    77.   
    78.         rc = sqlite3_open("mutiprocess.db", &db);  
    79.         if (rc != SQLITE_OK) {  
    80.                 printf("open sqlite3 error. ");  
    81.         }  
    82.   
    83.         rc = sqlite3_exec(db ,CREATE_SQL, 0, 0, &szErrMsg);  
    84.         if (rc != SQLITE_OK) {  
    85.                 printf("create db error-[%s] ", szErrMsg);  
    86.         }  
    87.   
    88.         for(i = 0; i < 4; i++){  
    89.                 sprintf(sql, REPLACE_SQL, i, i, i);  
    90.                 rc = sqlite3_exec(db ,sql, 0, 0, &szErrMsg);  
    91.                 if (rc != SQLITE_OK) {  
    92.                         printf("replace db error-[%s] ", szErrMsg);  
    93.                 }  
    94.         }  
    95.   
    96.         for(i = 0; i < 10; i++){  
    97.                 pthread_create(&(pid[i]), 0, select_cf, db);  
    98.                 pthread_detach(pid[i]);  
    99.         }  
    100.         for(; i < 20; i++){  
    101.                 pthread_create(&(pid[i]), 0, update_cf, db);  
    102.                 pthread_detach(pid[i]);  
    103.         }  
    104.   
    105.         while(1){  
    106.                 sleep(-1);  
    107.         }  
    108.         return 0;  
    109. }  


    编译:gcc -o mutitrhead mutitrhead.c -lsqlite3 -lpthread

     

    运行:./mutithread

    注意:只运行这一个进程没有发现任何database is locked的错误提示;如果在运行一个./mutithread进程,那么两个进程都会出现database is locked错误;如果kill掉其中一个进程,那么另外一个不再出现database is locked;

    注意两个进程和一个进程的区别,一个是进程数不同,一个是使用的数据库句柄连接不同;上述程序虽然在一个进程中使用了多线程,但是多个线程都是使用了同一个数据库连接(使用一个sqlite3_open返回的句柄),不好区分是什么问题(其实官方网站有一句话很重要『SQLITE_BUSY means that another database connection (probably in another process) is using the database in a way that prevents 茶叶www.aichar.com  you from using it』);这其实已经说明了产生database is locked的原因了,就是出在多个连接上,那么我们在做下面的实验;

    2、同一个进程,启动多个线程,每个线程中都打开一个连接(connection,使用一个sqlite3_open返回的句柄),并且在其中做select或者update的操作;结果会出现database is locked错误;

    程序源码(muticonnection.c):

     

    1. #include <sqlite3.h>  
    2. #include <stdio.h>  
    3. #include <pthread.h>  
    4. #include <string.h>  
    5. #include "main.h"  
    6.   
    7. #ifdef _WIN32  
    8. #include <windows.h>  
    9. #define sleep(x) Sleep((x)*1000)  
    10. #else  
    11. #define sleep(x) sleep(x)  
    12. #endif  
    13.   
    14. #define CREATE_SQL        
    15.         "CREATE TABLE IF NOT EXISTS "mutiprocess" ("                
    16.         ""id"  INTEGER NOT NULL PRIMARY KEY,"         
    17.         ""src"  TEXT(1024),"                     
    18.         ""videotype"  INTEGER NOT NULL,"                
    19.         ""postfiledir"  TEXT(1024)"                     
    20.         ");"  
    21. #define REPLACE_SQL "REPLACE INTO mutiprocess (id,src,videotype,postfiledir) VALUES(NULL,%d,%d,%d)"  
    22. #define UPDATE_SQL "UPDATE mutiprocess SET videotype = '2' WHERE id = 1"  
    23. #define SELECT_SQL "SELECT * FROM mutiprocess"  
    24.   
    25. static void* select_cf(void *param)  
    26. {  
    27.         int rc;  
    28.         sqlite3 *db = 0;  
    29.         char *szErrMsg;  
    30.         int i = 0;  
    31.         char sql[1024] = {0};  
    32.         pthread_t tid;  
    33.   
    34.         rc = sqlite3_open("mutiprocess.db", &db);  
    35.         if (rc != SQLITE_OK) {  
    36.                 printf("open sqlite3 error. ");  
    37.         }  
    38.   
    39.         rc = sqlite3_exec(db ,CREATE_SQL, 0, 0, &szErrMsg);  
    40.         if (rc != SQLITE_OK) {  
    41.                 printf("create db error-[%s] ", szErrMsg);  
    42.         }  
    43.   
    44.         for(i = 0; i < 4; i++){  
    45.                 sprintf(sql, REPLACE_SQL, i, i, i);  
    46.                 rc = sqlite3_exec(db ,sql, 0, 0, &szErrMsg);  
    47.                 if (rc != SQLITE_OK) {  
    48.                         printf("replace db error-[%s] ", szErrMsg);  
    49.                 }  
    50.         }  
    51.   
    52.         tid = pthread_self();  
    53.         while(1){  
    54.                 rc = sqlite3_exec(db ,SELECT_SQL, 0, 0, &szErrMsg);  
    55.                 if (rc != SQLITE_OK) {  
    56.                         printf("tid %u -- select error.[%s] -- rc=[%d] ", tid, szErrMsg, rc);  
    57.                         if(strstr(szErrMsg, "database is locked")){  
    58.                                 printf("<database is locked> when executing [%s], retry after 1 second. ", SELECT_SQL);  
    59.                         }  
    60.                 }else{  
    61.                         printf("tid %u -- successfully execute [%s]. ", tid, SELECT_SQL);  
    62.                 }  
    63.                 sleep(1);  
    64.         }  
    65. }  
    66.   
    67. static void* update_cf(void *param)  
    68. {  
    69.         int rc;  
    70.         sqlite3 *db = 0;  
    71.         char *szErrMsg;  
    72.         int i = 0;  
    73.         char sql[1024] = {0};  
    74.         pthread_t tid;  
    75.   
    76.         rc = sqlite3_open("mutiprocess.db", &db);  
    77.         if (rc != SQLITE_OK) {  
    78.                 printf("open sqlite3 error. ");  
    79.         }  
    80.   
    81.         rc = sqlite3_exec(db ,CREATE_SQL, 0, 0, &szErrMsg);  
    82.         if (rc != SQLITE_OK) {  
    83.                 printf("create db error-[%s] ", szErrMsg);  
    84.         }  
    85.   
    86.         for(i = 0; i < 4; i++){  
    87.                 sprintf(sql, REPLACE_SQL, i, i, i);  
    88.                 rc = sqlite3_exec(db ,sql, 0, 0, &szErrMsg);  
    89.                 if (rc != SQLITE_OK) {  
    90.                         printf("replace db error-[%s] ", szErrMsg);  
    91.                 }  
    92.         }  
    93.   
    94.         tid = pthread_self();  
    95.         while(1){  
    96.                 rc = sqlite3_exec(db ,UPDATE_SQL, 0, 0, &szErrMsg);  
    97.                 if (rc != SQLITE_OK) {  
    98.                         printf("tid %u -- update error.[%s] -- rc=[%d] ", tid, szErrMsg, rc);  
    99.                         if(strstr(szErrMsg, "database is locked")){  
    100.                                 printf("<database is locked> when executing [%s], retry after 1 second. ", UPDATE_SQL);  
    101.                         }  
    102.                 }else{  
    103.                         printf("tid %u -- successfully execute [%s]. ", tid, UPDATE_SQL);  
    104.                 }  
    105.                 sleep(1);  
    106.         }  
    107. }  
    108.   
    109. int main()  
    110. {  
    111.         pthread_t pid[20];  
    112.         int i = 0;  
    113.   
    114.         for(i = 0; i < 10; i++){  
    115.                 pthread_create(&(pid[i]), 0, select_cf, 0);  
    116.                 pthread_detach(pid[i]);  
    117.         }  
    118.         for(; i < 20; i++){  
    119.                 pthread_create(&(pid[i]), 0, update_cf, 0);  
    120.                 pthread_detach(pid[i]);  
    121.         }  
    122.   
    123.         while(1){  
    124.                 sleep(-1);  
    125.         }  
    126.         return 0;  
    127. }  


    编译:gcc -o muticonnection muticonnection.c -lsqlite3 -lpthread

     

    运行:./muticonnection

     

    总结:看来出现这个错误是因为多数是因为使用了多个连接(多个sqlite3_open返回的句柄)导致的,这里我的说法是“多数”,因为还有别的原因,请见官方网站的解释

    还有一点要注意:

    database is locked是SQLITE_BUSY的错误,不要和SQLITE_LOCKED混淆;

    SQLITE_LOCKED(6) means the source of contention is internal and comes from the same database connection that received the SQLITE_LOCKED error.

    SQLITE_BUSY(5) means that another database connection (probably in another process) is using the database in a way that prevents you from using it.

  • 相关阅读:
    ESXi 5.5 添加驱动
    .net static 变量
    socket
    .net HttpWebRequest 模拟form提交
    node.js form 上传
    .net Thrift 之旅 (二) TServer
    SVN服务器从Windows迁移到LInux
    如何在windows上安装部署设置SVN服务器
    [Ubuntu]在Ubuntu下搭建自己的源服务器
    Eclipse总是自动关闭
  • 原文地址:https://www.cnblogs.com/jiangye/p/3530131.html
Copyright © 2020-2023  润新知