deleted......
я не понимаю как может срабатывать ваша проверка т.к. я не вижу где устанавливается нулевой элемент массива $protect---------- Добавлено в 03:33 ---------- Предыдущее сообщение было в 03:17 ----------
заметьте, эта заявка все равно будет обработана, хотя пользователь заблокирован
что будет если селект вернет только одну запись?
у вас получается нельзя пользоваться вашим сервисом чаще чем раз в сутки на одинаковую сумму?
собственно, непонятно зачем делать эту проверку вообще. вы в этом скрипте должы взять запись, проверить баланс, если деньги есть - отослать, обновить баланс. после этого просто перейти к следующей записи. если будет запись от этого хакера, то проверка на баланс просто не пройдет.
PS подумайте что произойдет если в базе появится запись в момент когда ваш код пройдет эту проверку, но до апдейтов.
боюсь что хацкеру плевать на формочки-кнопочки, он напрямую в скрипт долбится. чтобы ваш вариант работал надо продумывать схему с рандомным числом каким-нибудь для этой кнопочки и проверять потом его. хрень редьки не слаще.
да
используйте функцию GET-LOCK из MySQL вместо флок, это намного проще. в качестве имени лока используйте логин пользователя.
вначале своего скрипта дергаете эту функцию и все. если кто-то уже положил лок и держит его, то ваш вызов будет просто тупо ждать пока лок не освободится, никаких if не надо.
на выходе из скрипта делайте RELEASE_LOCK
конечно, это даже распараллелит процесс. при условии что ваша pay функция не пишет в какие-нибудь общие для всех пользователей переменные.
вот здесь почитайте http://stackoverflow.com/questions/2921469/php-mutual-exclusion-mutex
sleep() - это только один из многих операторов который приводит к такому эффекту. напр. любой оператор IO тоже обладает таким же свойством. более того, sleep и иже с ним только резко повышают такой ход событий, на самом деле и без них такое может случится. выполнение вашего кода может быть прервано в абсолютно любой точке программы и вы на это влиять не можете. это называется "вытесняющая многозадачность".
та проблема о которой я написал лечится созданием флага, который говорит "сейчас этот скрипт занят, ждите". флагом может быть напр. просто файл. алгоритм
1. проверить, есть ли файл lock
2. если есть - спать 2-3 секунды, и идти к п.1
3. если нет - создать
4. после этого вся ваша функция
5. в конце функции удалять файл lock
о чем нужно беспокоится
а) у вас много exit() - соответственно нужно переделать, чтобы эти exit() удаляли файл lock перед выходом
б) возможна ситуация когда компьютер сбойнет в то время когда этот файл существует, это приведет к бесконечному циклу при старте. это значит что перед запуском вашего приложения нужно убедиться что такого файла нет, если есть - удалить ручками. собственно, любая ошибка которая может случится в этой функции должна не просто прекращать работу функции, а удалять этот файл.
возможно, кто-нибудь, кто знает MySQL лучше меня, расскажет как такое же можно сделать используя БД, а не файл. скорее всего это будет более правильным решением, особенно если использовать транзакции и внутри них лочить таблицы.
это самое простейшее решение, работает если транзакции редки. если у вас десятки транзакций в секунду, то надо делать совершенно по-другому, полностью менять архитектуру вашего приложения.
читайте внимательно что вам пишут. повторю - выполняется первый запрос включая проверку if($summa > balance($login)). В этот момент, до снятия с баланса, приходит второй запрос. выполнение первого запроса может прерваться и процессор пойдет выполнять второй запрос. и может полностью отработать второй запрос и после этого вернуться продолжать выполнять первый запрос. деньги сняты вторым запросом, проверка в первом запросе уже пройдена. вероятность такого поведения сильно повышается если у вас в коде используются некоторые операторы, один из которых sleep.
добро пожаловать в многозадачные операционные системы.
именно поэтому я и говорю - нужен весь код если вы хотите чтобы вам нашли ошибку. то, что вы делаетет какие-то проверки, это не видно совершенно. более того, в первом посте вы сумму брали напрямую из $_POST . мы должны догадаться что там уже что-то проверено? гадать как-то надоедает. нет кода - я умываю руки, я не телепат.
как вы хотите чтобы вам нашли баги, если код обрезан??? 😮
а ведь это очень важно, дьявол в деталях
я вам уже предложил подумать, что будет если у вас есть пользователи vasya1, vasya2, vasya3 и vas%. Что вернет проверка баланса с вашим любимым like для пользователя vas% ? для какого реально пользователя будет возвращен баланс? я вот не знаю. и скажу вам по секрету, никто не знает.
это один вариант развития событий.
другой вариант - что происходит если сумма передается в этот код отрицательная? я не знаю, т.к. код не полный.
третий вариант событий. предположим пришел запрос, начинает выполняться, прошел проверку if($summa > balance($login)) и в этот момент приходит второй запрос. первый запрос перестает выполняться, выполняется второй запрос, выполнился полностью и процессор вернулся к выполнению первого запроса. заметьте, проверка баланса в первом запросе уже прошла, и прошла удачно, о том что деньги сняты вторым запросом, первый запрос ничего не знает. кстати именно во время sleep и происходит переключение контекста.
1. выложите весь код, если хотите получить советы по коду
2. записывайте в файл все что приходит на вход этой функции, чтобы видеть, не подставляются ли левые данные типа отрицательной суммы.
3. отдайте эту часть сделать профессионалу, дешевле будет.
баян, но уж больно в тему
эта строчка вообще лишняя, буквально в следующей опять та же проверка идет