Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Doctrine] zwiększenie stanu magazynowego
Forum PHP.pl > Forum > PHP
zordon
Witam,
czy Doctrine (póki co 1.2) obsługuje zmianę wartości pól w stylu:
stan_magazynowy = stan_magazynowy + 10

W tej chwili robię:
  1. $row->stan_magazynowy = new Doctrine_Expression('stan_magazynowy + 10');

Wadą tego rozwiązania jest to, że obiekt PO ZAPISANIU zamiast aktualnej wartości liczbowej w polu stan_magazynowy posiada to co przypisałem, czyli Doctrine_Expression('stan_magazynowy + 10')
"Odświeżam" ponownie obiekt ręcznie ale zastanawiam się, czy ktoś nie wymyślił jakiegoś bardziej eleganckiego i automatycznego rozwiązania
Crozin
Jeżeli $row to obiekt-encja to dla czego nie zrobisz po prostu $row->stan_magazynowy += 10;?
zordon
bo w przypadku gdy 2 użytkowników zechce pobrać towar z magazynu w idealnie tej samej chwili poleca do bazy 2 zapytania, ktore "nadpiszą" się nawzajem.
np początkowy stan: 10
user 1 zabiera 1 szt,
user 2 zabiera 2 szt
łącznie zabierają 3 szt.
Do bazy przy dużym ruchu mogą pójść zapytania:
  1. UPDATE magazyn SET stan_magazynowy=9 WHERE ...
  2. UPDATE magazyn SET stan_magazynowy=8 WHERE ...

stan magazynu po zakończeniu obu transakcji: 8, a powinno być 7

W przypadku
  1. UPDATE magazyn SET stan_magazynowy=stan_magazynowy-1 WHERE ...
  2. UPDATE magazyn SET stan_magazynowy=stan_magazynowy-2 WHERE ...

będzie ok
Crozin
Słowo klucz: transakcje (ale takie w bazie danych) i poziomy transakcji.

Cytat
W przypadku
  1. UPDATE magazyn SET stan_magazynowy=stan_magazynowy-1 WHERE ...
  2. UPDATE magazyn SET stan_magazynowy=stan_magazynowy-2 WHERE ...


będzie ok
W takim czymś problem jest dokładnie taki sam.
zordon
używam transakcji w tabelach innodb i rozwiązanie stan_magazynowy=stan_magazynowy-x wciąż wydaje mi się lepsze.
W transakcji rekordy nie mogą nadpisywać tych samych rekordów, ale mogą je czytać, czyli w zapisie "stan_magazynowy=x" problem pozostaje. W rozwiązaniu "stan_magazynowy=stan_magazynowy-x" najgorsze, co może się stać to "wyjechanie" ze stanem magazynowym poniżej zera, ale to można obsłużyć już po zakończeniu transakcji (np cofając problematyczne zamówienie już po zakończeniu transakcji).
Wiem, że można zablokować rekordy również do odczytu ale tego tematu nie znam zbyt dobrze. Z tego co kojarzę to odczyt zablokowanego rekordu przez inną transakcję spowoduje wystąpienie błędu, a nie o to przecież chodzi.

Mógłbyś rozwinąć trochę temat i podać najlepszą praktykę rozwiązania tego typu problemu?
Crozin
1. Upewnij się, że masz wyłączony autocommit.
2. PDO jak zwykle nie popisało się swoimi możliwościami - poziomu izolacji transakcji nie ustawisz za jego pomocą.
3. Musisz więc ręcznie to zrobić, np. w przypadku MySQL: http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html bądź PostgreSQL: http://www.postgresql.org/docs/9.1/static/...ransaction.html
4. Poziom, który Ciebie interesuje to co najmniej READ COMMITTED.
zordon
READ COMMITED + FOR UPDATE w select
dzięki za pomoc!
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.