【问题标题】:Database locked exception数据库锁定异常
【发布时间】:2012-06-26 18:11:19
【问题描述】:

我在我的应用程序中创建了一个包含 5 个表的数据库。我的数据库正在从不同的线程更新。当我看到日志时,如果数据库已经打开,我可以看到在打开数据库时存在数据库锁定异常。

我的一位朋友建议我始终使用内容提供程序来避免这个问题。根据他的说法,内容提供商自己管理并发问题?

如果我们不想将数据共享给其他应用程序,使用内容提供程序是否是一种好习惯?

【问题讨论】:

    标签: android


    【解决方案1】:

    我认为在大多数情况下使用读写锁就足够了。

    假设你写了以下内容,

    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    public class MyDatabase extends SQLiteOpenHelper
    {
        private static final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
    
        private static void beginReadLock()
        {
            rwLock.readLock().lock();
        }
    
        private static void endReadLock()
        {
            rwLock.readLock().unlock();
        }
    
        private static void beginWriteLock()
        {
            rwLock.writeLock().lock();
        }
    
        private static void endWriteLock()
        {
            rwLock.writeLock().unlock();
        }
    

    那么你可以像下面这样完成你的任务。

        public static void doSomething()
        {
            SQLiteDatabase sldb = null;
    
            try
            {
                beginReadLock();
    
                MyDatabase mydb = new MyDatabase();
                sldb = mldb.getReadableDatabase();
                ......
            }
            catch (Exception e)
            {
                ......
            }
            finally
            {
                if (sldb != null)
                {
                    try
                    {
                        sldb.close();
                    }
                    catch (Exception e) {}
                }
    
                endReadLock();
            }
        }
    

    beginReadLock()endReadLock() 括起读取操作。同样,用 beginWriteLock()endWriteLock() 括起来写操作。

    几个月前,通过上述解决方案,我可以解决我自己的数据库锁定问题,即多个线程同时尝试读取/写入打开数据库。

    【讨论】:

    • 嘿@Takahiko Kawasaki:我试过你的解决方案,但我仍然面临这个问题。不知道可能出了什么问题。
    • 应该在databaseHelper类的同一个对象上完成
    【解决方案2】:

    问题是您使用多个数据库连接到您的数据库。因此,多个线程尝试同时更新您的表,并且所有这些线程都与您的数据库有不同的连接。

    为避免在所有线程中出现此问题,您需要使用与数据库的相同连接,即所有线程应使用与数据库的相同连接(由 SQLiteDabase 对象表示)。

    此外,由于 sqlite 文件上有一个文件块,因此使用多个线程不会提高数据库升级的性能(最好只使用一个线程来处理数据库)。如果你想使用多个线程,你应该使用同一个数据库连接,在这种情况下,Android 将管理锁。

    您可以在此处找到有关此问题的讨论:http://touchlabblog.tumblr.com/post/24474398246/android-sqlite-locking 和此处:What are the best practices for SQLite on Android?

    【讨论】:

      猜你喜欢
      • 2013-07-09
      • 1970-01-01
      • 2023-03-03
      • 2017-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多