1.1 Въведение
И сега започва забавлението - теорията за това How работят транзакциите. Как да поддържате работата на системата, когато променяте едни и същи данни в различни нишки? Или искате да изпълните една транзакция в друга? Ще започнем да търсим отговори на тези въпроси, като изучаваме изолацията на транзакциите ...
Нивото на изолация на транзакцията е условна стойност, която определя степента, до която в резултат на изпълнението на логически паралелни транзакции в СУБД се допускат противоречиви данни. Скалата на нивата на изолация на транзакциите съдържа редица стойности, подредени от най-ниската до най-високата; по-високото ниво на изолация съответства на по-добра последователност на данните, но използването му може да намали броя на физически паралелните транзакции.
Обратно, по-ниското ниво на изолация позволява повече паралелни транзакции, но намалява точността на данните. По този начин, избирайки използваното ниво на изолация на транзакциите, разработчикът на информационната система до известна степен осигурява избор между скоростта на работа и осигуряването на гарантирана последователност на данните, получени от системата.
Проблеми с едновременния достъп чрез транзакции
Когато транзакциите се изпълняват паралелно, са възможни следните проблеми:
- загубена актуализация - ако един блок данни се промени едновременно от различни транзакции, всички промени се губят, с изключение на последната;
- "мръсно" четене (англ. Dirty read) - четене на данни, добавени or променени от транзакция, които впоследствие няма да бъдат потвърдени (върнати назад);
- неповторяемо четене (англ. non-repeatable read) - при повторно четене в рамките на една и съща транзакция се променят предварително прочетените данни;
- фантомни четения - една транзакция по време на нейното изпълнение няколко пъти избира много редове по едни и същи критерии. Друга транзакция между тези извличания добавя редове or модифицира колони на някои от редовете, използвани в критериите за извличане на първата транзакция, и завършва успешно. В резултат на това ще се окаже, че едни и същи селекции в първата транзакция дават различни набори от редове.
Помислете за ситуации, в които могат да възникнат тези проблеми.
1.2 Загубена актуализация
Ситуацията, когато един блок данни се променя едновременно от различни транзакции, една от промените се губи.
Да предположим, че има две транзакции, изпълнявани едновременно:
Транзакция 1 | Транзакция 2 |
---|---|
АКТУАЛИЗИРАНЕ tbl1 SET f2=f2+20 WHERE f1=1; | АКТУАЛИЗИРАНЕ tbl1 SET f2=f2+25 WHERE f1=1; |
И в двете транзакции стойността на полето f2 се променя, след завършване стойността на полето трябва да бъде увеличена с 45. Всъщност може да възникне следната последователност от действия:
- И двете транзакции едновременно четат текущото състояние на полето. Тук не се изисква точна физическа паралелност, достатъчно е втората операция за четене да е завършена, преди друга транзакция да запише резултата си.
- И двете транзакции изчисляват новата стойност на полето, като добавят съответно 20 и 25 към предварително прочетената стойност.
- Транзакциите се опитват да запишат резултата от изчислението обратно в поле f2. Тъй като е физически невъзможно да се извършат две записи едновременно, в действителност една от операциите за запис ще бъде извършена по-рано, другата по-късно. Втората операция за запис ще презапише резултата от първата.
В резултат на това стойността на полето f2 след завършване на двете транзакции може да се увеличи не с 45, а с 20 or 25, тоест една от транзакциите за промяна на данните ще „изчезне“.
1.3 „Мръсно“ четене
Четене на данни, добавени or модифицирани от транзакция, която по-късно няма да успее да се ангажира (връщане назад).
Да предположим, че имаме две транзакции, отворени от различни applications, които изпълняват следните SQL изрази:
Транзакция 1 | Транзакция 2 |
---|---|
UPDATE tbl1 SET f2=f2+1 WHERE f1=1; | |
SELECT f2 FROM tbl1 WHERE f1=1; | |
ВЪРТАНЕ НА РАБОТА; |
В транзакция 1 стойността на поле f2 се променя, а след това в транзакция 2 се избира стойността на това поле. След това се връща обратно транзакция 1. В резултат на това стойността, получена от втората транзакция, ще се различава от стойността, съхранена в базата данни.
1.4 Неповторяемо четене
Ситуацията, когато при повторно четене в рамките на една и съща транзакция, преди това прочетени данни се оказват променени.
Да предположим, че имаме две транзакции, отворени от различни applications, които изпълняват следните SQL изрази:
Транзакция 1 | Транзакция 2 |
---|---|
SELECT f2 FROM tbl1 WHERE f1=1; | |
UPDATE tbl1 SET f2=f2+3 WHERE f1=1; | |
АНГАЖИРАНЕ; | |
SELECT f2 FROM tbl1 WHERE f1=1; |
В транзакция 2 се избира стойността на поле f2, след което в транзакция 1 стойността на поле f2 се променя. Ако опитате отново да изберете стойност от поле f2 в транзакция 2, ще се получи различен резултат. Тази ситуация е особено неприемлива, когато данните се четат, за да бъдат частично модифицирани и записани обратно в базата данни.
1.5 Четене на "фантоми"
Ситуацията, когато по време на многократно четене в рамките на една и съща транзакция, една и съща селекция дава различни набори от редове.
Да предположим, че има две транзакции, отворени от различни applications, които изпълняват следните SQL изрази:
Транзакция 1 | Транзакция 2 |
---|---|
SELECT SUM(f2) FROM tbl1; | |
INSERT INTO tbl1 (f1,f2) VALUES(15,20); | |
АНГАЖИРАНЕ; | |
SELECT SUM(f2) FROM tbl1; |
Транзакция 2 изпълнява SQL израз, който използва всички стойности на поле f2. След това се вмъква нов ред в транзакция 1, което води до различен резултат от повторното изпълнение на SQL израза в транзакция 2. Тази ситуация се нарича фантомно четене (фантомно четене). Различава се от еднократното четене по това, че резултатът от многократния достъп до данни се е променил не поради промяната/изтриването на самите данни, а поради появата на нови (фантомни) данни.
GO TO FULL VERSION