SQLite数据库损坏与修复
【引子】
平時用sqlite數據庫比較少。被問到sqlite數據庫損壞怎么辦這個問題時就把我難住了,于是就整合了幾篇比較好的文章,記錄一下。
SQLite算是非常穩定的數據庫,不容易出現損壞,就算應用程序崩潰,或者操作系統崩潰,甚至是執行事務時出現斷電,都能在下一次使用數據庫時自動修復。但是,還是不能避免不出現損壞的情況。
導致SQLite數據庫損壞的情況
導致SQLite數據庫損壞的情況大致可歸結為4類:文件覆蓋問題、文件鎖問題、數據同步問題、內存問題
文件覆蓋問題
SQLite數據庫文件被覆蓋是可能的,畢竟是一個普通的磁盤文件,意味著所有的進程都可以打開和覆蓋,所以不可能完全避免文件覆蓋的情況。
1. 多線程寫數據庫問題。
SQLite數據庫是支持多進程并發讀寫,但是如果這時候關閉和重新打開數據庫,就很可能出現一些線程還在寫數據到數據庫,出現部分數據被覆蓋的情況。
2. 執行事務時備份或恢復數據
事務都是一個過程性的操作,需要一定時間,而數據備份是原子操作,如果在事務執行過程時備份,可能導致復制的內容包含了部分新的內容和部分舊的內容,就出現數據庫損壞。恢復也是一樣。
3. 刪除日志文件
SQLite數據庫通常都是存儲所有內容到一個文件,但執行事務時,為了實現程序崩潰,斷電時可以回滾日志,就伴隨著一些附加的日志文件。如果日志被刪除了,就會導致恢復出現異常。
文件鎖問題
為了實現SQLite數據庫并發讀寫,SQLite會使用文件鎖來保證數據安全。
1. 系統文件鎖問題
SQLite依賴于底層的文件系統對文件鎖的實現,但是,一些文件系統存在鎖邏輯錯誤,使得鎖并不可靠,這在網絡文件系統和NFS情況比較常見。
2. POSIX協同鎖(advisory lock)
在linux 或者unix下,SQLite 默認鎖是協同鎖。當進程使用 協同鎖,如果其中有一個線程執行 close() 就可能導致鎖被取消。如果已經有兩個線程同時連接到同一個數據庫,再來一個線程不以SQLite API的形式,就是以系統文件形式讀取數據庫( open(), read() , 然后close()),就會導致這個進程的數據庫鎖被取消,而兩個線程同時操作數據庫就會導致數據覆蓋引起錯亂。
3. 不同的連接協議
不同的 連接協議鎖也可能會不同,也就導致鎖沒有發揮錯誤引起錯誤。
4.當數據庫正在使用時刪除或重命名數據庫文件
出現這種情況往往是在linux等類POSIX系統,windows下不會出現這個情況,而且同時有事務執行就會放大這個問題。
數據同步問題
為了保證數據一致性, SQLite有時候會請求操作系統將所有等待持久化的數據刷入磁盤,然后等待這個操作完成。
1.磁盤驅動器的同步請求可能是不可靠的
現有普通消費級別的磁盤驅動器 多數 都會謊報數據同步結果,以期望得到更高的寫入速度。當數據剛到達磁盤緩沖區,還沒真正寫入氧化物介質,磁盤驅動器就報告內容已經安全寫入。但是這時候斷電、硬件復位就會導致數據同步失敗。這種情況主要出現在閃存介質。
2.使用PRAGMAs會影響同步
通過設置PRAGMA synchronous=OFF, SQLite所有的同步操作都會被忽略。這使得SQLite運行得更快,但如果出現電源故障或硬件復位就會前面保存的所有數據。 如果單純為了獲得最大的數據可靠性和健壯性,SQLite可設置synchronous = FULL
內存問題
SQLite作為一個 C運行庫, 和使用它的應用程序運行在同一個內存地址空間。這意味著,任何野指針,緩沖區溢出,堆損壞等都有可能損壞了 SQLite的數據結構,并最終導致數據庫文件損壞。
另外,使用內存映射I/O模型(如mmap)的時候,內存問題會變得更加嚴重。當數據庫文件的一部分或全部被映射到應用程序的地址空間,雖然減少了文件IO操作,但是野指針可能訪問并修改到任何部分的 映射空間 數據。
更多SQLite數據庫損壞的原因可以看官網
How To Corrupt An SQLite Database File。
1.1. Continuing to use a file descriptor after it has been closed
1.2. Backup or restore while a transaction is active
1.3. Deleting a hot journal
1.4. Mispairing database files and hot journals
2.1. Filesystems with broken or missing lock implementations
2.2. Posix advisory locks canceled by a separate thread doing close()
2.2.1. Multiple copies of SQLite linked into the same application
2.3. Two processes using different locking protocols
2.4. Unlinking or renaming a database file while in use
2.5. Multiple links to the same file
2.6. Carrying an open database connection across a fork()
3.1. Disk drives that do not honor sync requests
3.2. Disabling sync using PRAGMAs
4.1. Non-powersafe flash memory controllers
4.2. Fake capacity USB sticks
6.1. Linux Threads
6.2. Failures of mmap() on QNX
6.3. Filesystem Corruption
8.1. False corruption reports due to database shrinkage
8.2. Corruption following switches between rollback and WAL modes
8.3. I/O error while obtaining a lock leads to corruption
8.4. Database pages leak from the free page list
8.5. Corruption following alternating writes from 3.6 and 3.7.
8.6. Race condition in recovery on windows system.
修復損壞的SQLite數據庫
前陣子由于分區空間滿出現了sqlite3數據庫文件損壞的現象,操作的時候報錯:
Error: database disk image is malformed
這里記錄一下修復的操作過程:
1.將數據庫中的數據導出為sql語句文件
sqlite3 test_file.db #打開損壞的數據庫文件 .output recovery.sql #設置輸出文件 .dump # 導出文件 .q2.將導出的recovery.sql文件最后一行ROLLBACK改為COMMIT;
vim recovery.sql3.導入到一個新庫中
sqlite3 fix.db #打開用于導入修復后的數據庫數據 .read recovery.sql #讀取數據文件 .qSQLite使用建議
這里有4點建議:
引經據典
https://blog.csdn.net/jieshibendan/article/details/90678036
https://blog.csdn.net/qq_35241071/article/details/111247142
https://blog.csdn.net/mycwq/article/details/45541409
總結
以上是生活随笔為你收集整理的SQLite数据库损坏与修复的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年中国餐饮配送机器人行业研究报告
- 下一篇: 微信生态下的营销洞察