question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Npgsql exceptions on simultaneous reading

See original GitHub issue

Issue

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:closed
  • Created 6 years ago
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
sdanylivcommented, Mar 8, 2018

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.

0reactions
MaceWinducommented, Apr 7, 2018

Closing answered/non-actionable issues. Feel free to reopen/continue discussion if it wasn’t anwsered.

Read more comments on GitHub >

github_iconTop 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 >

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