DML или команды манипулирования данными должны обрабатываться в SQL с особой осторожностью по той простой причине, что они каким-то образом модифицируют целевые данные. Обычно это делается с помощью операторов UPDATE или DELETE. В этом сообщении блога мы узнаем, как лучше защитить данные (и самих себя) при выполнении этих типов команд, используя SAVEPOINT в TRANSACTION.

Примечание: все данные, имена или наименования, найденные в базе данных, представленной в этом посте, строго используются для практики, обучения, обучения и тестирования. Он ни в коем случае не отображает фактические данные, принадлежащие или используемые какой-либо стороной или организацией.

ОС и БД используются:

  • Xubuntu Linux 16.04.5 LTS (Xenial Xerus)
  • MySQL 8.0.13

По умолчанию MySQL автоматически фиксирует все операторы при их запуске. Любые изменения с помощью команд DML записываются на диск и, следовательно, являются постоянными.

Однако вы можете (временно) изменить это «высечено на камне», введя команду START TRANSACTION. После включения, чтобы вернуть MySQL в режим автоматической фиксации, вы должны выполнить либо команду ROLLBACK, либо COMMIT, заканчивая или завершая TRANSACTION.

Чтобы сделать вещи еще лучше, в TRANSACTION также есть что-то, называемое SAVEPOINT. Вам просто нужно использовать его, потому что по умолчанию его нет.

Создавая SAVEPOINT с пользовательским именем, любой активный TRANSACTION можно откатить с помощью синтаксиса ROLLBACK TO save_point_name до этого конкретного места в TRANSACTION. Мне нравится представлять это как единичный «момент времени» внутри TRANSACTION в целом.

Любые модификации данных, которые были выполнены в течение TRANSACTION после установленного SAVEPOINT, возвращаются в исходное состояние (до состояния SAVEPOINT).

Чтобы лучше понять, давайте рассмотрим простой пример и закрепим концепцию. У меня есть эта таблица и данные:

mysql> SELECT * FROM names;
 + — — — + — — — — — — +
 | id    | first_name  |
 + — — — + — — — — — — +
 | 4     | Harry       |
 | 33    | Tom         |
 | 8     | Shelly      |
 | 10    | Ricky       |
 + — — — + — — — — — — +
 4 rows in set (0.00 sec)

Затем я инициализирую TRANSACTION:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

Создайте SAVEPOINT файл с именем «initial_save»:

mysql> SAVEPOINT initial_save;
Query OK, 0 rows affected (0.00 sec)

Затем выполните UPDATE в строке таблицы:

mysql> UPDATE names
    -> SET id = 414
    -> WHERE first_name = ‘Harry’;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

И посмотрите отраженные изменения:

mysql> SELECT *
    -> FROM names
    -> WHERE first_name = ‘Harry’;
 + — — — + — — — — — — +
 | id    | first_name  |
 + — — — + — — — — — — +
 | 414   | Harry       |
 + — — — + — — — — — — +
 1 row in set (0.00 sec)

Давайте отменим это изменение, выполнив ROLLBACK для созданного SAVEPOINT:

mysql> ROLLBACK TO initial_save;
Query OK, 0 rows affected (0.04 sec)

И просмотрите отмененные (исходные) данные для этой строки:

mysql> SELECT *
    -> FROM names
    -> WHERE first_name = ‘Harry’;
 + — — — + — — — — — — +
 | id    | first_name  |
 + — — — + — — — — — — +
 | 4     | Harry       |
 + — — — + — — — — — — +
 1 row in set (0.00 sec)

Ниже приводится очень важный отрывок из документации SAVEPOINT, цитируемый непосредственно из этого источника:

«Оператор ROLLBACK TO SAVEPOINT откатывает транзакцию до указанной точки сохранения без завершения транзакции. Изменения, внесенные текущей транзакцией в строки после установки точки сохранения, отменяются при откате, но InnoDB не снимает блокировки строк, которые были сохранены в памяти после точки сохранения. (Для новой вставленной строки информация о блокировке передается идентификатором транзакции, хранящимся в строке; блокировка отдельно не сохраняется в памяти. В этом случае блокировка строки снимается при отмене.) «

Наконец, чтобы сделать эти изменения постоянными, мы должны выпустить COMMIT:

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

Вы можете видеть, что с тех пор, как COMMIT был выпущен, мы больше не находимся внутри TRANSACTION и SAVEPOINT "initial_save" не существует:

mysql> ROLLBACK TO initial_save;
ERROR 1305 (42000): SAVEPOINT initial_save does not exist

Теперь, когда мы закончили или вышли из TRANSACTION, данные остаются в исходном состоянии:

mysql> SELECT *
    -> FROM names
    -> WHERE first_name = ‘Harry’;
 + — — — + — — — — — — +
 | id    | first_name  |
 + — — — + — — — — — — +
 | 4     | Harry       |
 + — — — + — — — — — — +
 1 row in set (0.00 sec)

Так это полное доказательство? Не совсем так.

Хотя у вас может быть несколько отдельных SAVEPOINTS в одном TRANSACTION, существуют некоторые ограничения на то, какие типы команд «разрешены» для ROLLBACK. Поскольку их слишком много, чтобы перечислить их все, можно использовать несколько наиболее распространенных команд: ALTER TABLE, CREATE VIEW, DROP FUNCTION и т. Д.

Чтобы увидеть полный список, посетите раздел 13.3.3 Утверждения, вызывающие неявную фиксацию в официальной документации.

TRANSACTIONSAVEPOINT' - отличное дополнение для тех, кто имеет дело с командами DML и их данными, так что обязательно проверьте их!

Нравится то, что вы прочитали? Видите что-нибудь неправильное? Прокомментируйте, пожалуйста, ниже и спасибо за чтение !!!

Изучите официальное Онлайн-руководство по MySQL 8.0 для получения дополнительной информации.

Призыв к действию!

Спасибо, что нашли время прочитать этот пост. Я искренне надеюсь, что вы открыли для себя что-то интересное и поучительное. Пожалуйста, поделитесь своими выводами здесь с кем-нибудь, кого вы знаете, кто тоже получит от этого такую ​​же ценность.

Посетите страницу Портфолио-проекты, чтобы увидеть сообщения в блоге / технические статьи, которые я написал для клиентов.

Я уже упоминал, как я люблю чашку кофе?!?!

Чтобы получать уведомления по электронной почте (Никогда не спамить) от этого блога (Проза Цифровой Совы) о последних публикациях в блогах по мере их публикации, пожалуйста, подпишитесь (по собственному желанию), нажав кнопку Нажмите, чтобы подписаться! На странице боковая панель на главной странице! (Не стесняйтесь в любое время просмотреть страницу Политики конфиденциальности Digital Owl's Prose по любым вопросам, которые могут у вас возникнуть: обновления по электронной почте, подписка, отказ, контактные формы и т. Д.)

Обязательно посетите страницу Best Of, где собраны мои лучшие сообщения в блоге.

Джош Отвелл хочет учиться и расти как разработчик SQL и блогер. Другие любимые занятия находят его, уткнувшись носом в хорошую книгу, статью или командную строку Linux. Среди них он разделяет любовь к настольным ролевым играм, чтению фэнтезийных романов и проведению времени с женой и двумя дочерьми.

Отказ от ответственности: примеры, представленные в этом посте, представляют собой гипотетические идеи о том, как достичь аналогичных результатов. Это не самое лучшее решение. Большая часть, если не все, из представленных примеров выполняется на рабочей станции-среде личного развития / обучения и не должна считаться производственной или готовой к использованию. Ваши конкретные цели и потребности могут отличаться. Используйте те методы, которые лучше всего подходят для ваших нужд и целей. Мнения мои собственные.

Первоначально опубликовано на joshuaotwell.com 16 января 2019 г.