问题
The following is my code that opens a transaction and inserts a row to the table, meanwhile I open another connection and query the same table. The program hangs up at Line (*).
//TestTable is empty.
using (connection1 == new SqlConnection(OpConsoleLib.std.CONNECTIONSTRING)) {
connection1.Open();
SqlCommand cmd = new SqlCommand("Insert into TestTable values('hello')", connection1);
cmd.Transaction = connection1.BeginTransaction();
cmd.ExecuteNonQuery()
using (SqlConnection connection2 = new SqlConnection(OpConsoleLib.std.CONNECTIONSTRING)) {
connection2.Open();
SqlCommand cmd2 = new SqlCommand("Select count(*) from TestTable where name='hello'", connection2); //(*)
int count=Convert.ToInt32(cmd2.ExecuteScalar());
}
cmd.Transaction.Commit();
}
TRANSACTION ISOLATION LEVEL is ReadCommitted
on my database. I was expecting count=0
.
It looks like connection 1 locks the table so connection 2 cannot read it. If that's true, why is there TRANSACTION ISOLATION LEVEL?
回答1:
You have a first connection that opens a transaction, inserts a new row into a table, and doesn't commit. It has any number and variety of non-shareable locks on that table.
You then have a second connection that attempts to read the count.
Yes, this will deadlock (at the app layer, not at the SQL layer). Those connections are completely unrelated (unless you have an ambient TransactionScope
that you haven't mentioned), so the second connection will be blocked. It can't tell you the count until the commit, because it is ReadCommitted
- which means it can only read committed data. Until then: it needs to wait.
If you explicitly want to read past the lock, use a lower isolation level such as READ UNCOMMITTED
, or add an explicit NOLOCK
hint.
回答2:
That's defined behaviour of READ_COMMITED isolaction level.
Have a look at the Wikipedia article: https://en.wikipedia.org/wiki/Isolation_(database_systems)#Read_committed
来源:https://stackoverflow.com/questions/36211341/database-deadlock-and-transaction-isolation-level