sqlite: Error Code : 5 (SQLITE_BUSY) (database is locked (code 5): , while compiling: PRAGMA journal_mode)
今天遇到了一个很奇怪的问题,登录完成后,程序会莫名crash, 报了下面的错误:
sqlite: Error Code : (SQLITE_BUSY) (database is locked (code ): , while compiling: PRAGMA journal_mode)
经过分析发现是数据库被locked,从而导致在调用
mDatabase = mDBHelper.getWritableDatabase();
时发生了crash, 而android上面同一时间向sqlite里写数据只允许有一个sqlite connection,所以发生了crash, 不过问题根源还是在数据库locked, 那么如何发生locked的呢?
仔细检查后发现:
private synchronized void copyTableFromAnonymousTable() {
SQLiteDatabase db = openDatabase();
try {
if (db.isOpen()) {
db.execSQL("create table if not exists "+ FLIGHT_LOG_TABLE_NAME +
"(id integer primary key autoincrement, " +
""+DBConfig.FLYING_LOG_USER_ID+" integer, "+
""+DBConfig.FLYING_LOG_USER_NAME+" varchar(100), "+
""+DBConfig.FLYING_LOG_HOME_LAT+" double, "+
""+DBConfig.FLYING_LOG_HOME_LON+" double, "+
""+DBConfig.FLYING_LOG_LAST_LAT+" double, "+
""+DBConfig.FLYING_LOG_LAST_LON+" double, "+
""+DBConfig.FLYING_LOG_LOCATION+" varchar(250), "+
""+DBConfig.FLYING_LOG_CITY+" varchar(50), "+
""+DBConfig.FLYING_LOG_DRONE_TYPE+" integer, "+
""+DBConfig.FLYING_LOG_DRONE_TYPE_STR+" varchar(100), "+
""+DBConfig.FLYING_LOG_DRONE_SSID+" varchar(150), "+
""+DBConfig.FLYING_LOG_DRONE_SN+" varchar(150), "+
""+DBConfig.FLYING_LOG_TAKEOFF_TIME+" long, "+
""+DBConfig.FLYING_LOG_LANDING_TIME+" long, "+
""+DBConfig.FLYING_LOG_DURATION+" long, "+
""+DBConfig.FLYING_LOG_TAKEOFF_TIME_STR+" varchar(150), "+
""+DBConfig.FLYING_LOG_RAW_OFFSET+" long, "+
""+DBConfig.FLYING_LOG_APP_VERSION+" varchar(100), "+
""+DBConfig.FLYING_LOG_FC_VERSION+" varchar(100), "+
""+DBConfig.FLYING_LOG_RC_VERSION+" varchar(100), "+
""+DBConfig.FLYING_LOG_CAM_VERSION+" varchar(100), "+
""+DBConfig.FLYING_LOG_MAX_HEIGHT+" double, "+
""+DBConfig.FLYING_LOG_MAX_SPEED+" double, "+
""+DBConfig.FLYING_LOG_MAX_DISTANCE +" double, "+
""+DBConfig.FLYING_LOG_TOTAL_MILEAGE+" double, "+
""+DBConfig.FLYING_LOG_FLIGHT_STATUS+" double, "+
""+DBConfig.FLYING_LOG_PLATFORM+" varchar(50), "+
""+DBConfig.FLYING_LOG_EXTEND_DATA1+" varchar(100), "+
""+DBConfig.FLYING_LOG_EXTEND_DATA2+" varchar(100), "+
""+DBConfig.FLYING_LOG_EXTEND_DATA3+" varchar(100), "+
""+DBConfig.FLYING_LOG_EXTEND_DATA4+" varchar(100)"
+")");
db.beginTransaction();
db.execSQL("INSERT INTO "+FLIGHT_LOG_TABLE_NAME+" SELECT * FROM "+FLIGHT_DEFAULT_TABLE_NAME+"");
db.setTransactionSuccessful(); db.endTransaction();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDatabase();
}
db.execSQL("INSERT INTO "+FLIGHT_LOG_TABLE_NAME+" SELECT * FROM "+FLIGHT_DEFAULT_TABLE_NAME+"");
执行上述SQL语句时是有问题的,而这个问题被try catch 捕获掉了,但是:
db.endTransaction();
却没有被执行!后来将 db.endTransaction(); 移至finally 代码块中发现程序变好了。
以前一直觉得只要记得closeDatabase就好了,却没注意到不 end transaction 也会造成问题,在此记录一下,引以为诫。
关于如何unlock的问题
其实我发现数据库被Locked了之后的第一反应时是如何去unlock。不过很遗憾,我没有在现有的android API里找到类似于数据库lock/unlock的方法。不过android 倒是提供了一个
isDbLockedByCurrentThread() 这样的方法用于检测当前数据库是否有被lock, 网上很多的数据库打开方式都是类似于下列代码:
private synchronized SQLiteDatabase openDatabase() {
if (mOpenCounter.incrementAndGet() == 1 || mDatabase == null) {
mDatabase = mDBHelper.getWritableDatabase();
}
return mDatabase;
}
这种方式虽然貌似解决了多个 数据库connection的问题,但是个人以为还是不太完善,像我遇到的这种情况,最终crash就发生在
mDatabase = mDBHelper.getWritableDatabase();
这行代码里。因此个人以为保险起见,可以在上述代码之前添加一个诸如下列的代码:
private synchronized SQLiteDatabase openDatabase() {
if (mOpenCounter.incrementAndGet() == 1 || mDatabase == null) {
if (mDatabase == null) {
mDatabase = mDBHelper.getWritableDatabase();
}
else {
while (mDatabase.isDbLockedByCurrentThread()) {
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
mDatabase = mDBHelper.getWritableDatabase();
}
}
return mDatabase;
}
可能会更好点,个人看法。
sqlite: Error Code : 5 (SQLITE_BUSY) (database is locked (code 5): , while compiling: PRAGMA journal_mode)的更多相关文章
- sqlite:多线程操作数据库“database is locked”解决方法(二)
上一篇博客<sqlite:多线程操作数据库“database is locked”解决方法>通过注册延时函数的方法来处理数据库被锁的问题.此方法固然能解决问题,但是在多个线程向数据库写入大 ...
- sqlite:多线程操作数据库“database is locked”解决方法
1. 使sqlite支持多线程(不确定是否非加不可,暂且加上,以备后患) 可以在编译时/启动时/运行时选择线程模式,参考:http://www.cnblogs.com/liaj/p/4015219.h ...
- sqlite遇到database is locked问题的完美解决
这两天在项目中用大强度大频率的方法测试时遇到sqlite报database is locked的问题,分析下来原因是sqlite对数据库做修改操作时会做(文件)锁使得其它进程同一时间使用时会报该错误( ...
- SQLITE报错database is locked的解决办法
用firedac连接SQLITE数据库,空间tdbedit绑定字段name,如下语句修改其值时报错. procedure TForm1.Button3Click(Sender: TObject);be ...
- 解决SQLite database is locked
前些时候,同事在站点服务端使用SQlite存储一些临时数据,但是在多人并发的时候Sqlite会抛出异常:The database file is locked , database is locked ...
- sqlite 报错:database is locked
在sqlite批量添加数据时,报错:database is locked. 解决办法:将db路径由相对路径设置为绝对路径.
- dpkg: error: dpkg status database is locked by another process 解决方法
使用dpkg -i/apt命令安装,报错: ------------------------------------------------------------- dpkg: error: dpk ...
- 解决SQLite中的 database is locked
前些时候,同事在站点服务端使用SQlite存储一些临时数据,但是在多人并发的时候Sqlite会抛出异常:The database file is locked , database is locked ...
- SQLITE 多进程查询出错database is locked
程序比较简单: 父进程查询数据库A表,没有更新操作 子进程同时查询数据库A表,查询出来的内容更新B表. 两个进程都放到while(1)循环中,速度慢的话就是2S执行一次就没有错,执行的速度快的话就会报 ...
随机推荐
- 利用JQuery 来操作 ListBox和ListBox内移动
[导读]利用jquery 来操作 listbox和listbox内移动function listbox_move(listfrom,listto) { var size = $(" &quo ...
- 最新CoreData封装Demo
1.创建CoreData文件 2. 3. 4. UploadCoreDataAPI.h // // UploadCoreDataAPI.h // dsafsda // // Created by 冯敏 ...
- 树莓派 SD卡镜像备份
一.准备工作 1.已经配置启动的树莓派SD卡 2.Linux系统的pc 3.读卡器 二.修改SD卡文件 刚开始我先再win7下把SD卡接到pc上,发现无法读取.用DISKGENIUS查看pc的磁盘状态 ...
- HDU 4540 威威猫系列故事——打地鼠 (状态压缩DP)
威威猫系列故事——打地鼠 Time Limit: 300/100 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total ...
- HTTP 请求头 Header
HTTP 请求头 Header HTTP请求头概述 (HttpServletRequest) HTTP客户程序(例如浏览器),向服务器发送请求的时候必须指明请求类型(一般是GET或者POST或者HEA ...
- 基于matplotlib的数据可视化 - 笔记
1 基本绘图 在plot()函数中只有x,y两个量时. import numpy as np import matplotlib.pyplot as plt # 生成曲线上各个点的x,y坐标,然后用一 ...
- mysql用户权限管理的问题
为了保证数据库安全,建立了若干个只能select的用户,但在权限授权的时候出现了不能连接的问题, 一个个尝试了一下,需要将 : 管理 -> SUPER项勾选才行(使用phpmyadmin),上 ...
- Ilist<object>转换成I<实体> 如何转换
ml = objects.Cast<menu>().ToList(); //需要 using System.Linq;
- javascript控件(一):一个好用的日历
一.官网 http://www.my97.net/ 二.引用 <script src="bower_components/My97DatePicker/WdatePicker.js&q ...
- C# 对文件与文件夹的操作包括删除、移动与复制
在.Net中,对文件(File)和文件夹(Folder)的操作可以使用File类和Directory类,也可以使用FileInfo类和DirectoryInfo类.文件夹(Folder)是只在Wind ...