2013-10-28 14 views
0

我似乎在我的代碼中每隔一段時間(插入一段重要)就會出現上述錯誤。我通常知道這意味着在連接中有一個開放的遊標,但我已經通過檢查我所有的遊標正在嘗試最後的塊並關閉。 也在logcat中的錯誤讀取'sqlite3_close(...)失敗:5,我認爲這意味着數據庫正忙?Android&SQLite - 偶爾錯誤'無法關閉,由於未處理的陳述'

如果我將下面的代碼添加到數據庫連接關閉的finally塊中,則可以忽略該錯誤。

finally 
    { 
    writer.endTransaction(); 
    boolean successAtClose = false; 
    while(successAtClose == false) 
    { 
     try 
     { 
     writer.close(); 
     successAtClose = true; 
     } 
     catch(Exception e) 
     { 
     e.printStackTrace(); 
     } 
    } 
    dbConn.releaseLock(); 
    } 

當通過上面的代碼加強「e.printStackTrace()」一次,但第二次嘗試的「writer.close()」不會拋出一個錯誤被擊中。

只是重申一次,這個問題在每次代碼塊運行時都不會發生,相同的數據可以插入5/6次,並且只在這些時間中的一個上引發錯誤。此外,錯誤在發生一次後不會立即發生,而是以隨機間隔繼續彈出。

有誰知道爲什麼會發生這種情況?或者比上面的最終代碼更好地恢復? (因爲這將要花費很長的時間把它添加到我的所有數據庫的代碼。)

新增:

數據庫與自定義SQLiteOpenHelper有效期延長使用重入鎖打開,以確保只有一個線程訪問數據庫在任何時候。因此,代碼的開始是這樣的:

MyDatabaseHelper dbConn = MyDatabaseHelper.getDatabaseAccess(c);//await availability/lock the database here 
    SQLiteDatabase writer = dbConn.getWritableDatabase();  
    try 
    {  
     writer.beginTransaction(); 

     //do inserts 

     writer.setTransactionSuccessful(); 

獲取數據庫訪問權限如下:

public static MyDatabaseHelper getDatabaseAccess(Context c) 
    {  
    l.lock();  
    return new MyDatabaseHelper(c); 
    } 

作爲進一步的測試,我已經再加入Thread.sleep()調用最終代碼(在我12的情況下,秒),在close()之前,但在endTransaction()之後,似乎已經停止了錯誤並確認它不是打開遊標的情況,但我寧願不依賴於計時器。如果有更好的方法,或許要預先檢查數據庫是否忙碌,請分享。

回答

1

如果您使用SQLiteStatement或SQLiteQuery對象來處理數據庫,則需要確保它們也被關閉。如果它是SQLiteClosable,則需要關閉它。

+0

畢竟,我很慚愧地說,一旦我經歷了這一切,並將整個過程放在試圖終結塊中,問題就得到了解決。無論是什麼聲明的密切呼叫被錯過,現在呼籲。我猜如果它看起來像一隻鴨子,像一隻鴨子般的庸醫...... – Matt

+0

@ user2145222我自己一直在那裏。 –

0

的解決方法是不正確。 close()遞減參考計數器,並且只有當計數器恰好爲零時纔是實際的資源處理,即嘗試sqlite3_close()。在第二次通話中,櫃檯將爲負數,通話將爲空操作。

你是對的,錯誤代碼5是SQLITE_BUSY

現在要解決實際問題,請提供一些額外的詳細信息,例如您如何打開和配置數據庫以及如何開始交易。

+0

我已經添加了一些細節,但我不認爲我在做任何特別的事情。你是否說這個解決方法是錯誤的,因爲即使第二次異常沒有被拋出仍然沒有關閉? – Matt

+0

@ user2145222解決方法中的while循環毫無用處。不會引發異常,因爲引用計數不完全爲零,並且拋出的代碼根本不會被調用。更新後的問題代碼中沒有任何明顯錯誤,但可以顯示'getDatabaseAccess()'中的內容。 – laalto

+0

已添加,但它只是設置了鎖的基本代碼(我已將釋放鎖調用添加到上面的代碼中,同樣這只是調用unlock())。 – Matt