Можно ли выполнить два или более запросов одновременно? - PullRequest
4 голосов
/ 22 июля 2010

Хорошо, допустим, у нас есть таблица bank_account.Есть строка с именем money.Это имеет 2000 значение.И у нас есть два человека, которые пытаются снять эти деньги, предположим, они могут это сделать.Итак, возможно ли, что они будут делать это одновременно?Например.есть выдуманный код:

 $all_money = get_value('money', 'bank_account); //lets suppose thats a function how we get value money from bank_account table

 if($all_money > 0) 
 {
     //here is a code where those money are being withdrawed from bank_account and inserting into the person's account
 }

Если эти два человека получают значение 2000 одновременно, это означает, что этот пункт if($all_money > 0) будетвыполнено, и оба игрока получат 2000, а bank_account будет иметь ценность в 2000 денег.Итак, возможно ли это случиться?Если да, то как я могу защитить это?Спасибо.

Ответы [ 6 ]

6 голосов
/ 22 июля 2010

Выполните это перед доступом к таблице:

LOCK TABLE table_name READ;

Это заблокирует стол. Когда вы закончили работу, вы звоните:

UNLOCK TABLES;
3 голосов
/ 22 июля 2010

Вопреки распространенному мнению, операторы SQL принимаются и помещаются в очередь для обработки.Они не выполняются одновременно.

Что происходит, зависит от бизнес-правил - если на банковском счете разрешен овердрафт, второй запрос будет выполнен успешно (при условии достаточно большого овердрафта).В противном случае второй запрос не будет выполнен.

2 голосов
/ 22 июля 2010

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

1 голос
/ 22 июля 2010

A очень стереотипный пример будет:

DELIMITER //
CREATE PROCEDURE do_banktransfer(
  IN transfer_amount INT,
  IN from_account    INT,
  IN to_account      INT,
  OUT success        INT)
BEGIN
START TRANSACTION;
UPDATE account SET balance = balance - transfer_amount WHERE id = from_account;
UPDATE account SET balance = balance + transfer_amount WHERE id = to_account;
SELECT balance INTO cur_balance FROM account WHERE id = from_account;
IF cur_balance < 0 THEN
    SET success = 0;
    ROLLBACK;
ELSE 
    SET success = 1;
    COMMIT;
END IF;
END;//
1 голос
/ 22 июля 2010

Транзакции в innodb помогут вам в этом. Не забудьте прочитать вашу версию MySQL, потому что они были прослушаны ранее.

0 голосов
/ 22 июля 2010

Я думаю, вы беспокоитесь о двух отдельных потоках, соединяющихся с базой данных, и о том, что один получает деньги, а другой выполняет код, основанный на ранее прочитанном балансе.

В этой ситуации вам следует применить чтениезаблокируйте (как говорит Кристиан) перед запросом баланса и снятием блокировки один раз [в вашем фрагменте кода] оператор if закончился.

Вы можете столкнуться с проблемами, если что-то упадет, пока у вашего потока все еще есть блокировка, поэтомувам нужны сценарии Canny Bash, чтобы убить вещи;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...