SQLite崩潰處理

SQLite崩潰處理

關于SQLite

SQLite 支持如下三種線程模型

  • 單線程模型 這種模型下,所有互斥鎖都被禁用,同一時間只能由一個線程訪問。
  • 多線程模型 這種模型下,一個連接在同一時間內(nèi)只有一個線程使用就是安全的。
  • 串行模型 開啟所有鎖,可以隨意訪問。
    設置線程模型

SQLite 可以通過以下三種方式進行線程模型的設置,在實際應用中選擇任一一項都可以。

  1. 編譯期設定 通過 SQLITE_THREADSAFE 這個參數(shù)進行編譯器的設定來選擇線程模型
  2. 初始化設定 通過調(diào)用 sqlite3_config() 可以在 SQLite 初始化時進行設定
  3. 運行時設定 通過調(diào)用 sqlite3_open_v2() 接口指定數(shù)據(jù)庫連接的數(shù)據(jù)庫模型
    SQLite 并發(fā)和事務

事務

事務是 SQLite 的核心概念。對數(shù)據(jù)庫的操作 (絕大部分) 會被打包成一個事務進行提交,需要注意的是,這里的打包成事務是自動開啟的。舉例而言,如果簡單在一個 for 循環(huán)語句里向數(shù)據(jù)庫中插入 10 條數(shù)據(jù),意味著將自動生成 10 個事務。但需要注意的是事務是非常耗時的,一般而言, SQLite 每秒能夠輕松支持 50000 條的數(shù)據(jù)插入,但是每秒僅能夠支持幾十個事務。一般而言,事務速度受限于磁盤速度。所以在批量插入時需要考慮禁用自動提交,將其用 BEGIN ... COMMIT 打包成一個事務。

回滾模式和 WAL

Write-Ahead Log (常簡寫為 WAL)
為了保證寫入正確,SQLite 在使用事務進行數(shù)據(jù)庫改寫時將拷貝當前數(shù)據(jù)庫文件的備份,即 rollback journal,當事務失敗或者發(fā)生意外需要回滾時則將備份文件內(nèi)容還原到數(shù)據(jù)庫中,并同時刪除該日志。這是默認的 DELETE 模式。

而后 SQLite 也引入了 WAL 模式,即 Write-Ahead Log。在這種模式下,所有的修改會寫入一個單獨的 WAL 文件內(nèi)。這種模式下,寫操作甚至可以不去操作數(shù)據(jù)庫,這使得所有的讀操作可以在 "寫的同時" 直接對數(shù)據(jù)庫文件進行操作,得到更好的并發(fā)性能。

SQLite開啟wal代碼

SQLiteDatabase dataBase = DataBaseHelper.getWritableDatabase()
SQLiteDatabase dataBase.enableWriteAheadLogging();

鎖和并發(fā)

SQLite 通過五種鎖狀態(tài)來完成事務。

  • UNLOCKED ,無鎖狀態(tài)。數(shù)據(jù)庫文件沒有被加鎖。
  • SHARED 共享狀態(tài)。數(shù)據(jù)庫文件被加了共享鎖??梢远嗑€程執(zhí)行讀操作,但不能進行寫操作。
  • RESERVED 保留狀態(tài)。數(shù)據(jù)庫文件被加保留鎖。表示數(shù)據(jù)庫將要進行寫操作。
  • PENDING 未決狀態(tài)。表示即將寫入數(shù)據(jù)庫,正在等待其他讀線程釋放 SHARED 鎖。一旦某個線程持有 PENDING 鎖,其他線程就不能獲取 SHARED 鎖。這樣一來,只要等所有讀線程完成,釋放 SHARED 鎖后,它就可以進入 EXCLUSIVE 狀態(tài)了。
    EXCLUSIVE 獨占鎖。表示它可以寫入數(shù)據(jù)庫了。進入這個狀態(tài)后,其他任何線程都不能訪問數(shù)據(jù)庫文件。因此為了并發(fā)性,它的持有時間越短越好。
    一個線程只有擁有低級別鎖時才能夠獲得更高一級的鎖

要保證數(shù)據(jù)庫使用的安全,一般可以采用如下幾種模式

SQLite 采用單線程模型,用專門的線程/隊列(同時只能有一個任務執(zhí)行訪問) 進行訪問
SQLite 采用多線程模型,每個線程都使用各自的數(shù)據(jù)庫連接 (即 sqlite3 *)
SQLite 采用串行模型,所有線程都公用同一個數(shù)據(jù)庫連接。
因為寫操作的并發(fā)性并不好,當多線程進行訪問時實際上仍舊需要互相等待,而讀操作所需要的 SHARED 鎖是可以共享的,所以為了保證最高的并發(fā)性,推薦

使用多線程模式
使用 WAL 模式
單線程寫,多線程讀 (各線程都持有自己對應的數(shù)據(jù)庫連接)
避免長時間事務
緩存 sqlite3_prepare 編譯結(jié)果
多語句通過 BEGIN 和 COMMIT 做顯示事務,減少多次的自動事務消耗

SQLite錯誤號

1 #define SQLITE_OK           0   /* 成功 | Successful result */
2 /* 錯誤碼開始 */
3 #define SQLITE_ERROR        1   /* SQL錯誤 或 丟失數(shù)據(jù)庫 | SQL error or missing database */
4 #define SQLITE_INTERNAL     2   /* SQLite 內(nèi)部邏輯錯誤 | Internal logic error in SQLite */
5 #define SQLITE_PERM         3   /* 拒絕訪問 | Access permission denied */
6 #define SQLITE_ABORT        4   /* 回調(diào)函數(shù)請求取消操作 | Callback routine requested an abort */
7 #define SQLITE_BUSY         5   /* 數(shù)據(jù)庫文件被鎖定 | The database file is locked */
8 #define SQLITE_LOCKED       6   /* 數(shù)據(jù)庫中的一個表被鎖定 | A table in the database is locked */
9 #define SQLITE_NOMEM        7   /* 某次 malloc() 函數(shù)調(diào)用失敗 | A malloc() failed */
10 #define SQLITE_READONLY     8   /* 嘗試寫入一個只讀數(shù)據(jù)庫 | Attempt to write a readonly database */
11 #define SQLITE_INTERRUPT    9   /* 操作被 sqlite3_interupt() 函數(shù)中斷 | Operation terminated by sqlite3_interrupt() */
12 #define SQLITE_IOERR       10   /* 發(fā)生某些磁盤 I/O 錯誤 | Some kind of disk I/O error occurred */
13 #define SQLITE_CORRUPT     11   /* 數(shù)據(jù)庫磁盤映像不正確 | The database disk image is malformed */
14 #define SQLITE_NOTFOUND    12   /* sqlite3_file_control() 中出現(xiàn)未知操作數(shù) | Unknown opcode in sqlite3_file_control() */
15 #define SQLITE_FULL        13   /* 因為數(shù)據(jù)庫滿導致插入失敗 | Insertion failed because database is full */
16 #define SQLITE_CANTOPEN    14   /* 無法打開數(shù)據(jù)庫文件 | Unable to open the database file */
17 #define SQLITE_PROTOCOL    15   /* 數(shù)據(jù)庫鎖定協(xié)議錯誤 | Database lock protocol error */
18 #define SQLITE_EMPTY       16   /* 數(shù)據(jù)庫為空 | Database is empty */
19 #define SQLITE_SCHEMA      17   /* 數(shù)據(jù)結(jié)構(gòu)發(fā)生改變 | The database schema changed */
20 #define SQLITE_TOOBIG      18   /* 字符串或二進制數(shù)據(jù)超過大小限制 | String or BLOB exceeds size limit */
21 #define SQLITE_CONSTRAINT  19   /* 由于約束違例而取消 | Abort due to constraint violation */
22 #define SQLITE_MISMATCH    20   /* 數(shù)據(jù)類型不匹配 | Data type mismatch */
23 #define SQLITE_MISUSE      21   /* 不正確的庫使用 | Library used incorrectly */
24 #define SQLITE_NOLFS       22   /* 使用了操作系統(tǒng)不支持的功能 | Uses OS features not supported on host */
25 #define SQLITE_AUTH        23   /* 授權(quán)失敗 | Authorization denied */
26 #define SQLITE_FORMAT      24   /* 附加數(shù)據(jù)庫格式錯誤 | Auxiliary database format error */
27 #define SQLITE_RANGE       25   /* 傳遞給sqlite3_bind()的第二個參數(shù)超出范圍 | 2nd parameter to sqlite3_bind out of range */
28 #define SQLITE_NOTADB      26   /* 被打開的文件不是一個數(shù)據(jù)庫文件 | File opened that is not a database file */
29 #define SQLITE_ROW         100  /* sqlite3_step() 已經(jīng)產(chǎn)生一個行結(jié)果 | sqlite3_step() has another row ready */
30 #define SQLITE_DONE        101  /* sqlite3_step() 完成執(zhí)行操作 | sqlite3_step() has finished executing */

Android版本與SQLite版本對應關系

Android SQLite
API 27 3.19
API 26 3.18
API 24 3.9
API 21 3.8
API 11 3.7
API 8 3.6
API 3 3.5
API 1 3.4
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容