Транзакция – это логически единая операция по модификации базовых таблиц, состоящая из одной или нескольких команд СУБД и переводящая таблицы БД одного корректного (целостного), с точки зрения предметной области, состояния в другое, также корректное.
Здесь подчёркивается разница между реальными командами модификации (insert, update, delete), изменяющими записи одной таблицы, и логическими преобразованиями, сохраняющими исходные отношения связей между таблицами.
Понятие транзакции при таком определении соответствует понятию процедуры, а точнее его обобщение, мотивируемое новыми по сравнению с обработкой оперативной памяти обстоятельствами. Транзакции могут не выполняться (процедуры тоже, но это обстоятельство в процедурном программировании игнорируется). Такими обстоятельствами могут быть не только перебои питания и другие ошибки и исключительные ситуации, но и вполне нормальная работа в среде распределённых параллельных вычисления такой, как многопользовательская система архитектуры «клиент-сервер».
Select-запрос
Результаты выборки
Модификации
Примеры.
1) Один клиент читает данные в момент модификации таблиц другим клиентом.
2) Один пользователь удаляет записи таблицы, другой изменяет их значения.
Транзакция – изначально финансовый термин (другой вариант – трансакция), а именно –банковская сделка, перевод денег с нескольких счетов на несколько.
Обе операции могут осуществляться параллельно, или асинхронно, но важно, чтобы они выполнялись полностью, либо не выполнялись вообще.
Характеристическими свойствами транзакции считают свойство ACID (Atomicity, Consistency, Isolation, Durability) – атомарность, непротиворечивость, изолированность и стойкость (жизнеспособность). Под атомарностью понимают принцип «Всё или ничего» (не навреди). Все вовлечённые в транзакции изменения либо происходят целиком, либо не происходят вообще. Непротиворечивость означает, что изменения в любом случае приводят к корректному состоянию. Под изолированностью понимают то, что транзакции могут быть вложенными, но не пересекаться. Жизнеспособность означает, что подтверждённые результаты транзакции не могут быть отлажены никаким внешними воздействиями.
Это определение требует коренного пересмотра базовых для нас понятий:
1) Понятия состояний: состояние программы теперь не определяет однозначно результат;
2) Понятия процедуры как единоличного акта управления, не зависящего от времени и любых внешних воздействий.
F(S) – процедура на состояние S.
F(S)=F½(S,X), где Х – скрытый фактор внешней среды.
$X: F(S)¹F½(S,X)
(S,X) – состояние вычислительной среды, однозначно определяющее результат.
F(S), если F(S)=F½(S,X)
Transaction(F,S,X)=
S, в противном случае
В SQL транзакция оформляется с помощью команд-скобок:
begin [transaction]
команды SQL (в том числе вложенные транзакции)
end½commit [transaction]
Если по каким-либо причинам выполнение команд транзакции невозможно, происходит автоматический откат в состояние на момент её начала. Такой же откат может быть произведён явно с помощью команды RollBack [transaction].
Такой механизм поддержки транзакций скрывает очень сложную низкоуровневую реализацию, основанную на двух важнейших для многопользовательских СУБД понятий: буферизация и блокирование. Буферизация означает, что в реальности модификация производится не над самими таблицами БД, а над их копиями в буфере (точнее над результатами некоторой выборки), затем производится блокировка – запрет на модификацию оригиналов другими пользователями. Если блокировка удачна, то есть оригиналы не заблокированы другими пользователями, содержимое буфера записывается в оригиналы. В противном случае оригиналы остаются неизменными.
Примеры транзакций
База данных. В контексте ситуации люди описываются следующими атрибутами: фамилия (name), паспорт (Id), паспорт матери (mum), паспорт отца (dad), день рождения (birthday), доход (income), город (city), налог (tax, %). Кроме того, в информацию о студентах дополнительно включаются сведения: institute, sex {‘м’,’ж’}.
tax, % 0..100
name char(30)
Id numeric
mum numeric
dad numeric
birthday date
income currency
city char(30)
БД включает в себя три таблицы: студенты (Students), отцы (Dads) и матери (Mums).
Задача 1: снизить на 5% налог с родителей, имеющих более трёх детей-студентов, обучающихся в Казани.
Вариант решения:
1) Отобрать в таблице Students ссылки на тех родителей, у которых больше трёх детей-студентов из Казани;
2) Изменить записи об отобранных мамах;
3) Изменить записи об отобранных отцах.
select mum, dad
fromStudents
group by mum, dad
having count(*)>=3
where city=’Казань’
into cursor temp;
Задача 2: Повысить на 200 рублей стипендию студентов (доход), у которых нет хотя бы одного из родителей, либо совокупный доход родителей не превышает 1529 рублей.
Вариант решения:
1) Подсчитать доход всех родителей и запомнить тех, у которых этот доход не превышает заданной суммы;
2) Изменить информацию о студентах, у которых ссылки на родителей либо пустые, либо попали в предыдущий список.
create view Parents as
select distinct mum, dad
fromStudents, Mums, Dads
where (Mums.income+Dads.income<=1529) and (Students.mum=Mums.Id)
and (Students.dad=Dads.Id)
updateStudents set income=income+200
where (is null(mum) or is null(dad)) and mum in (select mum from Parents)
and dad in (select dad from Parents));
Замечание. Согласно стандарту ANSI в опции where команд модификации запрещается делать запросы к модифицируемым таблицам.
Задача 3: Удалить информацию о студентах данного ВУЗа.
Вариант решения:
1) Запомнить студентов нужного ВУЗа вместе со ссылками на отцов;
2) Запомнить отцов, у которых все дети (если есть) учатся в одном ВУЗе;
3) Удалить информацию об отцах, входящую в первый и второй списки;
4) Запомнить студентов нужного ВУЗа вместе со ссылками на матерей;
5) Запомнить матерей, у которых все дети (если есть) учатся в одном ВУЗе;
6) Удалить информацию о матерях, входящую в первый и второй списки;
7) Удалить информацию о студентах данного ВУЗа.
create view КХТИ1 as
select Id, dad fromStudents
where institute=’КХТИ’
create view Dad1 as
select Id fromDads
where not exists(select Id fromStudentswhere institute<>’КХТИ’
andDads.Id=Students.dad)
delete fromDads
where Id in (select dad from КХТИ1) and Id in (select Id from Dad1)
create view КХТИ2 as
select Id, mum fromStudents
where institute=’КХТИ’
create view Mum1 as
select Id fromMums
where not exists(select Id fromStudentswhere institute<>’КХТИ’
andMums.Id=Students.mum)
delete fromMums
where Id in (select mum from КХТИ2) and Id in (select Id from Mum1)