database is locked和SQLITE_BUSY

database is locked和SQLITE_BUSY,第1张

概述这是官方网站找到的解释:http://www.sqlite.org/cvstrac/wiki?p=DatabaseIsLocked 下面我做了几个实验: 1、多个线程(pthread),使用同一个句柄(一次sqlite3_open,同一个数据库文件),在多个线程中同时使用此句柄,这些线程中有的是进行select *** 作的,有的是进行update *** 作的,使用的都是sqlite3_exec函数;结果是没有

这是官方网站找到的解释:http://www.sqlite.org/cvstrac/wiki?p=DatabaseIsLocked


下面我做了几个实验:

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

程序源码(mutitrhead.c):

#include <sqlite3.h>#include <stdio.h>#include <pthread.h>#include <string.h>#include "main.h"#ifdef _WIN32#include <windows.h>#define sleep(x) Sleep((x)*1000)#else#define sleep(x) sleep(x)#endif#define CREATE_sql      \        "CREATE table IF NOT EXISTS \"mutiprocess\" ("              \        "\"ID\"  INTEGER NOT NulL PRIMARY KEY,"       \        "\"src\"  TEXT(1024),"                   \        "\"vIDeotype\"  INTEGER NOT NulL,"              \        "\"postfiledir\"  TEXT(1024)"                   \        ");"#define REPLACE_sql "REPLACE INTO mutiprocess (ID,src,vIDeotype,postfiledir) VALUES(NulL,%d,%d)"#define UPDATE_sql "UPDATE mutiprocess SET vIDeotype = '2' WHERE ID = 1"#define SELECT_sql "SELECT * FROM mutiprocess"static voID* select_cf(voID *param){        int rc = -1;        sqlite3 *db = (sqlite3*)param;        char *szErrMsg;        pthread_t tID;        tID = pthread_self();        while(1){                rc = sqlite3_exec(db,SELECT_sql,&szErrMsg);                if (rc != sqlITE_OK) {                        printf("tID %u -- select error.[%s] -- rc=[%d]\n",tID,szErrMsg,rc);                        if(strstr(szErrMsg,"database is locked")){                                printf("<database is locked> when executing [%s],retry after 1 second.\n",SELECT_sql);                        }                }else{                        printf("tID %u -- successfully execute [%s].\n",SELECT_sql);                }                sleep(1);        }}static voID* update_cf(voID *param){        int rc = -1;        sqlite3 *db = (sqlite3*)param;        char *szErrMsg;        pthread_t tID;        tID = pthread_self();        while(1){                rc = sqlite3_exec(db,UPDATE_sql,&szErrMsg);                if (rc != sqlITE_OK) {                        printf("tID %u -- update error.[%s] -- rc=[%d]\n",UPDATE_sql);                        }                }else{                        printf("tID %u -- successfully execute [%s].\n",UPDATE_sql);                }                sleep(1);        }}int main(){        pthread_t pID[20];        int rc;        sqlite3 *db = 0;        char *szErrMsg;        int i = 0;        char sql[1024] = {0};        rc = sqlite3_open("mutiprocess.db",&db);        if (rc != sqlITE_OK) {                printf("open sqlite3 error.\n");        }        rc = sqlite3_exec(db,CREATE_sql,&szErrMsg);        if (rc != sqlITE_OK) {                printf("create db error-[%s]\n",szErrMsg);        }        for(i = 0; i < 4; i++){                sprintf(sql,REPLACE_sql,i,i);                rc = sqlite3_exec(db,sql,&szErrMsg);                if (rc != sqlITE_OK) {                        printf("replace db error-[%s]\n",szErrMsg);                }        }        for(i = 0; i < 10; i++){                pthread_create(&(pID[i]),select_cf,db);                pthread_detach(pID[i]);        }        for(; i < 20; i++){                pthread_create(&(pID[i]),update_cf,db);                pthread_detach(pID[i]);        }        while(1){                sleep(-1);        }        return 0;}

编译: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 you from using it』);这其实已经说明了产生database is locked的原因了,就是出在多个连接上,那么我们在做下面的实验;

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

程序源码(muticonnection.c):

#include <sqlite3.h>#include <stdio.h>#include <pthread.h>#include <string.h>#include "main.h"#ifdef _WIN32#include <windows.h>#define sleep(x) Sleep((x)*1000)#else#define sleep(x) sleep(x)#endif#define CREATE_sql      \        "CREATE table IF NOT EXISTS \"mutiprocess\" ("              \        "\"ID\"  INTEGER NOT NulL PRIMARY KEY,%d)"#define UPDATE_sql "UPDATE mutiprocess SET vIDeotype = '2' WHERE ID = 1"#define SELECT_sql "SELECT * FROM mutiprocess"static voID* select_cf(voID *param){        int rc;        sqlite3 *db = 0;        char *szErrMsg;        int i = 0;        char sql[1024] = {0};        pthread_t tID;        rc = sqlite3_open("mutiprocess.db",szErrMsg);                }        }        tID = pthread_self();        while(1){                rc = sqlite3_exec(db,SELECT_sql);                }                sleep(1);        }}static voID* update_cf(voID *param){        int rc;        sqlite3 *db = 0;        char *szErrMsg;        int i = 0;        char sql[1024] = {0};        pthread_t tID;        rc = sqlite3_open("mutiprocess.db",UPDATE_sql);                }                sleep(1);        }}int main(){        pthread_t pID[20];        int i = 0;        for(i = 0; i < 10; i++){                pthread_create(&(pID[i]),0);                pthread_detach(pID[i]);        }        for(; i < 20; i++){                pthread_create(&(pID[i]),0);                pthread_detach(pID[i]);        }        while(1){                sleep(-1);        }        return 0;}

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

运行:./muticonnection


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

还有一点要注意:

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.

附:sqlITE_LOCKED(6)错误见:http://sqlite.1065341.n5.nabble.com/Begin-immediate-transaction-gt-SQLITE-BUSY-database-is-locked-td64878.html

总结

以上是内存溢出为你收集整理的database is locked和SQLITE_BUSY全部内容,希望文章能够帮你解决database is locked和SQLITE_BUSY所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1172985.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存