фиксация и транзакция mysql


У меня есть вопрос относительно коммитов и транзакций mysql.

У меня есть пара операторов php, которые выполняют запросы mysql.

Могу ли я просто сказать следующее?

mysql_query("START TRANSACTION");
//more queries here
mysql_query("COMMIT");

Что именно это будет делать? Как это помогает? Для обновлений, удалений и вставок я также обнаружил, что это блокирует чтение других запросов:

mysql_query("LOCK TABLES t1 WRITE, t2 WRITE");
//more queries here
mysql_query("UNLOCK TABLES t1, t2");

Будет ли это блокировать другие запросы любого характера или только запись/выбор?

Еще один вопрос: Допустим, выполняется один запрос и блокируется другие запросы. Другой запрос пытается получить доступ к заблокированным данным - и видит, что они заблокированы. Как это происходит? Ждет ли он, пока данные снова не будут разблокированы, и повторно выполняет запрос? Это просто терпит неудачу и нуждается в повторении? Если да, то как я могу проверить?

Большое спасибо!

Деннис

Author: weltschmerz, 2012-05-14

1 answers

В InnoDB вам не нужно явно запускать или завершать транзакции для отдельных запросов, если вы не изменили настройку автоматической фиксации по умолчанию, которая "включена". Если включена функция автоматической фиксации, InnoDB автоматически заключает каждый отдельный SQL-запрос в транзакцию, что эквивалентно START TRANSACTION; query; COMMIT;.

Если вы явно используете START TRANSACTION в InnoDB с включенной автоматической фиксацией, то все запросы, выполняемые после оператора START TRANSACTION, либо будут выполнены, либо все они завершатся ошибкой. Это полезно в банковской сфере среды, например: если я перевожу 500 долларов на ваш банковский счет, эта операция должна быть успешной только в том случае, если сумма была вычтена из моего банковского баланса и добавлена к вашему. Так что в этом случае вы бы запустили что-то вроде

START TRANSACTION;
UPDATE customers SET balance = balance - 500 WHERE customer = 'Daan';
UPDATE customers SET balance = balance + 500 WHERE customer = 'Dennis';
COMMIT;

Это гарантирует, что либо оба запроса будут выполнены успешно, либо ни одного, но не только одного. В этом посте есть еще кое-что о том, когда следует использовать транзакции.

В InnoDB вам очень редко придется блокировать целые таблицы; InnoDB, в отличие от MyISAM, поддерживает блокировку на уровне строк. Это означает, что клиентам не нужно блокировать всю таблицу, заставляя других клиентов ждать. Клиенты должны блокировать только те строки, которые им действительно нужны, позволяя другим клиентам продолжать доступ к нужным им строкам.

Вы можете прочитать больше о транзакциях InnoDB здесь. На ваши вопросы о взаимоблокировке даны ответы в разделах 14.2.8.8 и 14.2.8.9 из документов. Если запрос завершится неудачно, ваш драйвер MySQL вернет сообщение об ошибке с указанием причины; затем ваше приложение должно повторно выполнить запросы, если потребуется.

Наконец, в своем примере кода вы использовали mysql_query. Если вы пишете новый код, пожалуйста, прекратите использовать старую, медленную и устаревшую библиотеку mysql_ для PHP и используйте вместо нее mysqli_ или PDO:)

 13
Author: Daan, 2012-05-14 17:50:59