wiki:dba_transactions

Трансакции, конкурентно извршување и заклучување на ресурсите

Трансакции

Трансакциите се фунфаментален концепт на системите за управување со бази на податоци, што обезбедува атомичност, конзистентост и изолација на состојбата во базата, додека се извршуваат повеќе операции групирани во единствена логичка целина. Ваквата логичка целина (трансакција) или се извршува во целост или не се извршува воопшто.

Во PostgreSQL клучните зборови кои се користат во контекст на трансакции за започнување, потврдување и поништување на трансакциите се BEGIN, COMMIT и ROLLBACK соодветно. Покрај ова, PostgreSQL поддржува и парцијално зачувување на состојбата во рамки на трансакцијата со SAVEPOINT.

Во однос на „типови“ на трансакции, односно нивоа на изолираност нa трансакции, PostgreSQL поддржува четири, и тоа:

  • READ UNCOMMITED

Ова е најниското ниво на изолација и нешто што практично излегува од концептот на трансакција бидејќи до некој степен ја нарушува конзистентноста во рамки на една трансакција. Имено, ова ниво на изолација дава можност во рамки на трансакцијта да се има пристап до непотврдени промени од други трансакции. Па така, доколку во една сесија се изврши следниот код:

BEGIN TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT balance FROM accounts WHERE name = 'User Test'; -- Резултат: 500

Притоа, во друга сесија се изврши следниот код:

BEGIN;
UPDATE accounts SET balance = balance + 500 WHERE name = 'User Test';

-- сѐ уште не се потврдува трансакцијата

Доколку се вратиме во првата сесија и го извршиме повторно истиот SELECT, резултатот овој пат ќе биде 1000.

  • READ COMMITED

Ова е стандардното однесување и ниво на изолација на трансакциите кое го добиваме без дополнителни клучни зборови при започнување на трансакција. Промените направени во рамки на трансакциите се достапни по нивно потврдување

  • REPEATABLE READ

Ова ниво на изолација обезбедува практично замрзнување на состојбата на базата во моментот на започнување на трансакцијата. Доколку по започнување на трансакција со ниво на изолација REPEATABLE READ, во друга сесија се започне и потврди друга трансакција, резултатот од истата нема да биде видлив во рамки на трансакцијата започната во првата сесија.

Во рамки на базата на системот dbLearnStar, едно сценарио каде ова би бил валиден пример е следното. Доколку за време на испит професорот има потреба да види резултати до тој момент, наместо истото да го прави со рачно филтрирање според датумот на поднесок, истиот ефект може да го постигне преку започнување трансакција со ниво на изолација REPEATABLE READ.

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- Пример прашање: Број на испратени решенија од почетокот на испитот до моментот на започнување на трансакцијата


SELECT COUNT(*) as total_submissions
FROM student_submit_solution sss
JOIN student_started_test sst ON sss.student_started_test_id = sst.student_started_test_id
JOIN test_instance ti ON sst.test_instance_id = ti.test_instance_id
WHERE ti.test_collection_id = 10;

Во меѓувреме студентите можат непречено да работат и да испраќаат решенија. Доколку трансакцијата е отворена подолго време и професорот го изврши истиот прашалник и по 10 минути и притоа студентите имаат испратено нови решенија, резултатот ќе биде ист.

  • SERIALIZABLE

Ова е највисокото ниво на изолација кое го нуди PostgreSQL. Пристапот за читање е практично ист како и со READ COMMITED, но разликата е во начинот на кој се справува со менување на податоци во редиците. Доколку во една сесија се изврши следново:

BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

UPDATE inventory SET quantity = 1 where product_id = 1;

И во втора сесија се изврши:

BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE inventory SET quantity = 2 where product_id = 1;
COMMIT;

Резултатот ќе биде грешка поради тоа што SERIALIZABLE не дозволува конкурентно менување на исти записи од две трансакции (сесии).

Конкурентно извршување и пристап и заклучување

PostgreSQL користи софистициран систем на заклучувања за да обезбеди конзистентност на податоците при конкурентен пристап. Заклучувањата се автоматски механизам што го контролираат пристапот до ресурсите и спречуваат конфликти помеѓу трансакциите, особено кога се извршуваат операции кои прават промени. Во PostgreSQL заклчувањата може да бидат на ниво на база, табела или ред. Иако е возможно експлицитно, со мануелно извршена команда да направиме заклучување, овој концепт генерално е управуван автоматски од системот за управување со бази на податоци.

Тип заклучување Автоматски се поставува при Дозволува конкурентно Блокира Типична употреба
ACCESS SHARE SELECT Сите освен ACCESS EXCLUSIVE ACCESS EXCLUSIVE Читање на податоци
ROW SHARE SELECT FOR UPDATE/SHARE Повеќето операции EXCLUSIVE, ACCESS EXCLUSIVE Читање со намера за ажурирање
ROW EXCLUSIVE INSERT, UPDATE, DELETE Читање и други промени SHARE и повисоки Стандардни промени
SHARE UPDATE EXCLUSIVE VACUUM, ANALYZE Читање и ROW EXCLUSIVE SHARE UPDATE EXCLUSIVE и повисоки Одржување
SHARE CREATE INDEX Читање и други SHARE ROW EXCLUSIVE и повисоки Индексирање
SHARE ROW EXCLUSIVE Ретко Само читање ROW EXCLUSIVE и повисоки Специјални операции
EXCLUSIVE ALTER TABLE Само читање Сè освен читање Структурни промени
ACCESS EXCLUSIVE DROP, TRUNCATE, VACUUM FULL Ништо Сите Сите други операции

Мошне корисна примена во системот за испити по бази може да има концептот на SELECT FOR UPDATE и SKIP LOCKED. Доколку постоечкото решение со прошири и е потребно последно испратените решенија на студентите за секоја од задачите, по завршување на испитот да се реизвршат врз посебна шема/база и притоа сакаме ова извршување да е паралелизирано, на повеќе инстанци (или на повеќе нитки), со примена на овој концепт можеме да го постигнеме ефектот на редица, така што секое решение кое треба да се реизврши ќе го додадеме во една табела која што ќе ја претставува редицата. Секоја од инстанците/процесите каде се извршуваат решенијата ќе го зема својот следен job со следниот прашалник

SELECT * FROM submissions_queue
WHERE status = 'PENDING'
ORDER BY id
LIMIT 1
FOR UPDATE SKIP LOCKED

Со ова практично добиваме две нивоа на контрола, и тоа, со користење на 'FOR UPDATE', ја заклчуваме таа редица за евентуална промена од друга сесија, а со SKIP LOCKED овозможуваме секој од процесите да го земе следното решение во редицата коешто не е испроцесирано, притоа избегнувајќи ги веќе заклучените

Last modified 5 days ago Last modified on 06/06/25 19:31:52
Note: See TracWiki for help on using the wiki.