До этого момента речь шла о транзакциях в контексте таблиц InnoDB и BDB, т.е. лишь тех типов таблиц MySQL, которые поддерживают транзакции и, следовательно, удовлетворяют стандарту ACID. Для более старых типов таблиц MySQL, которые все еще используются во многих инсталляциях MySQL и не поддерживают транзакций, MySQL позволяет реализовывать примитивные формы транзакций с использованием механизма блокировки таблиц. Этот раздел посвящен детальному рассмотрению транзакций такого типа. Его можно считать общим руководством по обеспечению безопасных транзакций при работе с таблицами, которые не поддерживают транзакций.

Предупрежден - значит защищен
В завершение предыдущего примера взаимоблокировки, можно сказать, что, скорее всего, она случилась не столько из-за недоработок базы данных, сколько из-за ошибок разработчика приложения: различным был порядок обработки таблиц клиентами, что и привело к взаимоблокировке. Взаимоблокировок можно избежать при условии хорошо продуманного планирования и разработки на уровне приложения. Таким образом, становится возможным распределение ресурсов между процессами и циклическими цепочками (наподобие той, что у нас только что получилась), которые при этом обнаруживаются и удаляются как можно раньше.
Разработчик может принимать самые разные фундаментальные решения на при­кладном уровне во избежание взаимоблокировок: сделать все необходимые блокировки в начале сеанса, обрабатывать таблицы в одном и том же порядке, предусмотреть встроенные программы восстановления для повторения транзакций при их отмене СУБД для разрешения возникающих ситуаций взаимоблокировки.

Блокировка таблиц как замена транзакций
Вследствие того, что формат MyISAM (и другие более старые форматы таблиц MySQL) не поддерживают работу с командами COMMIT и ROLLBACK, каждое произве­денное в базе данных изменение немедленно сохраняется на диске. Как было отмечено ранее, в однопользовательском сценарии это не составляет проблемы, но в многопользо­вательских сценариях работы это может привести к определенным затруднениям, т.к. в этом случае нет возможности создавать своеобразные "капсулы", которые бы изолирова­ли изменения, произведенные одними пользователями, от изменений, сделанных другими пользователями. В таком случае единственной возможностью обеспечения целостности данных при их вводе различными клиентами, является метод "грубой силы": а именно - запрет на доступ к таблицам других пользователей на время проведения изменений в них (для этого они блокируются) и разрешение доступа к ним только после завершения всех изменений.
В предыдущем разделе этой главы уже обсуждались таблицы типа InnoDB и BDB, рассчитанные на поддержку блокировки на уровне страниц и строк на период безопасно­го выполнения транзакций. Однако таблицы типа MyISAM не поддерживают эти точные механизмы блокировки. Для таблиц такого типа в целях предотвращения одновременных транзакций используется блокировка таблиц явным образом.
Для осуществления блокировки таблиц, в MySQL используется следующий синтаксис: 
LOCK TABLES имя-таблицы тип-блокировки, ...
В этом случае на таблицу users накладывается блокировка с разрешением чтения.
Листинг 12.18.
mysql> LOCK TABLE users READ;
Query OK, 0 rows affected (0.05 sec)
Довольно часто приходится блокировать сразу несколько таблиц. Для этого следует просто указать в команде LOCK TABLES список таблиц, разделенный запятыми.
Листинг 12.19.
mysql> LOCK TABLES users READ, pfolios WRITE
Query OK, 0 rows affected (0.05 sec)
Этот оператор блокирует таблицу users в режиме READ и таблицу pfolio в режиме WRITE.
Таблицы можно разблокировать командой UNLOCK TABLES.:
Листинг 12.20.
mysql> UNLOCK TABLES;
Query OK, 0 rows affected (0.05 sec)
Имена разблокированных таблиц можно не задавать. MySQL автоматически разбло­кирует все таблицы, заблокированные до этого командой LOCK TABLES.
Существует два основных типа блокировки таблицы: блокировка "только чтение" и блокировка записи.
Блокировка read (только чтение)
Блокировка таблицы READ предполагает, что поток (клиент), который сделал эту блокировку, может считывать данные из таблицы, это же могут делать и другие потоки. Однако ни один из потоков не может обновлять заблокированную таблицу.
Рассмотрим простой пример с блокировкой READ - заблокируем в этом режиме таб­лицу users,
Листинг 12.21.
mysql> LOCK TABLE users READ;
Query OK, 0 rows affected (0.05 sec)
а затем попробуем прочитать из нее данные.
Псевдотранзакции с таблицами, которые не поддерживают транзакций
Листинг 12.23.
mysql> INSERT INTO users (uid, uname) VALUES (6,'tom1);
ERROR 1099: Table 'users' was locked with a READ lock and can't be up­dated
MySQL отвергает операцию INSERT, т.к. таблица заблокирована в режиме "только чтение".
А могут ли другие клиенты получить доступ к таблице? Откроем сеанс для нового клиента MySQL и попробуем получить доступ к этой же таблице. И очень скоро мы сможем убедиться в том, что с операцией чтения опять нет никаких проблем.
Псевдотранзакции с таблицами, которые не поддерживают транзакций
Два R
Еще одним вариантом блокировки READ является блокировка READ LOCAL, кото­рая отличается от обычной блокировки READ тем, что другие потоки могут осуществ­лять операции INSERT, не конфликтующие с сеансом, инициировавшим блокировку. Такая разновидность блокировки была создана для использования утилитой mysqldump, для того чтобы разрешить выполнение нескольких одновременных опе­раций INSERT.

А как насчет записей?
Листинг 12.25.
mysql> INSERT INTO users (uid, uname) VALUES (7,'paul1);
В этом случае клиент MySQL остановит работу и будет ожидать снятия блокировки первым сеансом. Вернемся назад к первому сеансу MySQL и выполним команду UNLOCK TABLES.
Листинг 12.26.
mysql> UNLOCK TABLES;
Query OK, 0 rows affected (0.04 sec)
Затем блокировка снимается и второй сеанс продолжит обработку своего запроса.
Листинг 12.27.
mysql> INSERT INTO users (uid, uname) VALUES (7,'paul'); Query OK, 1 row affected (27 min 15.11 sec)