高效解決「SQLite」資料庫併發訪問安全問題,只這一篇就夠了
阿新 • • 發佈:2019-10-07
Concurrent database access
本文譯自:https://dmytrodanylyk.com/articles/concurrent-database/
對於 Android Dev 而言,有關 SQLite 的操作再經常不過了,相比你一定經歷過控制檯一片爆紅的情況,這不禁讓我們疑問:SQLite 到底是執行緒安全的嗎?
OK 廢話不多說,我們 ⬇️
直接開始
首先,假設你已經實現了一個 SQLiteHelper 類,如下所示:
public class DatabaseHelper extends SQLiteOpenHelper { ... }
現在你想要在兩個子執行緒中,分別地向 SQLite 裡寫入一些資料:
// Thread 1 Context context = getApplicationContext(); DatabaseHelper helper = new DatabaseHelper(context); SQLiteDatabase database = helper.getWritableDatabase(); database.insert(…); database.close(); // Thread 2 Context context = getApplicationContext(); DatabaseHelper helper = new DatabaseHelper(context); SQLiteDatabase database = helper.getWritableDatabase(); database.insert(…); database.close();
對吧?看上去很 OK 沒啥毛病。
那麼這時,我們點一下 run
,gio~ 你將會在你的 logcat 裡收到如下禮物「報錯」:
android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
到底是怎麼回事呢?
我們分析一下報錯終於發現:這是由於你每次建立 SQLiteHelper 時,都對資料庫進行了一個連結操作。這時,如果你嘗試著,同時從實際不同的連結中,對資料庫進行寫入操作,失敗就是必然的了。
總結一下
如果我們想再不同的執行緒中,對資料庫進行包括讀寫操作在內的任何使用,我們就必須得確保,我們使用的是同一個的連線
好,那現在問題就明瞭了。現在讓我們建立一個單例模式類:DatabaseManager
用來建立和返回唯一的,單例 DatabaseManager
物件。
ps 有些同學問我什麼是單例模式,我專門跑去寫了這篇部落格來解釋下,單例模式-全域性可用的 context 物件,這一篇就夠了碼字不易幫我點個贊謝謝