Блокировка базы данных или таблицы в sqlite (Android) - PullRequest
1 голос
/ 04 августа 2011

Вот моя проблема:

У меня есть таблица со столбцами: ID, VALUE и SYNCHRONICED. Последний является флагом, который указывает, была ли строка отправлена ​​на сервер с момента последнего обновления. У меня запущен поток, который может получить доступ к базе данных

И моя проблема возникает в этом случае использования (с 2 потоками T1 и T2:

T1-->Start_Send-->Query_Values-->Send_to_server-->wait_answer-->sync=1_for_sent_rows
T2------------------------->Update_a_row_sent

В этот момент T1 отметил с sync = 1 значение, обновленное T2.

Есть ли способ избежать этой проблемы?

  • Методы для запроса и обновления различны, поэтому нельзя использовать синхронизированный в методе.
  • Нет проблем, если T2 блокируется до окончания T1

Спасибо

Ответы [ 2 ]

8 голосов
/ 04 августа 2011

Поскольку вы спросили, как заблокировать базу данных / таблицу на Android, вы можете использовать SQLiteDatabase.beginTransaction () для достижения этого:

Из документов Android http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html:

public void beginTransaction ()

С: Уровень API 1

Начинает транзакцию в режиме EXCLUSIVE.

А из sqlite 3 http://www.sqlite.org/lang_transaction.html

После НАЧАЛА ИСКЛЮЧЕНИЯ никакое другое соединение с базой данных, кроме read_uncommitted соединения смогут читать базу данных и нет другое соединение без исключения сможет записать базу данных до завершения транзакции.

beginTransaction запускает транзакцию и ставит вашу базу данных в монопольную блокировку, поэтому при запуске T1 select блокирует T2 от обновления строк, пока T1 не вызовет db.endTransaction ().

public yourMethod() {
    db.beginTransaction();

    //do whatever you want with db;

    db.setTransactionSuccessful(); 
    db.endTransaction();
}
2 голосов
/ 04 августа 2011

Допустим, SYNCHRONICED равно 0, когда запись вставлена ​​или обновлена, 1, когда запись отправлена ​​на сервер, и 2, когда сервер подтвердил синхронизацию.

Поток T1 должен выполнить:

BEGIN;
SELECT ID, VALUE FROM TAB WHERE SYNCHRONICED = 0;
UPDATE TAB SET SYNCHRONICED = 1 WHERE SYNCHRONICED = 0;
COMMIT;

Оператор select дает записи для отправки на сервер.

Теперь любой insert или update в TAB должен установить SYNCHRONICED = 0;

Когда сервер отвечает ack,

UPDATE TAB SET SYNCHRONICED = 2 WHERE SYNCHRONICED = 1;

Это не повлияет на какие-либо записи, обновленные или вставленные, поскольку их SYNCHRONICED равно 0.

...