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)
|
public T Read<T>(Func<IResourceTx, T> action)
|
||||||
{
|
{
|
||||||
using var conn = Open();
|
for (int attempt = 0; ; attempt++)
|
||||||
// 显式事务让一次 Read 内的多条查询看到同一份快照
|
{
|
||||||
// 读事务延迟到首次访问时才取快照,避免并发读预检抢占 SQLite 写锁。
|
using var conn = Open();
|
||||||
using var tx = conn.BeginTransaction(deferred: true);
|
// 显式事务让一次 Read 内的多条查询看到同一份快照
|
||||||
return action(new SqliteTx(conn));
|
// 读事务延迟到首次访问时才取快照,避免并发读预检抢占 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)
|
public T Write<T>(Func<IResourceTx, T> action)
|
||||||
|
|||||||
Reference in new issue
Block a user