Doctrine toplama işlemi

50 views
Skip to first unread message

Selim Can CABA

unread,
Aug 16, 2016, 1:48:43 PM8/16/16
to Symfony 2 Turkish Users
Merhaba,

Bir kullanıcının coin'ini arttırmak istiyorum fakat bu işlem aynı anda iki php dosyası yaparsa çakışma oluyor. 
Arkaplanda çalışan bir php dosyam var diyelim ki o user'ı 20:00 da database'ten aldı 20:02 dede güncelleme sorgusu gitti 20:01 de başka bir php dosyası güncelleme yaparsa o işlem geçersiz oluyor.

Örneğin; aşağıdaki gibi kullanıcı coini arttırdım bu durumda database'e "set coin = 15 şeklinde" sorgu gidiyor. Ben "set coin = coin + 10" şeklinde giderse bu çakışmanın önüne geçebileceğimi düşünüyorum.

$user->setCoin( $user->getCoin() - 10 );

Bunun için doctrine ile dql sorgusu göndermek mantıklı mıdır? Doctrine tarafında addCoin gibi bir method yapabilir miyim?

Teşekkürler.


Osman Üngür

unread,
Aug 16, 2016, 2:39:18 PM8/16/16
to symfon...@googlegroups.com
Update AppBundle:Comment c Set v.upvote = v.upvote + 1 where v.id....

gibi bir dql ile denermisin?

Bu tarz queryler için orm çok uygun değil. Çünkü orm önce db den load eder sonra memory de tuttuğu db objesini update edip Persist eder. Yani atomik değildir. 

Ya bahsettiğim dql ile yada doktrine dbal ile normal sql query yazarak atomik güncelleme yapabilirsiniz. 

Sevgiler 

Sent from my iPhone
--

---
Bu iletiyi Google Grupları'ndaki "Symfony 2 Turkish Users" grubuna abone olduğunuz için aldınız.
Bu grubun aboneliğinden çıkmak ve bu gruptan artık e-posta almamak için symfony-2-tr...@googlegroups.com adresine e-posta gönderin.
Daha fazla seçenek için https://groups.google.com/d/optout adresini ziyaret edin.

Selim Can CABA

unread,
Aug 16, 2016, 2:49:13 PM8/16/16
to Symfony 2 Turkish Users
Cevabınız için teşekkürler. En doğru şekilde yapmaya çalışıyorum. İlk aklıma entity manager kullanmak yerine query göndermek geldi fakat daha iyi bir çözümü olabilir diye sizlere danışmak istedim. Geçici olarak $em->refresh() yaptım. Yazdığınıza benzer bir dql yazıcam toplama işini database'e bırakınca sorun temelli çözülür umarım.

İyi akşamlar.


16 Ağustos 2016 Salı 20:48:43 UTC+3 tarihinde Selim Can CABA yazdı:

Osman Üngür

unread,
Aug 17, 2016, 8:23:37 AM8/17/16
to symfon...@googlegroups.com
Eger isiniz tamamen atomik ise atomik sekilde increment decrement yapan redis, memcached gibi bir yerde datayi tutmanizi da onerebilirim.
em->refresh sonucta datanin son halini db den load edecektir.

Ancak kodunuz icin "sanssiz bir zamanlama” bu durumda da race condition olusmasina neden olur. Native query secenegi bu noktada en mantiklisidir.


Volkan Altan

unread,
Aug 17, 2016, 9:01:53 AM8/17/16
to symfon...@googlegroups.com
Selam,

Data kritik ve işlem yoğunsa ise direk Redis kullanın. Daha sonra redisdeki datayı DB ye belli aralıklarla alabilirsiniz.

Osman +1 :)

Selim Can CABA

unread,
Aug 17, 2016, 9:29:33 AM8/17/16
to Symfony 2 Turkish Users
Değerli yorumlarınız için teşekkürler. 

Veriye web dışında yine symfony altyapılı olan websocket ve rabbitmq consumer, arttırma veya eksiltme işlemi yapıyor. 
Data kritik fakat proje henüz tutmadığı için işlem fazla yoğun değil.

İlk olarak ilgili alanlardan setter'ları kaldırıp ayrı native query'ler göndericem.
Session'ları redis'e almayı düşünüyordum redis'i projeye dahil ederken önerinizi değerlendiricem.




16 Ağustos 2016 Salı 20:48:43 UTC+3 tarihinde Selim Can CABA yazdı:
Merhaba,

Kingem Kurdam

unread,
Aug 17, 2016, 9:39:59 AM8/17/16
to symfon...@googlegroups.com

Bu tür işlemler için row lock yapmak daha mantıklı
Eğer mysql innodb kullanıyorsanız.
http://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

Bir projede başıma gelmişti yuksek yük altında bakiyelerde tutarsızlık oluşmuştu lock ile çözmüştüm.


17 Ağu 2016 ÖS 4:29 tarihinde "Selim Can CABA" <slm...@gmail.com> yazdı:

--

---
Bu iletiyi Google Grupları'ndaki "Symfony 2 Turkish Users" grubuna abone olduğunuz için aldınız.
Bu grubun aboneliğinden çıkmak ve bu gruptan artık e-posta almamak için symfony-2-tr+unsubscribe@googlegroups.com adresine e-posta gönderin.

Selim Can CABA

unread,
Aug 17, 2016, 9:59:37 AM8/17/16
to Symfony 2 Turkish Users
Row lock hakkında pek bilgim yok. Tablo kilitli olduğunda sorguyu redderse pek çözüm olacağını sanmıyorum fakat kuyruk mantığında ise gayet güzel olur.

Eksiltme/arttırma işlemlerini database'e yaptırdığınız halde mi tutarsızlık oldu? Eğer öyleyse daha fazla önlem almak gerekecek :)

Teşekkürler.



17 Ağustos 2016 Çarşamba 16:39:59 UTC+3 tarihinde Abdulkadir Mutlu yazdı:
Bu grubun aboneliğinden çıkmak ve bu gruptan artık e-posta almamak için symfony-2-tr...@googlegroups.com adresine e-posta gönderin.

Kingem Kurdam

unread,
Aug 17, 2016, 11:06:13 AM8/17/16
to symfon...@googlegroups.com

Sorguyu reddetmiyor sadece bekletiyor.
Prod ortaminda yuksek yuk altinda kac yildir problemsiz calisiyor isterseniz kodu. Yazdiktan sonra test yazip kodun duzgun çalışıp calismadigina bakabilirsiniz.


17 Ağu 2016 ÖS 4:59 tarihinde "Selim Can CABA" <slm...@gmail.com> yazdı:
Bu grubun aboneliğinden çıkmak ve bu gruptan artık e-posta almamak için symfony-2-tr+unsubscribe@googlegroups.com adresine e-posta gönderin.

Selim Can CABA

unread,
Aug 17, 2016, 11:10:26 AM8/17/16
to symfon...@googlegroups.com


Güzelmiş, row lock'u arastırıcam. Tesekkürler.


17 Ağu 2016 18:06 tarihinde "Kingem Kurdam" <kingem...@gmail.com> yazdı:

Yılmaz Süslü

unread,
Aug 28, 2016, 6:45:43 PM8/28/16
to Symfony 2 Turkish Users
Çünkü 20:00 da okuyup 20:02 de sonucu db'ye yazmaya çalışan kodun okuduğu veri 20:01 de değişmiş oluyor. Yapmak istediğiniz operasyon Abudlkadir'in dediği gibi LOCK kullanmanızı gerektiriyor. Ancak lock operasyonunu DB seviyesinde değil Doctrine (uygulama) seviyesinde yönetmenizi tavsiye ederim.

Doctrine native olarak birkaç farklı LOCK mekanizması sunuyor, şu dökümanı okumanızı öneririm:


Çözümlerden biri tabloya basit bir "version" sütunu açmayı gerektiriyor. Pessimistic Locking kısmını özellike okumanızı tavsiye derim.

Selim Can CABA

unread,
Aug 28, 2016, 8:02:48 PM8/28/16
to symfon...@googlegroups.com
Merhaba, ilgili alanları dql'e çevirdim. Şu an için tutarsızlık olmayacak gibi gözüküyor fakat bakiye kontrolü gibi durumlarda yine şansız bir zamanlama olursa bakiye eksiye inecek gibi gözüküyor. Dediğiniz gibi lock kullanmak gerekli. 
Henüz lock ile ilgili bir çalışma yapmadım, dökümanı attığınız için teşekkürler. Mümkün olduğunca uygulama katmanında yapmak istiyorum, doctrine de bu özellik olması güzel oldu.

29 Ağustos 2016 01:45 tarihinde Yılmaz Süslü <yilma...@gmail.com> yazdı:
Reply all
Reply to author
Forward
0 new messages