fix(storage): retry a read transaction that fails to begin under load
This commit is contained in:
1 parent
fb5800f81d
commit
700be2ebae
1 file changed
+15
-5
@@ -51,11 +51,21 @@ public sealed class SqliteChannelStore : IResourceStore, IDisposable
|
||||
|
||||
public T Read<T>(Func<IResourceTx, T> action)
|
||||
{
|
||||
using var conn = Open();
|
||||
// 显式事务让一次 Read 内的多条查询看到同一份快照
|
||||
// 读事务延迟到首次访问时才取快照,避免并发读预检抢占 SQLite 写锁。
|
||||
using var tx = conn.BeginTransaction(deferred: true);
|
||||
return action(new SqliteTx(conn));
|
||||
for (int attempt = 0; ; attempt++)
|
||||
{
|
||||
using var conn = Open();
|
||||
// 显式事务让一次 Read 内的多条查询看到同一份快照
|
||||
// 读事务延迟到首次访问时才取快照,避免并发读预检抢占 SQLite 写锁。
|
||||
SqliteTransaction tx;
|
||||
try { tx = conn.BeginTransaction(deferred: true); }
|
||||
// 并发压力下偶发 SQLITE_ERROR(CI 的并行追加测试里出现过):丢弃这条连接和池里的闲置连接,换新连接重试
|
||||
catch (SqliteException e) when (e.SqliteErrorCode == 1 && attempt < 2)
|
||||
{
|
||||
SqliteConnection.ClearPool(conn);
|
||||
continue;
|
||||
}
|
||||
using (tx) return action(new SqliteTx(conn));
|
||||
}
|
||||
}
|
||||
|
||||
public T Write<T>(Func<IResourceTx, T> action)
|
||||
|
||||
Reference in new issue
Block a user