Error on Sqlite during multithread operations

See original GitHub issue

Bug

I was upgrading some projects to .NET 5 and I’m facing some issues with SQLite due race condition errors:

'SQLite Error 5: 'unable to delete/modify user-function due to active statements'.'

Or (sometimes)

Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct

Context

The project uses a single connection on a multithread environment and during a long query execution in one thread, the other ones will fail with the error addressed above.

This behavior does not happen on version 3.1.12.

How to reproduce

To reproduce the error, I created a unit test called SqliteMultithreadTests (https://github.com/vitorelli/efcore/blob/issue-multithread-con/test/EFCore.Sqlite.Tests/SqliteMultithreadTests.cs)

Stack traces

Message:
---- Microsoft.Data.Sqlite.SqliteException : SQLite Error 5: 'unable to delete/modify user-function due to active statements'.
----- Inner Stack Trace #1 (Microsoft.Data.Sqlite.SqliteException) -----
    SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db) ligne 86
    SqliteConnection.CreateFunctionCore[TState,TResult](String name, Int32 arity, TState state, Func`3 function, Boolean isDeterministic) ligne 730
    SqliteConnection.CreateFunction[T1,T2,TResult](String name, Func`3 function, Boolean isDeterministic) ligne 48
    SqliteRelationalConnection.InitializeDbConnection(DbConnection connection) ligne 121
    SqliteRelationalConnection.ctor(RelationalConnectionDependencies dependencies, IRawSqlCommandBuilder rawSqlCommandBuilder, IDiagnosticsLogger`1 logger) ligne 71
    RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
    RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
    CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
    <>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
    ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
    ServiceProviderEngineScope.GetService(Type serviceType)
    ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
    <>c.<AddEntityFrameworkSqlite>b__0_0(IServiceProvider p) ligne 64
    CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
    CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
    CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
    CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
    CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
    CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
    CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
    CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
    <>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
    ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
    ServiceProviderEngineScope.GetService(Type serviceType)
    ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
    ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
    DbContext.get_DbContextDependencies() ligne 394
    DbContext.get_InternalServiceProvider() ligne 376
    IServiceProvider>.get_Instance() ligne 1802
    InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor) ligne 33
    AccessorExtensions.GetService[TService](IInfrastructure`1 accessor) ligne 46
    DatabaseFacade.get_Dependencies() ligne 40
    IDatabaseFacadeDependenciesAccessor.get_Dependencies() ligne 288
    RelationalDatabaseFacadeExtensions.GetFacadeDependencies(DatabaseFacade databaseFacade) ligne 682
    RelationalDatabaseFacadeExtensions.GetDbConnection(DatabaseFacade databaseFacade) ligne 416
    <>c__DisplayClass0_0.<IsMultithreadSupported_when_using_SingleConnection>b__2() ligne 48
    Task.InnerInvoke()

How to fix

The method SqliteRelationalConnection.InitializeDbConnection should be called once on single connection. A possible solution is to apply the folowing code:

https://github.com/vitorelli/efcore/blob/issue-multithread-con/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs#L69

Include provider and version information

EF Core version: 5.0.3 Database provider: Microsoft.EntityFrameworkCore.Sqlite Target framework: .NET 5.0.3 Operating system: Windows 10 PRO IDE: Visual Studio Code

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
rojicommented, Mar 13, 2021

#13837 tracks adding connection pooling to sqlite, which should mitigate the perf issue with opening encrypted databases.

0reactions
vitorellicommented, Mar 15, 2021

Thanks @roji and @ajcvickers, I will keep tracking the issue #13837

Read more comments on GitHub >

github_iconTop Results From Across the Web

Error using SQLite Swift4: multi-threaded access to ...
1 Answer 1 ... "Multi-thread. In this mode, SQLite can be safely used by multiple threads provided that no single database connection is...
Read more >
Using SQLite In Multi-Threaded Applications
In this mode, SQLite can be safely used by multiple threads provided that no single database connection is used simultaneously in two or...
Read more >
SQLITE3 and multithreading - errors, mutexes, serialization ...
I am using an SQLITE3 dbo backend in a multi-threaded app, such that: a main, headless thread has its own database connection taken...
Read more >
Possible multi-threading issue in Roslyn's sqlite usage
Multi-thread mode says: Multi-thread. In this mode, SQLite can be safely used by multiple threads provided that no single database connection is ...
Read more >
Record locking in Aurelius
I have multiple threads running and accessing tables. I keep getting "table locked" errors from SQLite (using the object manager) and would ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found