За последние 24 часа нас посетили 31959 программистов и 1756 роботов. Сейчас ищут 922 программиста ...

innoDB и блокировка строки

Тема в разделе "PHP для новичков", создана пользователем 234you, 1 дек 2012.

  1. 234you

    234you Активный пользователь

    С нами с:
    31 июл 2012
    Сообщения:
    18
    Симпатии:
    0
    Всем доброго времени суток.
    Искал информацию в гугле. Информации вроде много - в голове каша.
    Исходные данные:
    1)Таблица innoDB
    2) Мне нужно, чтоб при UPDATE была блокировка такого рода, что пока этот UPDATE не завершится - другой пользователь не сможет ни прочитать данные из этой строки, ни изменить.
    $updatov = mysql_query("UPDATE `tovar` SET `tsena` = 'tsena' + 1 WHERE `tov` = 'mon' ");

    Я не совсем понимаю нужно ли вообще что-то дописывать, чтоб блокировалось. Просто необходимо, чтоб, если 5 пользователей одновременно обратятся к этому запросу, чтоб `tsena` стала именно +1+1+1+1+1, то есть +5 в общем.
     
  2. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Нет, ничего дописывать не нужно. Блокировка при UPDATE - это WRITE LOCK, то есть, полная.
     
  3. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    Нет, не нужно, если это одна операция, то база сама все сделает.

    Добавлено спустя 53 секунды:
    Блокировка только этой строки ;)
     
  4. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Код (PHP):
    1. $updatov = mysql_query("UPDATE `tovar` SET `tsena` = 'tsena' + 1 WHERE `tov` = 'mon' "); 
    Кавычки неправильные (вокруг tsena справо от знака равенства). Надо в обоих случаях косые.
    Код (PHP):
    1. $updatov = mysql_query("UPDATE `tovar` SET `tsena` = `tsena` + 1 WHERE `tov` = 'mon' "); 
     
  5. 234you

    234you Активный пользователь

    С нами с:
    31 июл 2012
    Сообщения:
    18
    Симпатии:
    0
    Спасибо ребят!
    А если операции 2-3?
    Если например человек попробует совершить 2 операции влияющие на 1 строку одновременно на 2 компьютерах?
    К примеру одно действие отвечает за покупку, второе за продажу. Обе влияют на его баланс. Если он на 2 компах одновременно ткнёт купить/продать. Сработает ли всё как надо или может не среагировать на одно из действий?
    Чтоб понятнее было
    1 случай
    Код (Text):
    1. $update_userbal = mysql_query("UPDATE `users` SET `baltot` = `baltot` + '".$sellcost." WHERE `usernume` = '".$ushar_ex['usernume']."'");
    2 случай
    Код (Text):
    1. $update_userbal2 = mysql_query("UPDATE `users` SET  `baltot` = `baltot` - '".$round."' WHERE `usernume` = '".$ushar_ex['usernume']."'");
    Спасибо) я просто изменял параметры, чтоб меньше код получился и случайно описАлся.
     
  6. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    По идее, действия совершатся последовательно, в соответствии с тем, в какой последовательности были запрошены.
     
  7. 234you

    234you Активный пользователь

    С нами с:
    31 июл 2012
    Сообщения:
    18
    Симпатии:
    0
    То есть 99.9% что мои опасения можно исключить? Вопрос просто в деньгах (хоть и не моих; - пользователей), но всёже не хотелось, чтоб какой-то умник воспользовался. А умники всегда находятся :)
     
  8. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    До тех пор, пока ваш скрипт для достижения цели будет использовать только один запрос - проблем не будет.
    Как только вы захотите использовать два и более, например
    sql: select `baltot`...
    php: $baltot += 100500;
    sql: update ... `baltot` = $baltot
    то нужно использовать транзакцию или другие механизмы (например, select for update).
     
  9. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Это на 100%. Как заметил MiksIr, под выражением "несколько операций" подразумевается несколько запросов, которые должны обработаться по-очереди, без вклинивания лишних между ними. Тогда надо делать ручную блокировку или транзакцию.
    Более того, InnoDB в транзацию неявно оборачивает каждый запрос, поэтому конфликты совершеннно исключены.
     
  10. 234you

    234you Активный пользователь

    С нами с:
    31 июл 2012
    Сообщения:
    18
    Симпатии:
    0
    Я понял. значит не совсем верно задал вопрос изначально. Запросов идет несколько:
    Код (Text):
    1.  
    2. $coinsell = ($ushar_exgold-1);
    3. $update_coin = mysql_query("UPDATE `users` SET `coinsell` = `coinsell` + 1 WHERE `usernume` = '".$admin_saitului."'");
    4.         $update_userbal = mysql_query("UPDATE `users` SET `baltot` = `baltot` + '".$sellcost."', `coinsell` = `coinsell` + 1 WHERE `usernume` = '".$ushar_ex['usernume']."'");
    5.             $curmon = ($ushar_exbal+$sellcost);
    6.             $cerereSQL =  "INSERT INTO `history` (`action`, `amount`, `userid`, `curcoin`, `curbal`, `time`, `date`, `user`, `cost`, `soldfor`)
    7.                   VALUES ('sellgold', '1', '".$ushar_ex['id']."', '".$coinsell."', '".$curmon."', NOW(), CURDATE(), '".$ushar_ex['usernume']."', '".$cost."', '".$sellcost."')";
    8.     mysql_query($cerereSQL);
    Как обезопаситься от вклинивания?
     
  11. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44