2016-03-24 2 views
1

Ниже приведен мой код, который открывает транзакцию и вставляет строку в таблицу, между тем я открываю другое соединение и запрашиваю ту же таблицу. Программа зависает в строке (*).Базовый тупик базы данных и уровень изоляции транзакции

//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 LEVEL является ReadCommitted на моей базе данных. Я ожидал count=0.

Похоже, что соединение 1 блокирует стол, так что соединение 2 не может его прочитать. Если это так, то почему существует УРОВЕНЬ ИЗОЛЯЦИИ ОПЕРАЦИЙ?

ответ

1

У вас есть первое соединение, которое открывает транзакцию, вставляет новую строку в таблицу, а не фиксирует. Он имеет любое количество и множество незакрепленных замков в этой таблице.

У вас есть второе соединение, которое пытается прочитать счет.

Да, это будет тупик (на уровне приложения, а не на уровне SQL). Эти соединения полностью не связаны (если у вас нет окружающего TransactionScope, о котором вы не упоминали), поэтому второе соединение будет заблокировано. Он не может рассчитать счет до фиксации, , потому что это ReadCommitted - это означает, что он может только читать совершил данных. До тех пор: он должен ждать.

Если вы явно хотите прочитать прошлое блокировки используйте более низкий уровень изоляции, такие как READ UNCOMMITTED, или добавить явные NOLOCK подсказку.

+0

О, я нашел https://msdn.microsoft.com/library/ms173763.aspx. Будет ли «SET READ_COMMITTED_SNAPSHOT ON» решить тупик? – Gqqnbig

+0

@LoveRight это ... не лучший способ зафиксировать тупик. IMO есть 3 * хорошие * способы исправить это: 1) выполнить подсчет по тому же соединению, что и транзакция (это даст вам новый счет); 2) реструктурировать код, чтобы вы * не делали этого * - оставив транзакцию открытой здесь очень плохой запах - но если вам нужно ждать (чтобы получить достоверное значение) - тогда * wait *; 3) если вы * должны * прочитать за замком, используйте нижнюю изоляцию; моментальный снимок может решить это, но по причинам, которые в основном кричат ​​«Я не понимаю, что происходит» - это никогда не бывает хорошо. –

+0

Я просто делаю эксперименты. благодаря – Gqqnbig

Смежные вопросы