PDO'da kalıcı bağlantı kullanmanın dezavantajları nelerdir


181

PDO'da bağlantı, PDO::ATTR_PERSISTENTöznitelik kullanılarak kalıcı hale getirilebilir . Php kılavuzuna göre -

Kalıcı bağlantılar komut dosyasının sonunda kapatılmaz, ancak başka bir komut dosyası aynı kimlik bilgilerini kullanarak bir bağlantı istediğinde önbelleğe alınır ve yeniden kullanılır. Kalıcı bağlantı önbelleği, bir komut dosyasının bir veritabanıyla her konuşması gerektiğinde yeni bir bağlantı kurma yükünü önlemenize olanak tanır ve bu da daha hızlı bir web uygulaması sağlar.

Kılavuz ayrıca, PDO ODBC sürücüsünü kullanırken kalıcı bağlantı kullanılmamasını önerir, çünkü ODBC Bağlantı Havuzu Oluşturma işlemini engelleyebilir.

Görünüşe göre PDO'da son durum dışında kalıcı bağlantı kullanmanın bir dezavantajı yok gibi görünüyor. Bununla birlikte, bu mekanizmayı kullanmanın başka dezavantajları olup olmadığını bilmek istiyorum, yani bu mekanizmanın performans düşüşü veya bunun gibi bir şeyle sonuçlandığı bir durum.


Vay canına, bu basit soru için 1000 temsil ödeydin mi?
Pacerier

Yanıtlar:


287

Lütfen burada özetlenen sorunları azaltmanın yollarını açıklayan bu cevabı aşağıda okuduğunuzdan emin olun .


Kalıcı bağlantılar yapan diğer PHP veritabanı arabirimlerinde olduğu gibi PDO kullanılarak aynı dezavantajlar vardır: komut dosyanız veritabanı işlemlerinin ortasında beklenmedik bir şekilde sonlanırsa, kalan bağlantıyı alan bir sonraki istek ölü komut dosyasının kaldığı yerden devam edecektir. Bağlantı, PHP düzeyinde değil, işlem yöneticisi düzeyinde (mod_php için Apache, FastCGI kullanıyorsanız geçerli FastCGI işlemi, vb.) Açık tutulur ve PHP, üst sürece bağlantının ne zaman ölmesine izin vereceğini bildirmez komut dosyası anormal olarak sona erer.

Ölü komut dosyası tabloları kilitlediyse, bağlantı sona erene veya bu bağlantıyı alan bir sonraki komut dosyası tabloların kilidini açana kadar bu tablolar kilitli kalır.

Ölü komut dosyası bir işlemin ortasındaysa, kilitlenme zamanlayıcısı devreye girene kadar çok sayıda tablo engelleyebilir ve o zaman bile kilitlenme zamanlayıcısı, soruna neden olan eski istek yerine daha yeni isteği öldürebilir.

Ölü komut dosyası bir işlemin ortasındaysa, bu bağlantıyı alan sonraki komut dosyası da işlem durumunu alır. Bir sonraki betiğin gerçekte mevcut işlemi gerçekleştirmeyi denememesi veya olmaması gerektiğinde işlemesi veya olmaması gerektiğinde geri alınması çok olasıdır (uygulama tasarımınıza bağlı olarak).

Bu sadece buzdağının ucu. Her bir komut dosyası isteğinde kirli bir bağlantıdan sonra her zaman temizlemeye çalışarak bir ölçüde hafifletilebilir, ancak veritabanına bağlı olarak bir acı olabilir. Eğer olarak veritabanı bağlantıları oluşturmak belirledik sürece bir darboğaz olan bir şey komut dosyanızda (bu araçlar kullanmakta profilleme bitti kod ettik Xdebug ve / veya xhprof ), sen gerektiğini değil bir şey bir çözüm olarak kalıcı bağlantıları düşünün.

Ayrıca, çoğu modern veritabanının (PostgreSQL dahil), düz vanilya PHP tabanlı kalıcı bağlantıların yaptığı derhal dezavantajları olmayan bağlantı havuzu oluşturmanın kendi tercih ettiği yolları vardır.


Bir noktayı açıklığa kavuşturmak için işyerimde kalıcı bağlantılar kullanıyoruz, ancak seçim yapmıyoruz. Uygulama sunucumuzdan veritabanı sunucumuza ilk bağlantının tam olarak üç saniye sürdüğü garip bağlantı davranışı ile karşılaşıyorduk . Bunun bir çekirdek hatası olduğunu düşünüyoruz. Rastgele gerçekleştiği ve talep üzerine yeniden üretilemediği için sorun gidermeye çalıştık ve dış kaynaklı BT'miz bunu takip etme konusunda somut bir kabiliyete sahip değildi.

Ne olursa olsun, depodaki insanlar birkaç yüz gelen parçayı işlerken ve her parça yarım saniye yerine üç buçuk saniye sürüyorsa, hepimizi kaçırmadan ve onlara yardım etmemiz için harekete geçmeliydik. Bu nedenle, ev tipi ERP / CRM / CMS canavarlığımızda birkaç bit açtık ve kalıcı bağlantıların tüm korkularını ilk elden yaşadık. Görünüşte rastgele meydana gelen tüm küçük sorunları ve tuhaf davranışları izlememiz haftalar sürdü . Kullanıcılarımızın uygulamamızdan özenle sıktığı haftada bir kez meydana gelen ölümcül hataların kilitli tablolar, terk edilmiş işlemler ve diğer talihsiz sakat durumlar bıraktığı ortaya çıktı.

Bu hıçkırık hikayesinin bir anlamı var: Performansta hiç kırılmayı beklemediğimiz şeyleri kırdı. Ödemeye değmezdi ve kullanıcılarımızdan bir isyan olmadan normal bağlantılara geri dönebileceğimiz günü hevesle bekliyoruz.


2
Umarım çalıştırmadan önce bu cevabı okumuştumSELECT orders.* FROM orders LEFT JOIN items USING(item_id)
Ast Derek

31
Yaklaşık on yıldır sürekli bağlantı kullanan büyük bir web sitesi biliyorum. Hile, DB uzantısının üstünde bir katman kullanıyor ve kullanılarak temizlenmesi gereken şeyleri hatırlamasını sağlıyor register_shutdown_function(). İşlem sona ererse, bağlantı da ölür. Başlamazsa, bağlantı temiz durumuna sıfırlanır (örneğin, açık işlemler geri alınır). Bu başarısız olursa, bağlantı kapatılır ve aynı işleme bir sonraki istekle yeni bir bağlantı açılır. Kalıcı bağlantıları şeytanlaştırmaya gerek yoktur.
Walter Tross

Merak ediyorum @Charles ... sorununuz hiç çözüldü mü?
Tschallacka

@MichaelDibbets Uygulama sunucusunu birkaç ay önce değiştirdik ve üç saniyelik hatanın hala etrafta olup olmadığını görmek için pconnect'i çevirdik. Öyle değildi. Sanırım proxy tarafından çözüldü. İle ilgili olarak aşağıda cevap mysqli_change_usermuhtemelen hala insanlar için en iyi çözüm olduğunu var olmayan devlet sorunlarla başa çıkmak için tasarlanmış bir uygulamada kalıcı bağlantıları yapmak.
Charles

5
Bir DNS + IPv6 sorunu olarak izole etmeyi başardığımız bağlantıda 5 saniyelik bir gecikmemiz vardı. Sunucu başarısız oldu ve sonra IPv4 adresini kullanarak bir v6 adresi arıyordu.
Nigel Atkinson

45

Charles'ın yukarıdaki sorununa yanıt olarak,

Gönderen: http://www.php.net/manual/en/mysqli.quickstart.connections.php -

Kalıcı bağlantılarla ilgili yaygın bir şikayet, yeniden kullanılmadan önce durumlarının sıfırlanmamasıdır. Örneğin, açık ve tamamlanmamış işlemler otomatik olarak geri alınmaz. Ancak, bağlantıyı havuza koymak ve yeniden kullanmak arasında gerçekleşen yetkilendirme değişiklikleri de yansıtılmaz. Bu istenmeyen bir yan etki olarak görülebilir. Aksine, kalıcı isim, devletin sürdüğüne dair bir vaat olarak anlaşılabilir.

Mysqli uzantısı, kalıcı bir bağlantının her iki yorumunu da destekler: durum kalıcı ve yeniden kullanmadan önce durum sıfırlama. Varsayılan ayar sıfırlanır. Kalıcı bir bağlantı yeniden kullanılmadan önce, mysqli uzantısı mysqli_change_user()durumu sıfırlamak için dolaylı olarak çağırır . Kalıcı bağlantı kullanıcıya yeni açılmış gibi görünür. Önceki kullanımlardan hiçbir eser görünmüyor.

mysqli_change_user()Fonksiyonu, pahalı bir işlemdir. En iyi performans için, kullanıcılar uzantıyı derleme bayrağı MYSQLI_NO_CHANGE_USER_ON_PCONNECTayarlanarak yeniden derlemek isteyebilir .

Güvenli davranış ve en iyi performans arasında seçim yapmak kullanıcıya bırakılmıştır. Her ikisi de geçerli optimizasyon hedefleridir. Kullanım kolaylığı için, güvenli davranış maksimum performans pahasına varsayılan hale getirilmiştir.


+1, karışıklığı başka şekillerde temizlediğimiz için değilse, change_user'ın manuel olarak çağrılmasının tuhaf bilinmeyen durum sorunlarımızı çözüp çözmediğini görmek isterim .
Charles

PDO Postgres kalıcı bağlantıları için eşdeğer nedir? @Charles vardı benzer sorunları var, nerede bir süre sonra kullanıcılar getirme sql gibi sunucu alıyorum - bağlantı beklenmedik bir şekilde kapatıldı Bu muhtemelen sunucu anormal sonlandırılır anlamına gelir Basit SELECT sorgusu (hatta işlemler) çalıştırırken.
Carmageddon

1
@Carmageddon, bu yeni bir soru için daha uygundur, ancak tl; dr, Postgres'in pconnect yapmaması ve bunun yerine harici bağlantı havuzlarından birini kullanmanız gerekir.
Charles

@Charles, bununla ne demek istiyorsun? PDO'nun kalıcı bağlantısını "harici bağlantı havuzları" ile eşdeğer değil mi? ya da ne demek istedin?
Carmageddon

@Carmageddon, Postgres topluluğunun bağlantı havuzuna pconnect'den daha iyi bir çözüm olarak yerleştiği anlamına geliyor. Pgbouncer veya pgpool-II'yi kontrol edin. PDO'nun zaten Postgres'in bağlandığından emin değilim, ama tamamen rocker'ımdan çıkmış olabilirim.
Charles

13

Kalıcı bağlantılar, veritabanınıza bağlanmak (nispeten) uzun zaman aldığında iyi bir fikirdir. Günümüzde neredeyse hiç böyle değil. Kalıcı bağlantıların en büyük dezavantajı, sitenize göz atabileceğiniz kullanıcı sayısını sınırlamasıdır: MySQL aynı anda yalnızca 10 eşzamanlı bağlantıya izin verecek şekilde yapılandırılmışsa, 11. bir kişi sitenize göz atmaya çalıştığında onlar için çalışmaz .

PDO kalıcılığı yönetmez. MySQL sürücüsü yapar. A) kullanılabilir olduklarında ve ana bilgisayar / kullanıcı / şifre / veritabanı eşleştiğinde bağlantıları yeniden kullanır. Herhangi bir değişiklik olursa bağlantı yeniden kullanılmaz. En iyi durum net etkisi, sitenizde farklı kullanıcılara sahip olduğunuz ve onları kalıcı hale getirmenin herhangi bir faydası olmadığı için sahip olduğunuz bu bağlantıların çok sık başlatılması ve durdurulmasıdır.

Kalıcı bağlantılar hakkında anlaşılması gereken en önemli şey, çoğu web uygulamasında bunları KULLANMAMANIZdır. Cazip geliyorlar ama tehlikeli ve neredeyse işe yaramazlar.

Eminim bu konuda başka iş parçacıkları var ama kalıcı bir bağlantı tehlikeli çünkü istekleri arasında devam ediyor. Örneğin, bir istek sırasında bir tabloyu kilitlerseniz ve ardından kilidini açamazsanız, bu tablo süresiz olarak kilitli kalacaktır. Kalıcı bağlantılar, uygulamalarınızın% 99'u için neredeyse işe yaramaz çünkü farklı bağlantıların arasında aynı bağlantının kullanılıp kullanılmayacağını bilmenin bir yolu yoktur. Her web iş parçacığının kendi kalıcı bağlantıları kümesi olacak ve hangi iş parçacığının hangi istekleri işleyeceğini kontrol etmenin hiçbir yolu yoktur.

PHP'nin yordamsal mysql kütüphanesi, mysql_connect'e yapılan sonraki çağrıların farklı bir bağlantı açmak yerine aynı bağlantıyı döndüreceği bir özelliğe sahiptir (beklendiği gibi). Bunun kalıcı bağlantılar ile ilgisi yoktur ve mysql kütüphanesine özgüdür. PDO böyle bir davranış sergilemez


Kaynak Bağlantısı: bağlantı

Genel olarak bunu kaba bir "kural kümesi" olarak kullanabilirsiniz ::

EVET , aşağıdaki durumlarda kalıcı bağlantılar kullanın:

  • Veritabanına erişen yalnızca birkaç uygulama / kullanıcı vardır, yani aynı ana bilgisayarda paylaşılan 200 farklı kullanıcı olduğu için 200 açık (ancak boşta) bağlantıya neden olmazsınız.
  • Veritabanı, ağ üzerinden eriştiğiniz başka bir sunucuda çalışıyor

  • (Bir) uygulama veritabanına çok sık erişir

HAYIR , aşağıdaki durumlarda kalıcı bağlantılar kullanmayın:

  • Uygulamanızın veritabanına yalnızca saatte 100 kez erişmesi gerekir.

  • Bir veritabanı sunucusuna erişen çok, çok sayıda web sunucunuz var

Kalıcı bağlantılar kullanmak, özellikle veritabanına bir ağ üzerinden erişiyorsanız, çok daha hızlıdır. Veritabanı aynı makinede çalışıyorsa çok fazla fark yaratmaz, ancak yine de biraz daha hızlıdır. Ancak - adından da anlaşılacağı gibi - bağlantı kalıcıdır, yani kullanılmasa bile açık kalır.

Buradaki sorun, "varsayılan yapılandırma" da MySQL'in sadece 1000 paralel "açık kanala" izin vermesidir. Bundan sonra, yeni bağlantılar reddedilir (Bu ayarı düzenleyebilirsiniz). Yani - örneğin - her 100 İstemciye sahip 20 Web Sunucunuz varsa ve her birinde saatte sadece bir sayfa erişimi varsa, basit matematik size veritabanına 2000 paralel bağlantıya ihtiyacınız olduğunu gösterecektir. Bu işe yaramaz.

Ergo: Yalnızca çok fazla istek içeren uygulamalar için kullanın.


4
Satırdan sonra cevabınız stackoverflow.com/a/51583/718224
Tony Stark

1
"EVET, kalıcı bağlantılar kullanın, eğer: [...] Veritabanına erişen çok az uygulama / kullanıcı var" ile "Çok fazla istek içeren uygulamalar için kullanın." Ancak ikincisi doğrudur. Durum: Saniyede binlerce istek yüzlerce etkin veritabanı bağlantısına neden olur. Bir sistem doğrusal olarak ölçeklendiğinde, veritabanına bağlantı miktarını da doğrusal olarak ölçeklendirir. Böylece daha fazla istek (daha fazla kullanıcı) daha fazla bağlantıya neden olur. Eğer Yani gerek sınırlı henüz pek aktif bağlantıları istekleri sürü (kullanıcı) olduğunda (!)
Ken Van Hoeylandt

12

Testlerimde, yerel ana bilgisayarımla bir saniyeden fazla bir bağlantı sürem vardı, bu nedenle kalıcı bir bağlantı kullanmam gerektiğini varsayıyorum. Diğer testler bunun 'localhost' ile ilgili bir sorun olduğunu gösterdi:

Saniyeler içinde test sonuçları (php mikrotime ile ölçülür):

  • barındırılan web: connectDB: 0.0038912296295166
  • localhost: connectDB: 1.0214691162109 (bir saniyeden fazla: localhost kullanmayın!)
  • 127.0.0.1: bağlayınDB: 0.00097203254699707

İlginçtir: Aşağıdaki kod 127.0.0.1 kullanmak kadar hızlıdır:

$host = gethostbyname('localhost');
// echo "<p>$host</p>";
$db = new PDO("mysql:host=$host;dbname=" . DATABASE . ';charset=utf8', $username, $password,
    array(PDO::ATTR_EMULATE_PREPARES => false,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

PDO alan adlarını çevirmekte zorlanıyor gibi görünüyor! Teşekkür ederim, her bağlantının neden dört çekirdekli makinemde çok uzun sürdüğünü merak ediyordum!
Mustafa

@Gunnar Bernstein +1 güzel bul. "localhost" kesinlikle daha uzun sürer ve bu benim web app hızını biraz geliştirdi (çok sayıda bağlantı yapar).
imperium2335

1
Bu harika. Geliştirme makinemde bir sorun var ... bir IP kullanarak senaryomu 6.1s'den 1.1s'ye aldı
Pete

localhostsoket bağlantısı kullanır, soket bağlantısı büyük miktarda bağlantıda kötü olduğu için ünlüdür
mente

@mente Bu gerçeği kanıtlayabilecek herhangi bir referans, kaynak? UDS'nin TCP yerine tercih edildiğini düşünmeye meyilliyim. Teşekkürler.
Nuxwin

6

Kalıcı bağlantılar, büyük bir performans artışı sağlamalıdır. Kalıcılıktan kaçınmanız gerektiği varsayımına katılmıyorum ..

Yukarıdaki şikayetler, MyIASM tablolarını kullanan ve tablo kilitlerini kaparak işlemlerin kendi versiyonlarında hacklenen bir kişi tarafından yönlendiriliyor gibi görünüyor. PDO'nun beginTransaction () yöntemini kullanın ve tablolarınızı InnoDB'ye taşıyın.


2
Bir yıl geç fark ettim, ancak kayıt için: masam, tamamen InnoDB tablolarından oluşan bir veritabanından geliyor , sadece tam metin endeksleme desteği için MyISAM bataklığında sıkışmış bir avuç denormalize klon hariç.
Charles

Pfft, Sfenks yaşlı ve baskın, Elastik Arama yeni sıcaklık. Güzel bir gün, aslında sadece yeni uygulamalar yerine eski uygulamalarımız için kullanacağız ...
Charles

PostgreSQL'de tam metin araması gerçek kazanır. İnanılmaz. İşini yapmak için çalışan başka bir araç / sunucu gerektirmez. Verileri senkronize tutma konusunda endişelenmenize gerek yoktur. Çok ayrıntılı kontroller. Birden fazla sözlük veya kendiniz yazın. PostgreSQL otomatik olarak çoklu indeks sorguları kullandığından, çalıştırdığınız herhangi bir sorguya bırakabilirsiniz.
brightball

2
MySQL 5.6, InnoDB tabloları için tam metin desteği sunar.
14'te

2

Bana sürekli bir bağlantı olması daha fazla sistem kaynağı tüketir gibi görünüyor. Belki önemsiz bir miktar, ama yine de ...


Genellikle bilgisayar zamanının mikrosaniye için çok fazla insan ticareti
Andy Chase

1

Kalıcı bağlantıları kullanma açıklaması, MySQL ile diğer veritabanlarına göre çok daha hızlı olmalarına rağmen oldukça maliyetli olan bağlantı miktarını azaltmaktadır.

Kalıcı bağlantılarla ilgili ilk sorun ...

Saniyede 1000 bağlantı oluşturuyorsanız, normalde çok uzun süre açık kalmasını sağlamazsınız, ancak İşletim Sistemi bunu yapar. TCP / IP protokolüne dayanır Bağlantı noktaları anında geri dönüştürülemez ve ayrıca "FIN" aşamasında geri dönüştürülmeden önce bir süre yatırım yapmak zorundadır.

2. sorun ... bir çok MySQL sunucu bağlantısı kullanıyor.

Birçok kişi * max_connections * değişkenini artırabildiğinizi ve MySQL ile 100'den fazla eşzamanlı bağlantı elde edebileceğinizi fark etmez, diğerleri MySQL ile 1024'ten fazla bağlantı iletememe konusunda eski Linux problemleri tarafından dövülmüştür.

Şimdi mysqli uzantısında kalıcı bağlantıların neden devre dışı bırakıldığı hakkında konuşalım. Kalıcı bağlantıları kötüye kullanmanıza ve temel nedeni olmayan düşük performans elde etmenize rağmen. Asıl sebep - onunla çok daha fazla sorun elde edebilirsiniz.

Kalıcı bağlantılar MySQL 3.22 / 3.23 boyunca MySQL çok zor olmadığında PHP'ye konuldu, bu da bağlantıları sorunsuz bir şekilde geri dönüştürebileceğiniz anlamına geliyor. Ancak sonraki sürümlerde sorunların miktarı ortaya çıktı - Taahhüt olmayan işlemleri olan bağlantıyı geri dönüştürürseniz sorun yaşarsınız. Özel karakter seti yapılandırmalarıyla bağlantıları geri dönüştürürseniz ve muhtemelen her oturum değişkeni için yaklaşık dönüştürülmüş olursunuz.

Kalıcı bağlantılar kullanmanın bir sorunu, o kadar iyi ölçeklendirilmemesidir. 5000 kişiyi bağlayanlar için 5000 kalıcı bağlantıya ihtiyacınız olacak. Kalıcılık gereksinimini ortadan kaldırmak için, benzer sayıda bağlantıya sahip 10000 kişiye hizmet verebilirsiniz, çünkü bireyler onlarla olmadığı zaman bireysel bağlantıları paylaşabileceklerdir.


0

Sadece kısmi bir çözümün bir kez kullanım bağlantılarına sahip olup olmayacağını merak ediyordum. Sistem düşük kullanımdayken, bir sınıra kadar, bir bağlantı havuzu oluşturmak için zaman harcayabilir, bunları tamamladıktan veya zaman aşımına uğradığında onları öldürebilirsiniz. Arka planda, yeni bağlantılar alınırken oluşturursunuz. En kötü durumda, bağlantının kurulmasının sınırlayıcı faktör olduğu varsayılarak, bu sadece havuzsuz bağlantı oluşturmak kadar yavaş olmalıdır?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.