Ответ
В .NET, при использовании TransactionScope, по умолчанию применяется уровень изоляции ReadCommitted.
Почему именно он? Это баланс между производительностью и целостностью данных. Он предотвращает чтение "грязных" данных (незафиксированных изменений других транзакций), но допускает неповторяемые чтения и фантомные чтения, что повышает параллелизм.
Пример использования по умолчанию:
using (var transaction = new TransactionScope())
{
// Операции с базой данных будут выполняться в ReadCommitted
using (var connection = new SqlConnection(connectionString))
{
// ... выполнение команд
}
transaction.Complete(); // Фиксация транзакции
}
Как изменить уровень изоляции явно:
var options = new TransactionOptions
{
IsolationLevel = IsolationLevel.Serializable // Или другой уровень
};
using (var transaction = new TransactionScope(TransactionScopeOption.Required, options))
{
// Операции с базой данных
transaction.Complete();
}
Важно: Фактический уровень изоляции также зависит от настроек и возможностей самой СУБД (SQL Server, PostgreSQL и т.д.).
Ответ 18+ 🔞
Да, ну вот, классика жанра! Сидишь ты такой, пишешь свой код, создаёшь TransactionScope и думаешь: "Ща я тут транзакцию грамотно сделаю, всё будет как у взрослых". А оно, сука, по умолчанию тебе подсовывает ReadCommitted. И ты такой: "А че так? Почему не Serializable, чтоб всё под замком было, как в банке?"
А причина, блядь, проще пареной репы. Это, типа, золотая середина. Чтоб ты не прочитал какую-нибудь хуйню, которую другая транзакция ещё даже не закоммитила — эти самые "грязные" данные. Это оно тебя защищает. Зато, сука, допускает другие аномалии — неповторяемые чтения и фантомы. Ну, потому что если всё наглухо блокировать, то производительность уподёт в пизду. База будет стоять, как вкопанная, все запросы друг дружку ждать. А так — компромисс, епта.
Вот смотри, как обычно это выглядит, даже думать не надо:
using (var transaction = new TransactionScope())
{
// Всё что тут делаешь с базой — будет под капотом в ReadCommitted
using (var connection = new SqlConnection(connectionString))
{
// ... делаешь свои делишки
}
transaction.Complete(); // И вот тут говоришь "ок, сохраняем"
}
Всё просто и работает. Но если тебе, чувак, вдруг приспичило контролировать всё жёстко, потому что у тебя там хитрая логика и фантомные чтения как нож по сердцу — то можно и явно указать. Не хочешь ReadCommitted? Ну так скажи!
var options = new TransactionOptions
{
IsolationLevel = IsolationLevel.Serializable // Или там Snapshot, или RepeatableRead — выбирай, не стесняйся
};
using (var transaction = new TransactionScope(TransactionScopeOption.Required, options))
{
// Теперь тут твои правила, блядь
transaction.Complete();
}
Но вот тут, внимание, важный момент, чтоб потом не орать "почему не работает!". Эта вся твоя возня с уровнями изоляции — это, по сути, просто намёк для .NET. А реально-то, сука, всё решает сама база данных — SQL Server, PostgreSQL или кто у тебя там. Если она твой выбранный уровень не поддерживает или настроена по-своему, то может быть лёгкое недопонимание, вплоть до "я вообще игнорирую твои потуги". Так что всегда смотри, что твоя СУБД может, а что нет. А то получится как всегда: думаешь, что ты король базы данных, а на деле — просто местный паяц.