.NET 8 Azure Functions迁移SQLite遇SQLite Error 5数据库锁定问题求助
我有一个基于.NET 8的Azure Functions应用,原本用SQL Server存储数据,为了提升访问速度、降低成本,正在迁移到SQLite。本地运行一切正常,但部署到Azure Functions后,执行SELECT查询时出现如下错误:
2025-06-05T16:28:16Z [Error] An exception occurred while iterating over the results of a query for context type 'Infrastructure.Persistence.MLTrainingContext'. Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 5: 'database is locked'. at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db) at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements()+MoveNext() at Microsoft.Data.Sqlite.SqliteCommand.GetStatements()+MoveNext() at Microsoft.Data.Sqlite.SqliteDataReader.NextResult() at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior) at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__21_0(DbContext _, Enumerator enumerator) at Microsoft.EntityFrameworkCore.Storage.NonRetryingExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
我确认当前只有该应用访问DbContext及数据库,且无并发函数同时访问数据库,请问问题原因是什么?
DbContext代码如下:
using Domain; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; namespace Infrastructure.Persistence { public class MLTrainingContext : DbContext { public DbSet<Model> Models { get; set; } public DbSet<Library> Libraries { get; set; } public DbSet<DestinationRoutingRule> DestinationRoutingRules { get; set; } private readonly string _connString; public MLTrainingContext(DbContextOptions<MLTrainingContext> options) : base(options) { _connString = Utils.GetDBConnectionString(); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Model>().HasMany(m => m.Libraries) .WithMany(l => l.Models); } protected override void OnConfiguring(DbContextOptionsBuilder options) { options.UseSqlite(_connString, x => x.MigrationsAssembly("Infrastructure")); options.ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.NonTransactionalMigrationOperationWarning)); } public void Save() { lock (this) { SaveChanges(); } } } }
问题原因分析
Azure Functions文件系统限制:Azure Functions默认使用的远程共享存储(如wwwroot目录),其文件锁机制与本地文件系统差异极大,SQLite对文件系统一致性要求高,共享存储的延迟或隐性操作(如系统快照、后台扫描)会干扰SQLite的文件锁逻辑,即使无业务并发也可能触发锁超时。
DbContext配置冲突:构造函数接收了
DbContextOptions<MLTrainingContext>注入参数,但OnConfiguring又手动调用UseSqlite覆盖配置,这种双重配置会导致EF Core连接生命周期异常,可能创建多个独立连接池,引发锁冲突。锁机制无效:
Save方法里的lock (this)仅对当前DbContext实例生效,若Azure Functions将DbContext配置为瞬态(Transient)或范围(Scoped),每次请求都会创建新实例,锁完全无法起到全局互斥作用,反而可能加剧多实例操作数据库的锁竞争。连接未及时释放:若查询结果未被完整枚举(如未调用
ToList()就提前释放DbContext),或请求结束后DbContext未被正确Dispose,会导致SQLite连接长时间持有数据库文件锁,后续查询触发锁等待超时。
内容的提问来源于stack exchange,提问作者Justin Lyon

