PHP activerecord mysql sunucusu gitti

Şimdilik kısa bir süre için php-activerecord kullanıyorum ve kesinlikle çok seviyorum. Php-activerecord, ActiveRecord şablonuna dayalı açık kaynaklı bir ORM kütüphanesidir. Ancak, son zamanlarda Wrench e dayalı bir websocket uygulaması ile birlikte kullanmaya çalıştım.

Bu mükemmel çalışır, ancak betiği başlatmak için uygulamanın linux'ta bir daemon olarak çalışması gerekir; Uygulamayı kullanmamak ve tekrar kullanmaya çalışmak kısa bir süre sonra bazı veritabanı istisnaları atar:

İlk başta bir uyarı verir:

PHP Warning: Error while sending QUERY packet. PID=XXXXX in /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php on line 322

Sonra ölümcül bir hata atıyor:

PHP Fatal error: Uncaught exception 'ActiveRecord\DatabaseException' with message 'exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2006 MySQL server has gone away' in /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php:322

Yığın izleme:

#0 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php(322): PDOStatement->execute(Array)

#1 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Table.php(218): ActiveRecord\Connection->query('SELECT * FROM ...', Array)

#2 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Table.php(209): ActiveRecord\Table->find_by_sql('SELECT * FROM `...', Array, false, NULL)

#3 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Model.php(1567): ActiveRecord\Table->find(Array)

#4 in /home/user/domains/example.com/public_html/vendor/php-activerecord/lib/Connection.php on line 325

Php-activerecord, websocket sunucusunun çalıştığı her zaman MySQL bağlantısını açık tutuyor gibi gözüküyor, daha sonra otomatik olarak sorguyu yeniden bağlayıp çalıştırmayı denerse bu sorun bir sorun olmamalıdır. Ama öyle değil.

MYSQL_OPT_RECONNECT ayarıyla ilgili bir şey okudum. Fakat bunun işe yarayıp yaramadığını ya da php-activerecord kullanarak bu seçeneğin nasıl ayarlanacağını bilmiyorum. Bu alanda herhangi bir deneyimi olan var mı?

Düzenleme: İşte benim global zaman aşımı config değişkenleri

VARIABLE_NAME                   VARIABLE_VALUE  
DELAYED_INSERT_TIMEOUT          300
WAIT_TIMEOUT                    28800
CONNECT_TIMEOUT                 10
LOCK_WAIT_TIMEOUT               31536000
INNODB_ROLLBACK_ON_TIMEOUT      OFF
THREAD_POOL_IDLE_TIMEOUT        60
NET_WRITE_TIMEOUT               60
INNODB_LOCK_WAIT_TIMEOUT        50
INTERACTIVE_TIMEOUT             28800
DEADLOCK_TIMEOUT_LONG           50000000
SLAVE_NET_TIMEOUT               3600
DEADLOCK_TIMEOUT_SHORT          10000
NET_READ_TIMEOUT                30
12
Bağlantının 8 saatten fazla devam etmesini sağlamaya mı çalışıyorsun?
katma yazar Rick James, kaynak
Bağlantının 8 saatten fazla devam etmesini sağlamaya mı çalışıyorsun?
katma yazar Rick James, kaynak
Ben de aynı sorunu yaşadım, sorduğun için teşekkürler;)
katma yazar Memet Olsen, kaynak
Ben de aynı sorunu yaşadım, sorduğun için teşekkürler;)
katma yazar Memet Olsen, kaynak
PHP'de veritabanının otomatik olarak yeniden bağlanmasının nasıl etkinleştirileceğini kontrol ettiniz mi? . Buna göre, PDO'da MYSQL_OPT_RECONNECT değerini ayarlamak mümkün değildir (ve php-activerecord PDO kullanır). Belki de geçici bir çözüm, her saat başı basit bir sorgu yürütmektir.
katma yazar VolenD, kaynak
PHP'de veritabanının otomatik olarak yeniden bağlanmasının nasıl etkinleştirileceğini kontrol ettiniz mi? . Buna göre, PDO'da MYSQL_OPT_RECONNECT değerini ayarlamak mümkün değildir (ve php-activerecord PDO kullanır). Belki de geçici bir çözüm, her saat başı basit bir sorgu yürütmektir.
katma yazar VolenD, kaynak
PHP'de soket servisi uyguladınız mı? DB ile bağlantı kurmaktan sorumlu bir kod verebilir misiniz? Tcp yerine DB'yi .sock ile bağlamayı denediniz mi?
katma yazar yergo, kaynak
PHP'de soket servisi uyguladınız mı? DB ile bağlantı kurmaktan sorumlu bir kod verebilir misiniz? Tcp yerine DB'yi .sock ile bağlamayı denediniz mi?
katma yazar yergo, kaynak
IMO, MYSQL_OPT_RECONNECT iyi bir çözüm değil. Cevabımı aşağıda oku. Gerçek uygulamaya dayanır.
katma yazar ihsan, kaynak
IMO, MYSQL_OPT_RECONNECT iyi bir çözüm değil. Cevabımı aşağıda oku. Gerçek uygulamaya dayanır.
katma yazar ihsan, kaynak
@RTB Aktif Kayıt Kullanarak, hak ettiğiniz şeyi elde edersiniz. Bir model olarak Aktif Kayıt, herhangi bir DB geliştiricisinin bir abominasyonudur ve bu nedenle bu desene dayanan herhangi bir kütüphanedir. Yalnızca, kullanmak üzere tasarlandıkları gibi RDBMS kullanmayı veya istedikleriniz sınıflarınız için pasif bir veri deposuysa ilişkisel olmayan bir veri deposu kullanmayı öğrenin.
katma yazar David Soussan, kaynak
@RTB Aktif Kayıt Kullanarak, hak ettiğiniz şeyi elde edersiniz. Bir model olarak Aktif Kayıt, herhangi bir DB geliştiricisinin bir abominasyonudur ve bu nedenle bu desene dayanan herhangi bir kütüphanedir. Yalnızca, kullanmak üzere tasarlandıkları gibi RDBMS kullanmayı veya istedikleriniz sınıflarınız için pasif bir veri deposuysa ilişkisel olmayan bir veri deposu kullanmayı öğrenin.
katma yazar David Soussan, kaynak
@Dimitri evet tam kontrole sahibim ve sorumu daha yeni düzenledim.
katma yazar RTB, kaynak
@Dimitri evet tam kontrole sahibim ve sorumu daha yeni düzenledim.
katma yazar RTB, kaynak
Veri tabanı yapılandırması üzerinde tam kontrolünüz var mı? Konfigürasyonunuzda belirlediğiniz tüm zaman aşımlarını listeler misiniz? Eğer configiniz boşsa, mysql'den global değişkenlerinizi seçin ve 'timeout' içeren tüm satırları gönderin.
katma yazar Dimitri, kaynak
Veri tabanı yapılandırması üzerinde tam kontrolünüz var mı? Konfigürasyonunuzda belirlediğiniz tüm zaman aşımlarını listeler misiniz? Eğer configiniz boşsa, mysql'den global değişkenlerinizi seçin ve 'timeout' içeren tüm satırları gönderin.
katma yazar Dimitri, kaynak

12 cevap

PHP ActiveRecord PDO'yu kullanır. Bir PDO bağlantısını kapatmanın kesinlikle bir yolu yoktur, uzun süren arkaplan görevleri için yanlış DB katmanıdır.

Bir PDO bağlantısının bağlantısını aşağıdaki snippet ile kesmeyi deneyebilirsiniz.

//if not using ZF2 libraries, disconnect in some other way
$db->getDriver()->getConnection()->disconnect()
$db = NULL;
gc_collect_cycles();

Bağlantıyı kesin, referansınızı null değerine ayarlayın, ardından çöp toplayıcıyı çalıştırın. Umut, PDO’nun bağlantıyı gerçekten kapatmak için iç __destruct yöntemini çağırmasıdır.

You must manage your DB connections in your own long running script. You must disconnect if your worker hasn't had to process work in a while, and you must reconnect when you have work.

Asıl çözüm PDO kullanmamak ve bağlantıyı kesip normal şekilde yeniden bağlamaktır.

Hem sunucu hem de istemci kitaplığı zaman aşımlarını sonsuz olacak şekilde ayarlarsanız, sizi tüm sunucuyu yeniden başlatmaya zorlayan (zaman aşımına uğramak için iyi bir fikir değil), hiç kontrol edilmeyen kontrol komut dosyaları ile ilgili sorunlarınızla karşılaşırsınız.

EDIT: Aslında tam olarak bu sorunu yaşadım ve geçen yıl işte bu tam çözümü kullandım. Bu benim problemlerimin% 99'unu çözdü. Fakat yine de, arada bir, yakalayamadığım ve yeniden bağlanamayacağım başıboş bir bağlantı istisnası vardı. Kendimi bu başıboş bağlantı hatalarından kurtulmak için günde bir kez yeniden başlatıyorum. Bu yüzden cevabım PDO kullanmayın. Şimdi geçin ve bağlantı kesme ve yeniden bağlantılarda gerçek kontrol sağlayın.

5
katma
... o zaman mysqli?
katma yazar angelcool.net, kaynak

PHP ActiveRecord PDO'yu kullanır. Bir PDO bağlantısını kapatmanın kesinlikle bir yolu yoktur, uzun süren arkaplan görevleri için yanlış DB katmanıdır.

Bir PDO bağlantısının bağlantısını aşağıdaki snippet ile kesmeyi deneyebilirsiniz.

//if not using ZF2 libraries, disconnect in some other way
$db->getDriver()->getConnection()->disconnect()
$db = NULL;
gc_collect_cycles();

Bağlantıyı kesin, referansınızı null değerine ayarlayın, ardından çöp toplayıcıyı çalıştırın. Umut, PDO’nun bağlantıyı gerçekten kapatmak için iç __destruct yöntemini çağırmasıdır.

You must manage your DB connections in your own long running script. You must disconnect if your worker hasn't had to process work in a while, and you must reconnect when you have work.

Asıl çözüm PDO kullanmamak ve bağlantıyı kesip normal şekilde yeniden bağlamaktır.

Hem sunucu hem de istemci kitaplığı zaman aşımlarını sonsuz olacak şekilde ayarlarsanız, sizi tüm sunucuyu yeniden başlatmaya zorlayan (zaman aşımına uğramak için iyi bir fikir değil), hiç kontrol edilmeyen kontrol komut dosyaları ile ilgili sorunlarınızla karşılaşırsınız.

EDIT: Aslında tam olarak bu sorunu yaşadım ve geçen yıl işte bu tam çözümü kullandım. Bu benim problemlerimin% 99'unu çözdü. Fakat yine de, arada bir, yakalayamadığım ve yeniden bağlanamayacağım başıboş bir bağlantı istisnası vardı. Kendimi bu başıboş bağlantı hatalarından kurtulmak için günde bir kez yeniden başlatıyorum. Bu yüzden cevabım PDO kullanmayın. Şimdi geçin ve bağlantı kesme ve yeniden bağlantılarda gerçek kontrol sağlayın.

5
katma
... o zaman mysqli?
katma yazar angelcool.net, kaynak

Dediğim gibi, PHP komut dosyalarındaki MySQL, ikisi arasında bir süre iletişim olmadığında zaman aşımına uğrar. Bu iyi bir şey, çünkü boştaki bağlantılar sunucu kaynaklarınızı tüketir.

"Sunucu kayboldu" hatası çoğunlukla iki sorgu arasında nispeten uzun bir hesaplama yapıldığında meydana gelir.

Bunu önlemek için,

  • Periodically execute a SELECT 1 query during your execution
  • Create a wrapper around your queries which checks if connection is valid before executing
  • Use answer from this post

Ancak, MySQL'in bağlantıyı daha uzun süre açık tutması için yeniden yapılandırılmasının dikkatsiz programlamayı teşvik ettiğine ve buna karşı tavsiyelerde bulunacağına inanıyorum.

1
katma

Dediğim gibi, PHP komut dosyalarındaki MySQL, ikisi arasında bir süre iletişim olmadığında zaman aşımına uğrar. Bu iyi bir şey, çünkü boştaki bağlantılar sunucu kaynaklarınızı tüketir.

"Sunucu kayboldu" hatası çoğunlukla iki sorgu arasında nispeten uzun bir hesaplama yapıldığında meydana gelir.

Bunu önlemek için,

  • Periodically execute a SELECT 1 query during your execution
  • Create a wrapper around your queries which checks if connection is valid before executing
  • Use answer from this post

Ancak, MySQL'in bağlantıyı daha uzun süre açık tutması için yeniden yapılandırılmasının dikkatsiz programlamayı teşvik ettiğine ve buna karşı tavsiyelerde bulunacağına inanıyorum.

1
katma

MySQL sunucusu için en yaygın hata, sunucunun zaman aşımına uğraması ve bağlantıyı kapatmasıdır.

Aşağıdaki değişikliği yapmayı deneyin.

max_allowed_packet=64M

Çok fazla isteğiniz varsa, bunu ayarlayın ve ortamınızla ilgili olduğundan daha büyük olarak ayarlamayın.

max_connections=1000

Bu satırı my.cnf dosyasına eklemek, sorununuzu çözebilir. Değişiklikten sonra MySQL hizmetini yeniden başlatın.

Read more on MySQL server has gone away

Çalışmazsa, bunu deneyin otomatik yeniden bağlanma işlevi de.

1
katma
Otomatik olarak yeniden bağlanmak, kaybedilen durum bilgisi nedeniyle sorunlara neden olabilir. Özellikle, bir işlemde iseniz, bu bağlantı kesilmeden geri alınır. Yeniden bağlandıktan sonra devam etmek, kayıp/değiştirilmiş verilere yol açabilir.
katma yazar Rick James, kaynak

MySQL sunucusu için en yaygın hata, sunucunun zaman aşımına uğraması ve bağlantıyı kapatmasıdır.

Aşağıdaki değişikliği yapmayı deneyin.

max_allowed_packet=64M

Çok fazla isteğiniz varsa, bunu ayarlayın ve ortamınızla ilgili olduğundan daha büyük olarak ayarlamayın.

max_connections=1000

Bu satırı my.cnf dosyasına eklemek, sorununuzu çözebilir. Değişiklikten sonra MySQL hizmetini yeniden başlatın.

Read more on MySQL server has gone away

Çalışmazsa, bunu deneyin otomatik yeniden bağlanma işlevi de.

1
katma
Otomatik olarak yeniden bağlanmak, kaybedilen durum bilgisi nedeniyle sorunlara neden olabilir. Özellikle, bir işlemde iseniz, bu bağlantı kesilmeden geri alınır. Yeniden bağlandıktan sonra devam etmek, kayıp/değiştirilmiş verilere yol açabilir.
katma yazar Rick James, kaynak

DB'niz birden fazla, eşzamanlı bağlantı ve sorguyu işlemiyorsa "sonsuz" zaman aşımlarını ayarlayabilirsiniz. Bu, DB kaynaklarını önemli ölçüde etkilemeyecektir. En iyi yaklaşım, zaman aşımını yenilemek ve bağlantıyı canlı tutmak için ping paketleri (SELECT 1) göndermektir.

1
katma

DB'niz birden fazla, eşzamanlı bağlantı ve sorguyu işlemiyorsa "sonsuz" zaman aşımlarını ayarlayabilirsiniz. Bu, DB kaynaklarını önemli ölçüde etkilemeyecektir. En iyi yaklaşım, zaman aşımını yenilemek ve bağlantıyı canlı tutmak için ping paketleri (SELECT 1) göndermektir.

1
katma

Ayrıca ORM'ler performansı artırmak için sorguları birleştirdiğinden, sorgunun boyutu da olabilir.

Max_allowed_packet = 128M ayarını yapmayı deneyin, en azından teşhis olarak kullanmanız gerekir.

1
katma

Ayrıca ORM'ler performansı artırmak için sorguları birleştirdiğinden, sorgunun boyutu da olabilir.

Max_allowed_packet = 128M ayarını yapmayı deneyin, en azından teşhis olarak kullanmanız gerekir.

1
katma

Böyle bir sorunu çözmek için, size şunları öneriyorum:

  1. İşlemlerinizi Gearman iş sunucusunu kullanarak dağıtın ( http://gearman.org/ )
  2. Danışmanı kullanarak bu işlemleri kolayca yönetin ( http://supervisord.org/ )

İşte nasıl.

Web soketi uygulamanızı tıpkı şimdi yaptığınız gibi (belki de cron kullanarak) bir arka plan programı olarak çalıştırın. Ya da daha iyisi, Danışmanı kullanarak yönetin. Supervisor başladığında Supervisor başlatılacak şekilde başlar ve Supervisor başladığında otomatik olarak servise başlar.

Örnek yapılandırma:

[program:my-daemon]
command=/usr/bin/php /path/to/your/daemon/script
autostart=true
autorestart=true

Ardından, sorgu işlemini uygulama arka plan programı içinde çalıştırmak yerine, işlemek için bir Gearman Worker oluşturun. Bir kere kaydedildiğinde, İşçi çalıştırılmayı/çağrılmayı bekliyor olacaktır. Çalışanı websocket uygulamanızdan, gerekirse gerekli iş yükü parametresiyle birlikte aramanız gerekir (bu iş yükü terim açıklaması için Gearman web sitesine bakın).

İşçi'de, arka plan programı tarafından istenen işi zaten bitirdiğinde durmasını/çıkmasını ayarlayın. Bununla bağlantı hemen kesilir, çünkü "mysql sunucusu sorunu çözdü" olmaz.

Son olarak, İşçiyi her zaman olduğu gibi her zaman kullanılabilir duruma getirmek zorundayız. Böylece, servise benzer şekilde, Süpervizör'ü İşçi öldüğünde/durduğunda otomatik olarak başlayacak ve otomatik olarak başlatacak şekilde yapılandırın:

[program:my-worker]
command=/usr/bin/php /path/to/your/worker/script
autostart=true
autorestart=true

Bir başka ilginç şey ise, canlı bekletmek için istediğiniz kadar işçi ekleyebilmenizdir. Sadece aşağıdaki konfigürasyonu ekleyin:

numprocs=9 #change it to any number
process_name=%(program_name)s_%(process_num)02d #to identity worker number

Süpervizöre her bir işlemi otomatik olarak başlatmasını söylediğimiz için, arka planda çalışan sürekli Çalışanlarımız vardır.

Here is another explanation about this strategy: http://www.masnun.com/2011/11/02/gearman-php-and-supervisor-processing-background-jobs-with-sanity.html

Umarım yardımcı olur!

0
katma
Downvoter, lütfen stratejiyi dikkatlice okuyunuz. Ben de gönderdiğim bağlantıyı okuyun! "MySQL sunucusu gitti" sorunu çözmek için basit gibi görünüyor, ama değil.
katma yazar ihsan, kaynak
@ArunPoudel neden bu? Bunları üretim ortamında uyguladım. MySQL sunucusu gitti çünkü bağlantı çok uzun açık ve PHP uzun süreli kullanım için uygun değil.
katma yazar ihsan, kaynak
@ArunPoudel Neden ilişkili değil? "MySQL sunucusu gitti" sorunu çözdü.
katma yazar ihsan, kaynak
@ArunPoudel Yani şimdi bunun ilişkili olduğunu söylüyorsun, ama aptalca? Başka bir çözümünüz varsa, kendi cevabınızı yazın. SO'nun tercih edilen şekli budur. * aslında deyimsel ne demek istediğini anlamıyorum.
katma yazar ihsan, kaynak
Evet, yaptım ve hiçbir şekilde posta ile ilgili değil. OP'nin sahip olduğu sorun, çözmeye çalıştığınızdan oldukça farklı.
katma yazar Arun Poudel, kaynak
Bunun OP'nin sorununu çözmediğini sanmıyorum.
katma yazar Arun Poudel, kaynak
Evet, çılgınca bir yaklaşım kullanarak. Sadece sorunu çözmekle ilgili değil. Ama bunu aptalca bir şekilde yapmak. Bu tür meseleleri ele almanın başka yolları da var ve yeniden bağlantı bayrağı bunlardan biri.
katma yazar Arun Poudel, kaynak

Böyle bir sorunu çözmek için, size şunları öneriyorum:

  1. İşlemlerinizi Gearman iş sunucusunu kullanarak dağıtın ( http://gearman.org/ )
  2. Danışmanı kullanarak bu işlemleri kolayca yönetin ( http://supervisord.org/ )

İşte nasıl.

Web soketi uygulamanızı tıpkı şimdi yaptığınız gibi (belki de cron kullanarak) bir arka plan programı olarak çalıştırın. Ya da daha iyisi, Danışmanı kullanarak yönetin. Supervisor başladığında Supervisor başlatılacak şekilde başlar ve Supervisor başladığında otomatik olarak servise başlar.

Örnek yapılandırma:

[program:my-daemon]
command=/usr/bin/php /path/to/your/daemon/script
autostart=true
autorestart=true

Ardından, sorgu işlemini uygulama arka plan programı içinde çalıştırmak yerine, işlemek için bir Gearman Worker oluşturun. Bir kere kaydedildiğinde, İşçi çalıştırılmayı/çağrılmayı bekliyor olacaktır. Çalışanı websocket uygulamanızdan, gerekirse gerekli iş yükü parametresiyle birlikte aramanız gerekir (bu iş yükü terim açıklaması için Gearman web sitesine bakın).

İşçi'de, arka plan programı tarafından istenen işi zaten bitirdiğinde durmasını/çıkmasını ayarlayın. Bununla bağlantı hemen kesilir, çünkü "mysql sunucusu sorunu çözdü" olmaz.

Son olarak, İşçiyi her zaman olduğu gibi her zaman kullanılabilir duruma getirmek zorundayız. Böylece, servise benzer şekilde, Süpervizör'ü İşçi öldüğünde/durduğunda otomatik olarak başlayacak ve otomatik olarak başlatacak şekilde yapılandırın:

[program:my-worker]
command=/usr/bin/php /path/to/your/worker/script
autostart=true
autorestart=true

Bir başka ilginç şey ise, canlı bekletmek için istediğiniz kadar işçi ekleyebilmenizdir. Sadece aşağıdaki konfigürasyonu ekleyin:

numprocs=9 #change it to any number
process_name=%(program_name)s_%(process_num)02d #to identity worker number

Süpervizöre her bir işlemi otomatik olarak başlatmasını söylediğimiz için, arka planda çalışan sürekli Çalışanlarımız vardır.

Here is another explanation about this strategy: http://www.masnun.com/2011/11/02/gearman-php-and-supervisor-processing-background-jobs-with-sanity.html

Umarım yardımcı olur!

0
katma
Downvoter, lütfen stratejiyi dikkatlice okuyunuz. Ben de gönderdiğim bağlantıyı okuyun! "MySQL sunucusu gitti" sorunu çözmek için basit gibi görünüyor, ama değil.
katma yazar ihsan, kaynak
@ArunPoudel neden bu? Bunları üretim ortamında uyguladım. MySQL sunucusu gitti çünkü bağlantı çok uzun açık ve PHP uzun süreli kullanım için uygun değil.
katma yazar ihsan, kaynak
@ArunPoudel Neden ilişkili değil? "MySQL sunucusu gitti" sorunu çözdü.
katma yazar ihsan, kaynak
@ArunPoudel Yani şimdi bunun ilişkili olduğunu söylüyorsun, ama aptalca? Başka bir çözümünüz varsa, kendi cevabınızı yazın. SO'nun tercih edilen şekli budur. * aslında deyimsel ne demek istediğini anlamıyorum.
katma yazar ihsan, kaynak
Evet, yaptım ve hiçbir şekilde posta ile ilgili değil. OP'nin sahip olduğu sorun, çözmeye çalıştığınızdan oldukça farklı.
katma yazar Arun Poudel, kaynak
Bunun OP'nin sorununu çözmediğini sanmıyorum.
katma yazar Arun Poudel, kaynak
Evet, çılgınca bir yaklaşım kullanarak. Sadece sorunu çözmekle ilgili değil. Ama bunu aptalca bir şekilde yapmak. Bu tür meseleleri ele almanın başka yolları da var ve yeniden bağlantı bayrağı bunlardan biri.
katma yazar Arun Poudel, kaynak