#php #mysql
#php #mysql
Вопрос:
$database->count = "SELECT * FROM table WHERE item_id = 1"
if($database->count == 1)
{
$database->update = "UPDATE users SET money = money - 1000";
$database->delete = "DELETE table WHERE item_id = 1";
}
Допустим, у меня есть этот код (я только что создал его) в index.php страница. Может ли одновременно "SELECT * FROM table WHERE item_id = 1"
выполняться запрос, чтобы два человека получили счет 1 и -1000 денег? Если да, то как я могу этого избежать?
Спасибо.
Комментарии:
1. 1 за размышления об условиях гонки .
Ответ №1:
Если вы беспокоитесь о том, что два запроса, выполняемых одновременно, могут привести к несбалансированному состоянию вашей базы данных, вам следует использовать транзакции : http://dev.mysql.com/doc/refman/5.0/en/ansi-diff-transactions.html
Транзакции полезны для поддержания правильного состояния ваших данных.
Ответ №2:
Вы можете LOCK TABLE table WRITE
до и UNLOCK TABLE table
после выполнения запросов.
Комментарии:
1. Любой метод — транзакции, блокировка, секундное ожидание и запрос — для предотвращения условий гонки может замедлить работу страницы (но если ваши запросы выполняются быстро, замедление обычно минимально). Вам решать, стоит ли это того — если вы имеете дело с денежными суммами, вероятно, лучше, чтобы странице потребовалась дополнительная секунда для загрузки, чем сообщать кому-то, что у них на тысячу долларов больше, чем на самом деле.
2. Блокировка таблицы требуется только для таблиц MyISAM для выполнения «поддельных» транзакций. InnoDB имеет блокировку на уровне строк и не требует блокировок на уровне таблиц.
3. @Marc B: итак, если у меня InnoDB, значит, со мной все в порядке и мне не нужно беспокоиться?
4. Вам все равно нужно использовать транзакции и блокировки на уровне строк, чтобы убедиться, что никакие другие запросы не прерывают выполняемые вами обновления. Но да, не беспокойтесь о блокировках таблиц для такого рода вещей. блокировки innodb на уровне таблицы предназначены для «общей картины», такой как сброс базы данных во время резервного копирования.
Ответ №3:
Вам нужны транзакции.
Ответ №4:
Если вы используете InnoDB, вы можете поиграть с уровнем изоляции транзакций, чтобы не разрешать грязные чтения. Убедитесь, что вы используете повторяемые чтения в качестве уровня изоляции транзакции.
Кстати, в строке УДАЛЕНИЯ должно быть написано УДАЛИТЬ ИЗ таблицы, ГДЕ item_id = 1;
Ответ №5:
Не все базы данных поддерживают транзакции, поэтому, если вы используете mysql так же, как работаете с PHP, вам понадобится метод блокировки таблицы. Ваша таблица будет заблокирована до тех пор, пока не будет выполнена вся работа, а не вы ее разблокируете, вы также можете указать блокировку строк.
http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
Лучший 🙂 Вакар Аламгир
Комментарии:
1. Поддержка транзакций не имеет ничего общего с PHP, все дело в используемом движке базы данных MySQL.
2. В основном php-приложения, работающие на сервере mysql
3. Довольно тривиально переключиться с MyISAM на InnoDB.
4. @ceejayoz Я не видел ваш ответ, извините, кстати