PHP ve eşzamanlılık

8 Cevap php

Ben genel olarak dil üzerinde çalışma beni açmıştır son zamanlarda PHP bazı web geliştirme çalışmaları yapıyorum. Bugüne kadar ben bir veritabanı ile etkileşim için kullanmak gerekli değildir, ama ben bunu yapmak için uygun bir çok fonksiyonu sağlar biliyor.

Ben temel SQL bilmek ve bir veritabanındaki verilere temel manipülasyon ile çalışmış olmasına rağmen, ben PHP / JavaScript / SQL etrafında kendi web sitelerini temel web geliştiricileri aynı anda aynı verileri değiştirerek kullanıcılarını yönetmek edebiliyoruz nasıl anlamıyorum.

Örneğin, onlar kaydolmak zaman iki takım birine kullanıcıları bölen bir blackjack web sitesi var diyelim. Bir kullanıcı oyunu kazanır her zaman, kendi kazançların bir bölümü bu takım için çalışan toplam eklenir.

Yani bu böyle bir şey görünüyor bunu fonksiyonu için sözde kod Diyelim ki:

... 
$total = mysql_query("SELECT score FROM team1");
$total = $total + $mytotal;
mysql_query("UPDATE team1 SET score='".$total."'");
...

İki oyuncu aynı anda oynuyorsanız, bu diğeri öyle bir kullanıcılar değişiklikler derhal yazılır olacak, masa artırmak ve güncellemek için bir şans var önce ikisi çağrı SEÇ olacağı çok mümkün.

Benim soru nasıl biri bu önlemek mi, nedir? Bu kod düzeyinde PHP kullanılarak yapılır, ya da bunu önlemek için bu yardım kullandığınız her türlü veritabanı tarafından sağlanmaktadır özellikleri vardır mı?

Ben biraz araştırma yaptım, ve PHP semaphore mekanizma sağlamaz, ve ben de mysql bir LOCK table feature sunuyor fark ettik gibi görünüyor. Ancak, ben, ya da eğer, uygulamada kullanılan bu hangi emin değilim.

8 Cevap

Gerçek dünya sorun, bu basit örnekte daha büyük EĞER, emin kullanıcılarının birbirleri üzerine yok yapmak için kilit tabloları ile birlikte bir işlem kullanmalısınız.

PHP çoklu iş parçacığı için tasarlanmış bir dil değil, ve ben hiç olacak sanmıyorum.

Eğer muteksin işlevselliği gerekiyorsa, PHP içeri derleme bir Semaphore işlevleri vardır

Memcache hiçbir muteks yeteneği vardır, ama Memcache kullanılarak taklit edilebilir :: () yöntemini ekleyin.

Bir MySQL veritabanı kullanıyor, ve yarış durumu yolsuzluk bazı tür önlemek için çalışıyorsanız, size kilit tablo deyimi veya kullanım işlemleri kullanabilirsiniz.

Aynı anda birden isteklerini yapabilirsiniz yük test aracı ile kod vurma deneyebilirsiniz. Jmeter akla geliyor.

Ben yukarıdaki cevapların hiçbiri bir tasarım kusur olarak çalışıyor olabilir işaret olduğunu inanamıyorum.

Tüm cevaplar doğru Evet, mysql yarış koşulları ve tablolar birbirini dışlayan erişim işleyebilir.

Eğer böyle bir sorun rastlamak Ancak, bu tasarım yeniden düşünmek muhtemelen zamanıdır. Neden onların kazançlarının bir kısmını ekledi kim için bir kullanıcı kimliği tutuyor değil mi? Eğer bir olabilir:

    INSERT INTO team1(userid, amount) VALUES(32, 100);
    SELECT SUM(amount) FROM team1
or
    REPLACE INTO team1 SET amount = $total

Beni Ama eğer, ben bile rahatsız olmaz. Ben sadece set_cookie (team_score, team_score + miktarı) olacak ve her istemci tarafında tutun. Ben skoru okumak istersiniz zaman ben okumak veya sunucuya yazmak ve hala uyumsuz istemci arabirimi güncelleştirmek için bir AJAX isteği yangın. Eğer web geliştirme temel olduğuna işaret beri ben bugüne kadar bunu başarmak için en kolay yolu olduğu gibi asenkron istemci-sunucu iletişimi için jQuery çerçeve bakabilirsiniz öneririz.

EDIT: Ve başka bir oyuncu skoru bir miktar ekler herkesin UI güncelleme sorunu için, onlar hemen güncellemeleri olsun böylece oyuncuların müşteri için güzel senin veri modeli tayt backbone.js içine bakmak öneririz zaman skor değişir.

Veritabanları eşzamanlılık kontrolü yerleşik var, örneğin postgres eşzamanlılık kontrolü hakkında okuyabilirsiniz here. Eğer haklıysam, pgsql tarafından varsayılan ayarlar iyimser kilitleme ve her işlemin diğer kaydedilmemiş işlemleri ile yapılan değişikliklerden haberdar olduğu anlamına gelir kararlı hareket yalıtım, okuyun.

Eğer durumda bu ayarlar tamam, bu yüzden UPDATE team1 SET score = score + mytotal basitçe yapabilir ve veritabanı iyi eşzamanlılık konuları ele alacaktır.

Eğer uzun bir seçmek varsa - güncelleme sorunu, o zaman ilk önce bir SELECT FOR UPDATE sorgu ile seçtiğiniz elle satırları kilitleyebilirsiniz.

Bunlar şu anda en iyi uygulamalar vardır ...

DB de mantığı tutmak, bu semantik çoğunlukla sizin için çözüldü.

update teams
set score = score + 1
where team_id = 1

.. Veya ne olursa olsun puan ve ne olursa olsun takım sayısı.

Büyük veritabanları gibi durumları işlemek için tasarlanmıştır.

MySQL kullanırken, InnoDB depolama motoru yazılı olan satır kilitleyen satır kilitleme özelliği vardır. Yani, aynı satır için herhangi bir güncelleme isteği satır tamamlanıncaya önceki operasyonda kadar bekler.

Eğer MyISAM depolama motorunu kullanırsanız bir satır güncellendi edilirken, bu tüm tabloyu kilitler. Yani birden fazla oyuncu aynı anda güncelleme isteklerini itmek sunucu üzerinde bir şok bobini oluşturur. Yani hepsi ne veritabanı hakkında ve amaç için özellikle kullanıyorsanız ne depolama motorudur.

Veritabanı eşzamanlı kilitleme yönetir ve değişiklikler atomik yapılır sağlar. Bu ACID işlemleri destekleyen bir veritabanı kullanarak bir şeydir.

Çoğu durumda değişiklikler kilit çekişme az olduğunu yeterince hızlı. Ama yine de olabilir, bu yüzden hata durumu bir SQL sorgusu çalıştırmak sonra iade için kontrol etmeniz gerekir. mysql_query() function döner FALSE bir problem varsa.

Sonra arayarak nedenini (güncelleştirme çakışması, yetersiz izinler, SQL sözdizimi hatası, vb) anlamaya almak mysql_errno(). http://dev.mysql.com/doc/refman/5.1/en/error-messages-server.html MySQL hata kodu referans için bkz.

Ben kesinlikle gerekmedikçe eşzamanlılık kaygıları tanıtmak değil, Xepochs cevap katılıyorum. Konusunda büyük bir cevap için farklı kilitleme stratejiler here bkz.