2.1 Четене без ангажимент
„Нивото на изолация на транзакциите“ се отнася до степента на защита, осигурена от вътрешните механизми на СУБД (тоест, не изискващи специално програмиране) от всички or някои от горните видове несъответствия в данните, които възникват по време на паралелно изпълнение на транзакции. Стандартът SQL-92 дефинира скала от четири нива на изолация:
- Прочетете без ангажименти
- Прочетете ангажирани
- Повторно четене
- Може да се сериализира
Първият от тях е най-слабият, последният е най-силен, всеки следващ включва всички предишни.
Най-ниското (първо) ниво на изолация. Ако няколко паралелни транзакции се опитат да променят един и същ ред на table, тогава последният ред ще има стойност, определена от целия набор от успешно завършени транзакции. В този случай е възможно да се четат не само логически непоследователни данни, но и данни, чиито промени все още не са записани.
Типичен начин за прилагане на това ниво на изолация е да се заключват данни, докато се изпълнява командата за промяна, което гарантира, че командите за модификация на едни и същи редове, изпълнявани паралелно, действително се изпълняват последователно и нито една от промените не се губи. Транзакциите само за четене никога не се блокират под това ниво на изолация.
2.2 Извършено четене
Повечето индустриални СУБД, по-специално Microsoft SQL Server, PostgreSQL и Oracle, използват това ниво по подразбиране. На това ниво се осигурява защита срещу чернова, „мръсно“ четене, но по време на операцията на една транзакция друга може да бъде успешно завършена и напequalsите от нея промени са фиксирани. В резултат на това първата транзакция ще работи с различен набор от данни.
Изпълнението на пълно четене може да се основава на един от двата подхода: блокиране or създаване на версии.
Блокиране на четими и променливи данни.
Състои се във факта, че записващата транзакция блокира променливи данни за транзакции за четене, работещи на ниво четене or по-високо, докато не завърши, като по този начин предотвратява "мръсното" четене, а данните, заключени от транзакцията за четене, се освобождават веднага след приключване на операцията SELECT
(по този начин може да възникне ситуация на „неповтарящо се четене“ при дадено ниво на изолация).
Запазване на множество версии на редове, които се променят паралелно.
Всеки път, когато ред се промени, СУБД създава нова version на този ред, с която транзакцията, която е променила данните, продължава да работи, докато всяка друга транзакция за „четене“ връща последната ангажирана version. Предимството на този подход е, че е по-бърз, защото предотвратява блокирането. Въпреки това, той изисква, в сравнение с първия, значително по-голяма консумация на RAM, която се изразходва за съхраняване на версии на редове.
Освен това, когато множество транзакции променят данни успоредно, това може да създаде ситуация, при която няколко едновременни транзакции правят непоследователни промени в едни и същи данни (тъй като няма заключвания, нищо няма да попречи на това да се случи). Тогава транзакцията, която се ангажира първа, ще запази промените си в основната база данни, а останалите паралелни транзакции ще бъдат невъзможни за извършване (тъй като това ще доведе до загуба на актуализацията на първата транзакция). Единственото нещо, което СУБД може да направи в такава ситуация, е да върне обратно останалите транзакции и да издаде съобщение за грешка „Записът вече е променен“.
Конкретен метод за внедряване се избира от разработчиците на СУБД и в някои случаи може да бъде персонализиран. Така че по подразбиране MS SQL използва ключалки, но (във version 2005 и по-нова) при настройване на READ_COMMITTED_SNAPSHOT
параметъра на базата данни той превключва към стратегията за управление на версиите, Oracle първоначално работи само според схемата с версии. В Informix можете да предотвратите конфликти между транзакциите за четене и запис, като зададете опция за конфигурация USELASTCOMMITTED
(от version 11.1), която кара транзакцията за четене да получава най-новите ангажирани данни.
2.3 Повторно четене
Нивото, на което транзакцията за четене „не вижда“ се променя на данните, които е прочела преди това. В същото време никоя друга транзакция не може да промени данните, прочетени от текущата транзакция, докато не приключи.
Заключванията в споделен режим се прилагат към всички данни, прочетени от която и да е инструкция в транзакция и се задържат, докато транзакцията приключи. Това не позволява на други транзакции да променят редове, които са бor прочетени от чакащата транзакция. Други транзакции обаче могат да вмъкват нови редове, които съответстват на условията за търсене на инструкции, съдържащи се в текущата транзакция. Когато операторът се рестартира от текущата транзакция, ще бъдат извлечени нови редове, което ще доведе до фантомно четене.
Като се има предвид, че споделените заключвания се държат до края на транзакцията, instead of да се освобождават в края на всеки оператор, степента на едновременност е по-ниска от нивото на изолация READ COMMITTED
. Следователно обикновено не се препоръчва използването на това и по-високи нива на транзакция без необходимост.
2.4 Може да се сериализира
Най-високо ниво на изолация; транзакциите са напълно изолирани една от друга, всяка се изпълнява така, сякаш няма паралелни транзакции. Само на това ниво едновременните транзакции не са обект на ефекта на "фантомно четене".
2.5 Поддръжка за изолиране на транзакции в реални СУБД
Транзакционните СУБД не винаги поддържат всичките четири нива и могат да въведат допълнителни. Има и различни нюанси при осигуряването на изолация.
Така че по принцип Oracle не поддържа нулевото ниво, тъй като неговото изпълнение на транзакции изключва „мръсни четения“ и формално не позволява настройка на нивото на повтарящо се четене, тоест поддържа само (по подразбиране) Read committed
и Serializable
. В същото време, на ниво отделни команди, това всъщност гарантира повторяемост на четене (ако команда SELECT
в първата транзакция избира набор от редове от базата данни и в този момент паралелна втора транзакция променя някои от тези редове, тогава резултатният набор, получен от първата транзакция, ще съдържа непроменени редове, сякаш не е имало втора транзакция). Oracle също поддържа така наречените READ-ONLY
транзакции, които съответстват на Serializable
, но не могат да променят самите данни.
А Microsoft SQL Server поддържа и четирите стандартни нива на изолация на транзакциите и допълнително нивото SNAPSHOT, на което транзакцията вижда състоянието на данните, което е било ангажирано преди да бъде стартирана, Howто и промените, напequalsи от самата нея, тоест тя се държи като ако получи при стартиране, моментна снимка на данните от DB и работи с нея. Разликата от Serialized е, че не се използват заключвания, но в резултат на това извършването на промени може да не е възможно, ако едновременна транзакция е променила същите данни преди това; в този случай втората транзакция, когато се опита да изпълни, COMMIT
ще изведе съобщение за грешка и ще бъде отменена.
GO TO FULL VERSION