SQLiteException: database is locked異常的解決辦法
原理:檔案資料庫sqlite,同一時刻允許多個程序/執行緒讀,但同一時刻只允許一個執行緒寫。在操行寫操作時,資料庫檔案被瑣定,此時任何其他讀/寫操作都被阻塞,如果阻塞超過5秒鐘(預設是5秒,能過重新編譯sqlite可以修改超時時間),就報"database is locked"錯誤。
所以,在操作sqlite時,應該即時關閉連線;開啟連線後,儘量減少非常費時的操作。
1. 方法
在頁面中用到了ViewPager控制元件,ViewPager中的內容分別是兩個ListView,兩個ListView的資料都來自本地資料庫(先從網路下載資料,然後更新本地資料庫),在實際的使用過程中發現會出現SQLiteDatabaseLockedException: database is locked的問題。
經網上搜索資料,發現是讀寫資料庫時存在的同步問題,所以採用單例+同步鎖的方法,並且在每次資料庫操作後都關閉資料庫,經測試後發現沒有在出現上述問題。
以下是兩個主類
DBHelper.java(這個類用來管理資料庫)
public class DBHelper extends SQLiteOpenHelper { private final String TAG = this.getClass().getSimpleName(); public final static String DATABASE_NAME = "test.db"; public final static String TABLE = "table"; public final static int DATABASE_VERSION = 2; public DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } private static DBHelper mInstance; public synchronized static DBHelper getInstance(Context context) { if (mInstance == null) { mInstance = new DBHelper(context); } return mInstance; }; @Override public void onCreate(SQLiteDatabase db) { try { db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE + "(id INTEGER PRIMARY KEY ,data BLOB)"); } catch (SQLiteException e) { e.printStackTrace(); } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 刪除原來的資料表 db.execSQL("DROP TABLE IF EXISTS " + TABLE); // 重新建立 onCreate(db); } public static byte[] objectToBytes(Object obj) throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream sOut = new ObjectOutputStream(out); sOut.writeObject(obj); sOut.flush(); byte[] bytes = out.toByteArray(); return bytes; } public static Object bytesToObject(byte[] bytes) throws Exception { ByteArrayInputStream in = new ByteArrayInputStream(bytes); ObjectInputStream sIn = new ObjectInputStream(in); return sIn.readObject(); } }
DBStudentManager類(這裡可以定義自己的管理類)
public class DBStudentManager { private DBHelper helper; private SQLiteDatabase db; public DBStudentManager(Context context) { helper = DBHelper.getInstance(context); db = helper.getWritableDatabase(); } // 插入 private void insert(Student student) { synchronized (helper) { // 看資料庫是否關閉 if (!db.isOpen()) { db = helper.getWritableDatabase(); } // 開始事務 db.beginTransaction(); try { db.execSQL( "INSERT INTO " + DBHelper.TABLE + " VALUES(?,?)", new Object[] { student.mID, DBHelper.objectToBytes(student) }); db.setTransactionSuccessful(); // 設定事務成功完成 } catch (SQLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { db.endTransaction(); db.close(); } } } // 更新 private void update(Student student) { synchronized (helper) { if (!db.isOpen()) { db = helper.getWritableDatabase(); } db.beginTransaction(); try { db.execSQL("UPDATE " + DBHelper.TABLE + "SET data = ? WHERE id = ?", new Object[] { DBHelper.objectToBytes(student), student.mID }); db.setTransactionSuccessful(); // 設定事務成功完成 } catch (SQLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { db.endTransaction(); db.close(); } } } // 同步 public void synchronous(List<Student> students) { if (students == null) { return; } for (Student student : students) { if (query(student.mID) == null) { insert(student); } else { update(student); } } } // 刪除指定資料 public void delete(String id) { synchronized (helper) { if (!db.isOpen()) { db = helper.getWritableDatabase(); } db.beginTransaction(); try { db.execSQL("DELETE FROM " + DBHelper.TABLE + " WHERE id = ? ", new String[] { id }); db.setTransactionSuccessful(); } catch (Exception e) { e.printStackTrace(); } finally { db.endTransaction(); db.close(); } } } // 刪除所有資料 public void delete() { synchronized (helper) { if (!db.isOpen()) { db = helper.getWritableDatabase(); } db.beginTransaction(); try { db.execSQL("DELETE * FROM " + DBHelper.TABLE); db.setTransactionSuccessful(); } catch (Exception e) { e.printStackTrace(); } finally { db.endTransaction(); db.close(); } } } // 查詢所有的Students public List<Student> query() { List<Student> students = new ArrayList<Student>(); synchronized (helper) { if (!db.isOpen()) { db = helper.getWritableDatabase(); } Cursor c = queryTheCursor(); Student student = null; try { while (c.moveToNext()) { byte[] bytes = c.getBlob((c.getColumnIndex("data"))); student = (Student) DBHelper.bytesToObject(bytes); students.add(student); } } catch (Exception e) { e.printStackTrace(); } finally { c.close(); } } return students; } // 查詢指定ID的Student public Student query(String id) { Student student = null; synchronized (helper) { if (!db.isOpen()) { helper.getWritableDatabase(); } Cursor c = queryTheCursor(id); try { while (c.moveToNext()) { byte[] bytes = c.getBlob((c.getColumnIndex("data"))); student = (Student) DBHelper.bytesToObject(bytes); break; } } catch (Exception e) { e.printStackTrace(); } finally { c.close(); } } return student; } // 獲取遊標 public Cursor queryTheCursor(String id) { Cursor c = db.rawQuery("SELECT FROM " + DBHelper.TABLE + " WHERE id = ?", new String[] { id }); return c; } // 獲取遊標 public Cursor queryTheCursor() { Cursor c = db.rawQuery("SELECT * FROM " + DBHelper.TABLE); return c; } class Student { String mID; String mName; int mAge; } }
2. 方法
遇到這個問題,有幾種可能,我在下面詳細的列出來,方便大家在遇到的時候檢視
· 多執行緒訪問造成的資料庫鎖定。
如A執行緒在訪問當前的資料庫,這時候B執行緒也需要訪問資料庫,這樣在B執行緒中,就會有類似以上的異常產生,我們需要將提供資料庫訪問的方法設定成同步的,防止非同步呼叫時出現問題,如:public static synchronized DBConnection getConnection(String connectionName) throws Exception { String pathFile = getPath() + connectionName;// 轉換目錄data下 return new DBConnection(SQLiteDatabase.openDatabase(pathFile, null, SQLiteDatabase.OPEN_READWRITE)); }
使用synchronized 關鍵字來修飾獲取資料庫連線的方法,或者使用isDbLockedByOtherThreads方法判斷資料庫是否被鎖住了,然後等待一定的時間再進行訪問。 ·sqlite自身的問題 有時我們會在除錯程式的時候發現Log控制檯頻繁的出現上述異常,而在執行程式的時候就沒有這個問題,這種現象我在除錯ResultSet時也會出現,查資料找原因是因為sqlite資料不完全是執行緒安全的,導致在一些地方會莫名其妙的出問題,如果遇到這樣的情況,那隻能不要將斷點打到資料庫連線的地方了。3. 方法
如果多執行緒同時讀寫(這裡的指不同的執行緒用使用的是不同的Helper例項),後面的就會遇到android.database.sqlite.SQLiteException:
database is locked這樣的異常。
對於這樣的問題,解決的辦法就是keep single sqlite connection,保持單個SqliteOpenHelper例項,同時對所有資料庫操作的方法新增synchronized關鍵字。
完美解決sqlite的
database locked
或者是
error 5: database locked 問題
相關推薦
SQLiteException: database is locked異常的解決辦法
原理:檔案資料庫sqlite,同一時刻允許多個程序/執行緒讀,但同一時刻只允許一個執行緒寫。在操行寫操作時,資料庫檔案被瑣定,此時任何其他讀/寫操作都被阻塞,如果阻塞超過5秒鐘(預設是5秒,能過重新編譯sqlite可以修改超時時間),就報"database is lo
Yum database disk image is malformed 錯誤 解決辦法
yumyum install xxx 時出現: database disk image is malformed解決辦法:yum clean dbcache Yum database disk image is malformed 錯誤 解決辦法
dpkg: error: dpkg status database is locked by another process 解決方法
http other cor 系統監視 pen figure 操作 body lis https://i.cnblogs.com/EditPosts.aspx?opt=1使用dpkg -i/apt命令安裝,報錯: ------------------------------
解決嵌入式使用SQL出現 Error(5): database is locked
之前有遇到通過sqlite3_exec()函式操作資料庫出現 database is locked 這樣的一個問題,特別的記錄一下這個問題。 SQLite,是一款輕型的資料庫,它的設計目標是嵌入式的,而
解決django的sqlite3的database is locked
今天在用admin後臺新增一篇部落格,最後居然報錯:DatabaseError at ... database is locked, 因為我的資料庫使用的是sqlite3,所以不支援大量的訪問是有可能的,但是目前僅僅我一個人訪問的話,居然報錯,我就納悶了,用google搜
@RequestBody物件為空,異常Required request body is missing的解決辦法
由於與前端互動的過程當中,都是用json資料與前端進行互動,這樣想取出整個傳送過來的json資料的時候,就需要用到@RequestBody這個註解,前端傳送資料的格式如下://測試傳送json資料 $
ios FMDB多執行緒"is currently in use", "database is locked"問題的解決
is currently in use” 出現的場景是這樣的,多執行緒操作資料庫,每個執行緒都使用了FMDatabase例項 FMDatabase是不具備執行緒安全的,如果兩個執行緒中同時操作資料庫,
不完全解決sqlite遇到database is locked問題方法
這兩天在專案中用大強度大頻率的方法測試時遇到sqlite報database is locked的問題, 分析下來原因是sqlite對資料庫做修改操作時會做(檔案)鎖使得其它程序同一時間使用時會報該錯誤(也就是SQLITE_BUSY),但如果僅是多程序或多執行緒查詢sqlite是支援的。解決方法有:1。使
TortoiseSVN提交提示423 Locked的解決辦法
提交 locks mit 4.2 pdf tortoise 擁有 release ise 此辦法是閱讀官方文檔(TortoiseSVN-1.6.16-zh_CN.pdf) 4.21 鎖部分提供的辦法: 首先選擇選擇要提交的文件右鍵菜單:“To
eclipse報jvm terminated.exitcode=2異常解決辦法
不用 oracl system data eclips jre lib acl bsp 如上圖,我原來安裝的是jdk1.7,現在要用到jdk1.8,所以我又安裝了個jdk1.8,安裝jdk1.8後,打開eclipse就提示這樣的信息,上網查了一下說是環境變量path需要修
svn和NetBeans一起使用造成svn老是死鎖, database is locked
beans 就是 base clear 所有 編譯 bean post net 其實我一直沒發現,又一次我以為需要寫些前端吧NetBeans關了,使用HBuilder寫vue,因為內存只有8G,亂七八糟的一些東西一開,只剩20%左右,我就把 NetBeans關了,發現更新s
Keil4 一例異常解決辦法
via .com main.c 自己的 異常 提示 一個 image syn 以下幾個問題在Keil5上沒有發現,不過因為下載的例子都是Keil4,強迫癥讓我用起了Keil4 錯誤一:main.c: Warning: C3910W: Old syntax, please
報錯--dpkg status database is locked
報錯 dpkg status databas dpkg: error: dpkg status database is locked by another process一、可能是軟件中心,關掉就好了,或者打開‵系統監視器‵,在進程裏面把帶有apt, dpkg 字樣的進程 kill掉就行了。二、也可
Pycharm中安裝package出現microsoft visual c++ 14.0 is required問題解決辦法
twisted mina 信息 根據 錯誤 nta 他會 窗口 8.4 在利用pycharm安裝scrapy包是遇到了挺多的問題。在折騰了差不多折騰了兩個小時之後總算是安裝好了。期間各種谷歌和百度,發現所有的教程都是利用命令行窗口安裝的。發現安裝scrapy需要的包真是多的
testNg 關閉瀏覽器異常解決辦法
ask sed kill 系統文件 process sys after 環境 lips 執行testNg關閉瀏覽器方法一直報錯,報錯信息如下:Process refused to die after 10 seconds, and couldn‘t taskkill it
Redis安裝異常解決辦法
命令 alloc error: 說明 文件中 密碼登錄 from nload size $ wget http://download.redis.io/releases/redis-4.0.11.tar.gz $ tar xzf redis-4.0.11.tar.gz $
python學習(5)--網易郵箱發郵件異常解決辦法
python發郵件 解決辦法如下 nbsp -- bsp err error 發郵件 png 在用python發郵件時,發現用網易郵箱作為發件人。會出現以下異常: smtplib.SMTPDataError: (554, b‘DT:SPM 163 smtp12,EMCo
spark/java連線 kudu incompatible RPC? Error is: step 異常解決
如果是新搭的CDH 叢集並使用預設的kudu設定, 使用spark /java 連線kudu時候,一般都會碰到此類異常。 程式: val masteraddr = "kudumasterip:7051" //建立kudu的資料庫連結 val client = new KuduClient.Kudu
Linux——重啟防火牆時出現Failed to start firewalld.service: Unit is masked的解決辦法
報錯如下: 這是因為程序被鎖住了。 對它進行解鎖就可以了。 執行命令,即可實現取消服務的鎖定 # systemctl unmask firewalld 我們試一試 好了,現在防火牆已經重新啟動了。 注:下次需要鎖定該服務時可以輸入以下命令列執行
按需載入iviei元件時,引入vue專案報iview is not defined解決辦法(使用vue-vli + iview)
解決方法 npm 下載(我使用了淘寶映象): cnpm install iview --save cnpm install babel-plugin-import --save-dev .babelrc檔案 { "presets": [ ["env", {