Чтение данных sqlite при выполнении транзакции (Android)

мне нужно прочитать некоторые данные из базы данных, тем временем я загружаю некоторые данные в другой поток с транзакцией.

все мои потоки для чтения других таблиц останавливаются до завершения транзакции в другом потоке.

мне нужно иметь возможность читать информацию из базы данных, не беспокоясь о другом потоке.

Я прочитал много информации о sqlite, android...но ничего не работает, всегда мой запрос на чтение параметров блокированный.

я следовал этим советам, как говорит @KevinGalligan в этой теме (каковы наилучшие методы для SQLite на Android?) разрешение блокировок и других проблем.

1) я использую только один SQLiteOpenHelper (singleton)

2) я никогда не закрывал базу данных

Я пробовал:

запустить транзакцию с:

database.execSQL("begin immediate transaction");

или

database.beginTransactionNonExclusive();

вместо

database.beginTransaction();

не работает, запрос заблокирован.

Я читал о Wal(база данных.enableWriteAheadLogging ()), но мне нужно поддерживать api 9.

любые другие решения для чтения между тем транзакция обновляет некоторые таблицы? Мне все равно, если моя информация устарела, важнее не блокировать мои потоки.

4 ответов


я решил проблему.

я следовал этим шагам.

для решения проблемы блокировки базы данных и многопоточного использования базы данных (на основе http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection):

1) я использую только один SQLiteOpenHelper (singleton).

2) Никогда не закрывайте базу данных.

чтобы иметь возможность читать и писать, не блокируя мои запросы, я следовал этому шаги:

использовать database.enableWriteAheadLogging() (только api>=11), моя ошибка заключалась в том, что вы должны включить этот режим во всех соединениях, а не только в вашей транзакции или ваших записях, поэтому я добавил следующий код в свой класс openHelper в методе "onOpen". На основе этого кода Mozilla в github (https://github.com/mozilla/mozilla-central/blob/9f2b8297b99d9d28038256b4f92a5aaa941749f1/mobile/android/base/db/TabsProvider.java).

@SuppressLint("NewApi")
    @Override
     public void onOpen(SQLiteDatabase db) {

         // From Honeycomb on, it's possible to run several db
         // commands in parallel using multiple connections.
         if (Build.VERSION.SDK_INT >= 11) {
             try{
                 db.enableWriteAheadLogging();
             }catch(Exception e){
                 Log.e("onOpen", e.getMessage());
             }
         }
     }

С этим решением я решил свою проблему блокировки чтения во время обновления некоторых таблиц, но другие обновления также блокируются. Если вы хотите решить эту последнюю проблему, как говорит @commonsware:

используя yieldIfContendedSafely() внутри вашей транзакции вы дадите другим потокам возможность работать с базой данных. Я не видел никакой разницы, используя этот метод с beginTransaction или beginTransactionNonExclusive.

другое интересное чтение: каковы лучшие практики для SQLite на Android?


Я думаю, что вы должны использовать концепцию синхронизации, чтобы избежать проблем, с которыми вы сталкиваетесь.


SQLite в android это не потокобезопасно, база данных будет заблокирована при выполнении операции, что означает, что вы должны убедиться, что операция базы данных выполняется только в одном потоке, и вызвать базу данных.setTransactionSuccessful (); для завершения транзакции после завершения работы.


Если ваша работа по загрузке данных - это не просто одна массивная транзакция SQL,использовать yieldIfContendedSafely() чтобы позволить другим потокам читать базу данных в разных точках. Так, например, если вы выполняете какую-то массовую загрузку данных, и вы выполняете транзакцию каждые 100 вставок, вызовите yieldIfContendedSafely() на каждом проходе цикла every-100-inserts, чтобы дать другим потокам возможность работать с базой данных.