Как «закрыть» базу данных при выполнении запроса?

#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 после выполнения запросов.

http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html

Комментарии:

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 Я не видел ваш ответ, извините, кстати