Поддержка транзакций в сервере MySQL реализуется при помощи обработчиков
транзакционных таблиц типов InnoDB
и BDB
(see section 7 Типы таблиц MySQL).
Таблицы InnoDB
обеспечивают соответствие требованиям ACID
.
Однако для таблиц нетранзакционных типов, таких как MyISAM
, в MySQL
используется иная парадигма обеспечения целостности данных, получившая
название ``атомарные операции
''. Атомарные операции в сравнении с
транзакциями часто обеспечивают такую же или даже лучшую целостность при
более высокой производительности. Поскольку сервер MySQL поддерживает обе
парадигмы, пользователь может выбирать между скоростью, которую
обеспечивают атомарные операции, и транзакционными возможностями для своих
приложений. Такой выбор может быть сделан для каждой таблицы отдельно.
Рассмотрим, как используются возможности сервера MySQL для обеспечения строгой целостности и каковы эти возможности в сравнении с транзакционной парадигмой.
ROLLBACK
вместо COMMIT
, то транзакции предпочтительней
атомарных операций. Транзакции также обеспечивают гарантию того, что
незаконченные обновления или искаженные действия не будут
фиксироваться в базе данных; серверу предоставляется возможность
выполнить автоматический откат, и база данных будет сохранена. Почти
во всех случаях при работе с сервером MySQL решить возможные проблемы
можно путем включения простых проверок перед обновлениями и запуска
простых скриптов, которые выполняют проверку баз данных на нарушение
целостности с автоматическим исправлением повреждений или выдачей
предупреждения, если такое нарушение возникает. Отметим, что
полноценное выявление и устранение ошибок в таблицах без потери
целостности данных можно обеспечить, просто используя системный журнал
MySQL или добавив еще один дополнительный журнал.
LOCK TABLES
или атомарных UPDATE
,
при гарантии того, что в базе данных никогда не произойдет
автоматического прерывания (что является часто встречающейся проблемой
для транзакционных баз данных).
Транзакционная парадигма имеет свои достоинства и свои недостатки. Для многих пользователей и разработчиков приложений решающее значение имеет простота кодирования в проблемных ситуациях, в которых может произойти или неизбежно аварийное прерывание. Однако даже если парадигма атомарных операций для вас нова или вы привыкли к транзакциям, все же следует принимать во внимание выигрыш в скорости, который могут обеспечить нетранзакционные таблицы (порядка от трех до пяти раз по сравнению со скоростью наиболее быстрых и оптимально настроенных транзакционных таблиц).
В ситуациях, где целостность данных чрезвычайно важна, сервер MySQL
обеспечивает даже для нетранзакционных таблиц надежность и целостность
данных уровня транзакций или лучше. При блокировании таблиц с помощью LOCK
TABLES
все обновления останавливаются до тех пор, пока не будут выполнены
все проверки на целостность. При наличии только блокировки чтения (в
противоположность блокировке записи) операции чтения и вставки, тем не
менее, производятся. Новые внесенные записи не будут видны никому из
имеющих блокировку чтения клиентов до освобождения этих блокировок. С
iомощью INSERT DELAYED
вставки становятся в очередь и находятся там до тех
пор, пока не будут сняты все блокировки. При этом клиент не вынужден
ждать, пока отработает INSERT
(see section 6.4.4 Синтаксис оператора INSERT DELAYED
).
То, что мы подразумеваем под термином ``атомарные'', не означает ничего сверхъестественного. Имеется в виду лишь следующее: гарантируется, что при выполнении каждого конкретного обновления никакой другой пользователь не может повлиять на него и никогда не произойдет автоматического отката (который возможен на транзакционных таблицах, если не приняты должные меры предосторожности). Сервер MySQL также гарантирует, что не случится грязного чтения (dirty read)".
Ниже описаны некоторые технические приемы работы с нетранзакционными таблицами:
LOCK TABLES
, причем нет необходимости в указателях при
динамическом обновлении записей.
ROLLBACK
, можно использовать следующую
стратегию:
LOCK TABLES ...
для блокирования всех таблиц, к которым
необходим доступ.
UNLOCK TABLES
для освобождения произведенных
блокировок.
WHERE
в команде
UPDATE
. Если данную запись обновить не удалось, то клиент получает
сообщение: "Некоторые данные, которые вы изменяли, были модифицированы
другим пользователем". После этого в окне выводится старая версия, чтобы
пользователь мог решить, какую версию записи заказчика он должен
использовать. Такой алгоритм обеспечивает нечто похожее на блокирование
столбцов, но реально он даже лучше, поскольку мы обновляем только часть
столбцов, используя величины, соответствующие их текущим значениям. Это
означает, что типичные команды UPDATE
выглядят примерно как приведенные
ниже:
UPDATE tablename SET pay_back=pay_back+'relative change'; UPDATE customer SET customer_date='current_date', address='new address', phone='new phone', money_he_owes_us=money_he_owes_us+'new_money' WHERE customer_id=id AND address='old address' AND phone='old phone';Как можно видеть, этот способ очень эффективно и работает, даже если другой клиент изменит величины в столбцах
pay_back
или money_he_owes_us
.
ROLLBACK
и/или LOCK
TABLES
для управления уникальными идентификаторами для разных таблиц.
Того же результата можно добиться намного более эффективно, используя
столбец AUTO_INCREMENT
и либо SQL-функцию LAST_INSERT_ID()
, либо
функцию C API mysql_insert_id()
(see section 8.4.3.31 mysql_insert_id()
).
В общем случае можно написать код и для блокирования на уровне строк. Для
некоторых ситуаций это действительно необходимо, но таких случаев очень мало.
Блокировка на уровне строк поддерживается в таблицах InnoDB
. Для типа
MyISAM
можно использовать флаговые столбцы в таблице и выполнять
запросы, подобные следующему:
UPDATE tbl_name SET row_flag=1 WHERE id=ID;MySQL возвращает 1 в качестве количества подвергнутых воздействию строк, если данная строка была найдена, а
row_flag
в исходной строке не был уже
равен 1. Это можно себе представить так, как будто сервер MySQL изменяет
предшествующий запрос на:
UPDATE tbl_name SET row_flag=1 WHERE id=ID AND row_flag <> 1;
User Comments
Add your own comment.