2011-10-28 57 views
27

我收到以下错误。那么如何解锁我的数据库呢?Android数据库锁定

10-28 08:43:26.510: ERROR/AndroidRuntime(881): FATAL EXCEPTION: Thread-11 
10-28 08:43:26.510: ERROR/AndroidRuntime(881): android.database.sqlite.SQLiteDatabaseLockedException: database is locked 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteDatabase.dbopen(Native Method) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:742) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at com.aa.me.vianet.dbAdapter.DbAdapter.open(DbAdapter.java:25) 
10-28 08:43:26.510: ERROR/AndroidRuntime(881):  at com.aa.me.vianet.services.NotificationManagerThread.run(NotificationManagerThread.java:49) 
+0

1.确保您只在同一个文件上使用单个SQLiteOpenHelper。 2。确保一次只有一个线程正在使用您的SQLiteDatabase。 – Jens

回答

32

我想你已经忘记关闭数据库,或当你试图写它另一个线程写入数据库。 SQLite在写入数据库时​​会锁定数据库,以防止另一个实体尝试同时写入同一数据库时发生损坏。 Android的,将只显示在日志猫错误,你提供的将只是忘记了查询...

所以,我建议:

  • 你只从一个SQLOpenHelper
  • 您访问数据库请确保您关闭数据库助手的所有实例,一旦你与他们完成
  • 你要确保你总是最后交易与endTransaction()如果你还没有设置他们获得成功(也就是说,如果你想EM滚”回去),如果你使用交易
  • 你可以尝试使用OrmLite,我没有使用它,但我听说过其他人在这里狂喜。
+5

我写了OrmLite的原始端口到Android。你的第一个建议,只使用一个帮手,是很好的建议。你的第二个与你的第一个矛盾。 “关闭数据库帮助程序的所有实例”意味着超过1.仅使用一个,始终!另外,你不需要关闭你的助手连接。请看我的答案。最初,我为OrmLite编写了复杂的引用计数代码,以帮助保持一个助手的存活状态,并在完成后关闭它,但事实证明,Sqlite“连接”只是文件句柄。系统将在转储过程时为您关闭它们。 –

+0

嘿凯文,这是否意味着你永远不必关闭你的数据库处理程序? –

+2

是的。我知道这听起来很糟糕。处理程序只是一个文件句柄。当过程死亡时它将关闭。 SQLite不会破坏自己。至于只在logcat中显示错误,对于“插入”而言是如此,但对于其他方法而言则如此。这就是为什么你应该总是调用“insertOrThrow”。 –

7

出现这种情况的原因是因为你只能有一次一个连接到数据库的打开(这是为了防止竞争条件修改数据库时)。我猜你多次连接到不同线程的数据库?解决这个问题的最简单方法就是为您的数据库创建一个ContentProvider前端。这将能够处理来自多个线程的查询。

欲了解更多信息,结账这个blogpost

+0

blogpost的链接中断,新的链接又破了http://www.touchlab.co/blog/android-sqlite-locking/ – pengwang

+0
+0

@christophercotton似乎再次为我工作。 –

11

使用您整个应用程序的单一连接。在这里看到:

http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection

+0

你能修复这个链接吗?如何处理多线程访问与单一连接? – Michael

+0

@迈克尔固定链接! –

+0

我用这种方法,但不工作在我的情况请看看我的问题[链接在这里...](http://stackoverflow.com/questions/13859840/application-crashes-on-installation -with-error-sqlite3-exec-failed-set-sync) – MobileEvangelist

0

我有一个类似的错误。我的问题是,我不小心给了两个助手类的数据库相同的名称,所以他们最终同时访问了同一个数据库。所以确保你没有使用多个helper类访问单个数据库。

2

我有同样的问题,请尝试使用此

db.beginTransactionNonExclusive(); 
    try { 
     //do some insertions or whatever you need 
     db.setTransactionSuccessful(); 
    } finally { 
     db.endTransaction(); 
    } 

我试着用db.beginTransaction但它锁定了BD

0

我有同样的问题,因为我试图通过访问我的数据库ContentResolver虽然我已经有一个直接打开SQLiteDatabase连接(交易所需)。

我通过更改我的代码的顺序来解决它,所以ContentResolver的东西是在我的直接SQLiteDatabase连接打开之前完成的。

我还删除了一些代码,所以我不再接近我的直接SQLiteDatabase

这是值得一读this answer,因为它提供了很多其他有用的指导。