Android5.0上運行SQLite資料庫出現attempt to write a readonly database的解決方案

來源:互聯網
上載者:User

標籤:android ndk jni sqlite attempt to write a readonly database

情境

Jni下編譯SQLite源碼作為資料庫,在測試手機:型號(Redmi Note 2) Android版本(5.0.2 LRX22G)系統下使用,嘗試寫資料庫的時候,返回錯誤資訊:attempt to write a readonly database


解決

在sqlite.c檔案中尋找

ino_t ino; /* Inode number */

修改為

unsigned long long ino; /* Inode number */



錯誤說明

Store inodes in unsigned long long


In 32 bit ABIs, ino_t is a 32 bit type, while the st_ino field


in struct stat is 64 bits wide in both 32 and 64 bit processes.


This means that struct stat can expose inode numbers that are


truncated when stored in an ino_t.


The SDCard fuse daemon (/system/bin/sdcard) uses raw pointer


values as inode numbers, so on 64 bit devices, we‘re very likely


to observe inodes that need > 32 bits to represent.


The fileHasMoved function in sqlite compares the stored


inode value with a new one from stat, and when the stored


value is truncated, this check will falsely indicate that


the file has been moved. When the fileHasMoved function


triggers, other functions start returning errors indicating


that the database is in read-only mode.


NOTE: Bionic differs from glibc in that struct stat‘s st_ino


is *always* 64 bits wide, and not the same width as ino_t.



參考

http://www.jianshu.com/p/30139ef31230


解決過程:

1 懷疑是讀寫權限的問題,但是其他檔案也有讀寫,明顯不成立,並且已經提供了讀寫的許可權:

<uses-permission android:name="android.permission.INTERNET" />


2 懷疑是使用MTP模式共用機身儲存到電腦,導致兩邊同時編輯,通過關閉MTP媒體共用,不成立

Redmi Note 2手機請勿關閉MTP媒體裝置,否則需要恢復出廠預設值才能夠重新共用到電腦。


3 拷貝test.db和test.db-journal檔案到Windows系統,並且使用SQLite控制台進行修改,沒有任何的

問題。當前使用的是相同的SQLite源碼編譯的控制台程式。進行資料的插入過程中,會自動刪除journal歸檔檔案,並沒有提示唯讀。另外單獨拷貝test.db,直接操作,也沒有任何的問題。


4 嘗試關閉Java層對資料庫的讀寫訪問,只是允許NDK層直接操作資料庫,防止多線程訪問資料庫,還是出現同樣的結果,當然不知道是否是sqlite3_open與sqlite3_open_v2的介面是否會產生不同的結果,目前採用第一種方法訪問資料庫。


5 嘗試擷取Android系統中SQLite的版本,調用getVersion返回1,沒有實質上的協助。


6 是否是其他的Java層擷取資料庫的串連,沒有關閉導致問題的出現?SQliteOpenHelper內部只緩衝一個資料庫的串連,在多線程的使用過程中,不要頻繁的調用close,而應該儲存一個唯一的一個訪問執行個體,但是對於多進程之間的訪問,也帶來問題http://blog.sina.com.cn/s/blog_5de73d0b0102w0g0.html



7 雖然NDK無法修改資料,但是可以讀取資料,而Java層卻可以輕鬆的完成資料庫的修改操作。


8 嘗試調用beginTransaction和endTransaction對資料庫的操作進行事務加鎖還是沒有任何的效果


9 懷疑是Android目錄的讀取問題,NDK層的SQLite讀取資料庫檔案,發現有問題,但是沒有辦法找到journal歸檔檔案,因此認為是唯讀,也是合理的

總結:

    經過上述種種的研究分析,得到如下的猜測:NDK層的SQLite執行個體在系統開機啟動之後,會檢查是否存在journal檔案。如果是通過程式自動刪除該journal檔案。但是如果程式無法自動刪除,目前懷疑就是因為版本之間的不對稱,導致無法刪除journal,SQLite資料庫因此資料庫變成唯讀狀態。


折中方案:

    NDK層只是負責唯讀資料,如果有任何的修改,都需要調用Java的介面進行修改資料,雖然有SQLite的源碼,但是NDK層不好調試。


Android5.0上運行SQLite資料庫出現attempt to write a readonly database的解決方案

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.