【问题标题】:Lock a database or table in sqlite (Android)在 sqlite (Android) 中锁定数据库或表
【发布时间】:2011-08-03 23:34:05
【问题描述】:

这是我的问题:

我有一个包含以下列的表: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 已将 T2 更新的值标记为 sync=1。

有没有办法避免这个问题?

  • 查询和更新的方法不同,所以不能在方法上使用同步。
  • 如果 T2 被阻塞直到 T1 结束也没问题

谢谢

【问题讨论】:

  • 您能否扩展一下 The methods for query and update are diferent so cant use synchronized at the method. 我们希望他们有所不同,但您的意思是他们属于不同的班级吗?

标签: android sql sqlite thread-safety


【解决方案1】:

由于您询问如何在 android 上锁定数据库/表,您可以使用 SQLiteDatabase.beginTransaction() 来实现:

来自安卓文档http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html

public void beginTransaction()

自:API 级别 1

以独占模式开始交易。

从 sqlite 3 http://www.sqlite.org/lang_transaction.html

在 BEGIN EXCLUSIVE 之后,没有其他数据库连接,除了 read_uncommitted 连接将能够读取数据库并且没有 其他连接无异常就能写数据库 直到交易完成。

beginTransaction 启动一个事务并将您的数据库置于排他锁中,因此当 T1 select 运行时,它会阻止 T2 更新行,直到 T1 调用 db.endTransaction()。

public yourMethod() {
    db.beginTransaction();

    //do whatever you want with db;

    db.setTransactionSuccessful(); 
    db.endTransaction();
}

【讨论】:

  • 感谢您的两个答案,但考虑到向服务器提交请愿书可能需要很长时间,最好不要阻止数据库。再次感谢
【解决方案2】:

假设SYNCHRONICED 在插入或更新记录时为 0,在记录发送到服务器时为 1,在服务器确认同步时为 2。

T1 线程应该这样做:

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

select 语句将记录发送到服务器。

现在任何insertupdate 到TAB 都应该设置SYNCHRONICED = 0;

当服务器响应ack时,

UPDATE TAB SET SYNCHRONICED = 2 WHERE SYNCHRONICED = 1;

这不会影响任何更新或插入的记录,因为它们的 SYNCHRONICED 为 0。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-07
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    相关资源
    最近更新 更多