You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Example Code:
var connection = new NpgsqlConnection(ConnectionString);
var connection2 = new NpgsqlConnection(ConnectionString);
connection.Open();
connection2.Open(); //Make sure we get a different connection, not a reused pool one.
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "create table CantTouchThis(floop integer, name varchar(10));";
cmd.ExecuteNonQuery();
}
connection.BeginTransaction(); //Seems not to actually begin a transaction
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "insert into CantTouchThis values (10, 'test');";
cmd.ExecuteNonQuery(); //Actually begins the transaction
}
connection.Close(); //Send connection back to the pool, the transaction *should* be rolled back here
using (var cmd = connection2.CreateCommand())
{
cmd.CommandText = "drop table CantTouchThis;";
cmd.ExecuteNonQuery();
}
Expected behaviour: 'connection' should perform a rollback prior to 'Close' returning.
Actual behaviour: transaction remains pending, causing a timeout, as seen: http://i.imgur.com/UemAvOb.png
It appears the problem is in NpgsqlConnector.cs : Reset(), where the "PrependInternalMessage" does not actually send the messages placed into the queue.
The text was updated successfully, but these errors were encountered:
@tastywheattasteslikechicken this was actually done intentionally, as a performance optimization. When a pooled connection is closed, rather than immediately sending a rollback (meaning a network round-trip) we prepend it to the first statement sent after the connection is reopened.
I see now that this optimization has its negative consequences... Even without your scenario (trying to drop a table currently under a transaction), I'm guessing that leaving a transaction open in the way we do might have some other problematic consequences on the PostgreSQL side (resources left in-use because the transaction is still in progress).
@Emill, I think we discussed this optimization together at some point, do you have any thoughts here? I guess we went too far here and should undo this for 3.0.5..
If you need a temporary workaround, send some useless query (SELECT 1) after calling Rollback(), that will make sure the rollback gets to the database immediately.
When a pooled connection was closed while a transaction was still in
progress, Npgsql had an optimization whereby it didn't execute a rollback
immediately, but rather prepended a rollback message for execution the
next time the connection is opened and used. This created some issues as
the transaction kept locks etc. for an indefinite time.
Removed the optimization, closing a connection now immediately sends a
rollback.
Fixes#927
(cherry picked from commit 611f390)
roji
changed the title
Closing a connection with an active transaction does not rollback transaction immediately if pooling is enabled
Closing a pooled connection with an active transaction does not rollback transaction immediately
Jan 1, 2016
friism
pushed a commit
to friism/npgsql
that referenced
this issue
Jan 11, 2016
When a pooled connection was closed while a transaction was still in
progress, Npgsql had an optimization whereby it didn't execute a rollback
immediately, but rather prepended a rollback message for execution the
next time the connection is opened and used. This created some issues as
the transaction kept locks etc. for an indefinite time.
Removed the optimization, closing a connection now immediately sends a
rollback.
Fixesnpgsql#927
Example Code:
var connection = new NpgsqlConnection(ConnectionString);
var connection2 = new NpgsqlConnection(ConnectionString);
connection.Open();
connection2.Open(); //Make sure we get a different connection, not a reused pool one.
Expected behaviour: 'connection' should perform a rollback prior to 'Close' returning.
Actual behaviour: transaction remains pending, causing a timeout, as seen: http://i.imgur.com/UemAvOb.png
It appears the problem is in NpgsqlConnector.cs : Reset(), where the "PrependInternalMessage" does not actually send the messages placed into the queue.
The text was updated successfully, but these errors were encountered: