Прежде всего, не беспокойтесь об этом:
Я проверяю, достаточно ли у отправителя кредита для передачи с помощью запроса SELECT, прежде чем выполнять вышеупомянутый набор запросов.
Это оставляет вас открытыми для состояния гонки, с которым вам все равно придется иметь дело.Вместо этого установите ограничения в своей базе данных, чтобы сделать невозможным переход в недопустимое состояние.
Проблема 2 : мощность unsigned int
.
Не делай этого тоже, в этом нет необходимости.4-байтовое целое число со знаком должно иметь более чем достаточно места на положительной стороне;если это не так, вы можете переключиться на 8-байтовое целое число со знаком.Причина, по которой вы хотите получить значение со знаком, заключается в том, что он делает проверку целостности довольно простой: если баланс падает ниже нуля, значит что-то не так.Если вы используете значение без знака, вам придется зарезервировать 4294967295-n
(для некоторых n
), чтобы обнаружить недостаточное и избыточное переполнение вместо простого < 0
.
Что касается ограничения ваших данныхобычно вы используете ограничение CHECK следующим образом:
check (power >= 0)
, но MySQL не поддерживает ограничения CHECK.Однако вы можете написать триггер BEFORE INSERT OR UPDATE, который может проверить, что new.power >= 0
и вызывают исключение , если это не так.
Теперь у вас есть таблица users
, которая нене допустим недопустимые значения power
, поэтому мы закончили с выпуском 2.
Выпуск 1: транзакции.Да, вы действительно хотите использовать транзакцию для перевода.Вам понадобится такая последовательность:
start transaction
INSERT INTO power (sender, receiver, amount) VALUES ('$sender', '$receiver', '$amount')
UPDATE users SET power=power-$amount WHERE user_id='$sender'
UPDATE users SET power=power+$amount WHERE user_id='$receiver'
- Были ли какие-либо ошибки из "триггера проверки"?
- Если есть, то отправьте
rollback
в базу данных и сообщите пользователю, что пошло не так. - Если нет, то отправьте
commit
в базу данных.
Транзакция гарантирует, что все три операции будут либо успешными, либо неудачными как единое целое, а ограничение CHECK (реализовано как триггер) гарантирует, что никто не может отдать больше энергии, чем ониесть.