Npgsql exceptions on simultaneous reading
See original GitHub issueIssue
I am trying to read PostgreSQL tables from different threads simultaneously. If Thread1 reads Table1, Thread2 reads Table1 and Thread3 reads Table2, I get exceptions (occasionaly, not always).
Steps to reproduce
Simplified example:
var count = ... ; // quite big: each query is long running, queries are likely to overlap with each other
using (var db = new Db()) // inherits LinqToDB.Data.DataConnection, is generated by t4 template
{
ThreadPool.QueueUserWorkItem(state => db.Table1.Take(count).ToList());
ThreadPool.QueueUserWorkItem(state => db.Table1.Take(count).ToList());
ThreadPool.QueueUserWorkItem(state => db.Table2.Take(count).ToList());
};
Sometimes Npgsql throws “System.InvalidOperationException: An operation is already in progress”:
System.InvalidOperationException: An operation is already in progress.
in Npgsql.NpgsqlConnector.StartUserAction(ConnectorState newState)
in Npgsql.NpgsqlCommand.ExecuteDbDataReaderInternal(CommandBehavior behavior)
in Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
in System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
in LinqToDB.Data.DataConnection.ExecuteReader(CommandBehavior commandBehavior) in c:\projects\linq2db\Source\Data\DataConnection.cs:line 1038
in LinqToDB.Data.DataConnection.QueryRunner.ExecuteReader() in c:\projects\linq2db\Source\Data\DataConnection.QueryRunner.cs:line 428
in LinqToDB.Linq.QueryRunner.<ExecuteQuery>d__2b`1.MoveNext() in c:\projects\linq2db\Source\Linq\QueryRunner.cs:line 327
in System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
in System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
in TestConsole.Program.<>c__DisplayClass0_1.<Main>b__3(Object state) in C:\Code2\MeterCollector\TestConsole\Program.cs:line 95
in System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
in System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
in System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
in System.Threading.ThreadPoolWorkQueue.Dispatch()
in System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
I suppose it’s caused by simultaneous access to the same table from one DataConnection. Let’s try to use different DataConnection instances:
var count = ... ; // quite big: each query is long running, queries are likely to overlap with each other
using (var db1 = new Db())
using (var db2 = new Db()) // inherits LinqToDB.Data.DataConnection, is generated by t4 template
{
ThreadPool.QueueUserWorkItem(state => db1.Table1.Take(count).ToList());
ThreadPool.QueueUserWorkItem(state => db2.Table1.Take(count).ToList());
ThreadPool.QueueUserWorkItem(state => db1.Table2.Take(count).ToList());
};
In this case Npgsql throws (sometimes) another exception:
System.Exception: Internal Npgsql error, please report: acquired both locks and connector is in state Connecting
in Npgsql.NpgsqlConnector.StartUserAction(ConnectorState newState)
in Npgsql.NpgsqlCommand.ExecuteDbDataReaderInternal(CommandBehavior behavior)
in Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
in System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
in LinqToDB.Data.DataConnection.ExecuteReader(CommandBehavior commandBehavior) in c:\projects\linq2db\Source\Data\DataConnection.cs:line 1038
in LinqToDB.Data.DataConnection.QueryRunner.ExecuteReader() in c:\projects\linq2db\Source\Data\DataConnection.QueryRunner.cs:line 428
in LinqToDB.Linq.QueryRunner.<ExecuteQuery>d__2b`1.MoveNext() in c:\projects\linq2db\Source\Linq\QueryRunner.cs:line 327
in System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
in System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
in TestConsole.Program.<>c__DisplayClass0_1.<Main>b__3(Object state) in C:\Code2\MeterCollector\TestConsole\Program.cs:line 87
in System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
in System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
in System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
in System.Threading.ThreadPoolWorkQueue.Dispatch()
in System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
Environment details
linq2db version: 1.9.0
Database Server: PostgreSQL 9.6.3
Database Provider: Npgsql 3.1.6
Operating system: Windows 10
Framework version: .NET Framework 4.6.1
Issue Analytics
- State:
- Created 6 years ago
- Comments:6 (5 by maintainers)
Top Results From Across the Web
Npgsql Exception while reading from stream, Postgres
All I am doing is SELECTs. Here is the stack trace: Exception while reading from stream at Npgsql.ReadBuffer.Ensure(Int32 count, Boolean ...
Read more >Npgsql Basic Usage
PostgreSQL doesn't support nested or concurrent transactions - only one transaction may be in progress at any given moment (starting a transaction while...
Read more >PostgreSQL: Documentation: 15: 13.2. Transaction Isolation
The Repeatable Read isolation level only sees data committed before the transaction began; it never sees either uncommitted data or changes committed during ......
Read more >Concurrent transactions result in race condition with ...
When a transaction uses this isolation level, a SELECT query (without a FOR UPDATE / SHARE clause) sees only data committed before the...
Read more >MVCC in PostgreSQL — 1. Isolation - Postgres Professional
All other operations are performed simultaneously: write transactions never lock read-only transactions, and read-only transactions never ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Yes, the following code is thread safe. DataConnection is not thread safe object but if you create for each thread new connection - it is ok. We do not have change tracking and entities chache, so blocking is possible only on server side.
Closing answered/non-actionable issues. Feel free to reopen/continue discussion if it wasn’t anwsered.