【发布时间】:2012-02-12 18:57:30
【问题描述】:
阅读this document,它说SQLite 支持事务和嵌套事务。我想知道是否可以创建许多不同的交易。
例如:我有 2 个线程访问数据库连接,是否可以在每个线程上创建一个事务并且它们不嵌套?
【问题讨论】:
标签: android multithreading sqlite transactions
阅读this document,它说SQLite 支持事务和嵌套事务。我想知道是否可以创建许多不同的交易。
例如:我有 2 个线程访问数据库连接,是否可以在每个线程上创建一个事务并且它们不嵌套?
【问题讨论】:
标签: android multithreading sqlite transactions
Sqlite does not support nested transactions:
使用 BEGIN...COMMIT 创建的事务不嵌套。对于嵌套 事务,请使用 SAVEPOINT 和 RELEASE 命令。
我自己在使用带有 SQLiteDatabase 类的嵌套事务时遇到过死锁,因此我强烈建议您远离嵌套事务。使用您自己的锁来防止您的事务嵌套。
【讨论】:
在两个单独的线程上创建两个单独的事务不被视为“嵌套事务”。
每个线程都维护自己的数据库会话,该会话映射到 0 或 1 个数据库连接(可以从连接池中选择一个数据库连接,如果会话不再需要该连接,则将其返回给它,所以在任何时候,会话是否有连接,取决于它是否需要)。
因此,每个线程都独立于其他线程维护自己的事务状态。消息来源证实了这一点:
../Android/sdk/sources/android-23/android/database/sqlite/SQLiteDatabase.java:
// Thread-local for database sessions that belong to this database.
// Each thread has its own database session.
// INVARIANT: Immutable.
private final ThreadLocal<SQLiteSession> mThreadSession = new ThreadLocal<SQLiteSession>() {
@Override
protected SQLiteSession initialValue() {
return createSession();
}
};
../Android/sdk/sources/android-23/android/database/sqlite/SQLiteSession.java:
* <h2>About database sessions</h2>
* <p>
* Database access is always performed using a session. The session
* manages the lifecycle of transactions and database connections.
* </p><p>
...
* Consequently, each thread
* has its own session object and therefore its own transaction state independent
* of other threads.
因此,如果您有两个事务在单独的线程中进行,它们不是“嵌套”的,而是完全独立的,并且将并行运行或序列化,具体取决于所涉及事务的模式和类型(即它们是否被延迟,立即、独占以及它们是读还是写)。
但是,必须正确使用 Android SQLite 库才能实现此目的。
我有 2 个线程访问数据库连接
如果这意味着两个线程都使用同一个 SQLiteSession,(尽管我不确定如果可能的话,你如何实现这一点),那么这很可能会导致死锁。
我的设置:
如果要在线程上执行长时间运行的事务(例如,从后台线程同步导入数据),请考虑使用 db.yieldIfContended() 或 db.yieldIfContendedSafely() 以允许来自其他线程的事务(例如或在 UI 上记录更新thread) 挤进去,这样他们就不必等待长时间运行的事务完成并因此阻塞这些线程。
【讨论】: