pg_end_copy (): mod engelleme bağlantısı kurmak değil mi?

5 Cevap php

I have a long-running script that seems to occasionally report the following NOTICE-level error: pg_send_query(): Cannot set connection to blocking mode

Bu daha sonra sorguları göndermeye devam görünüyor, ama başarılı hata üretir sorgu gönderir eğer belli değil.

Bu bir belirtisi nedir?

Edit: postgres'in hiçbir girdi, bu sadece, bir şey örneğin muhtemelen postgres'in sonucu çökmesini ve yeniden başlatmadan veya (postgres 'tarafta yanlış gitmiyor bir bağlantı hatası olduğunu düşündüren, hata oluştu anda log vardır bir şey)

Bu hata tetiklenir zaman Edit: Bildiğim kadarıyla söyleyebilirim, benim INSERT deyimleri, bir yol veya başka başarıyoruz.

Bu sabit olabilir gibi Edit: Görünüşe göre 2013 yılının haziran ayında: https://bugs.php.net/bug.php?id=65015

5 Cevap

Bu pg_send_query() başarıyla geri engelleme modu için bağlantıyı geçmek mümkün olmayan bir belirtisidir. PHPs pgsql.c kaynak koduna baktığımızda, şunları bulabilirsiniz:

/* {{{ proto bool pg_send_query(resource connection, string query)
   Send asynchronous query */
PHP_FUNCTION(pg_send_query)
{

<... snipped function setup stuff ...>

 if (PQ_SETNONBLOCKING(pgsql, 1)) {
  php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
  RETURN_FALSE;
 }

<... snipped main function execution stuff ...>

 if (PQ_SETNONBLOCKING(pgsql, 0)) {
  php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
 }
 RETURN_TRUE;
}

Ana çalışma yapıldıktan sonra Yani hata fonksiyonunun sonunda gündeme alır. Bu INSERT deyimleri idam olsun sizin gözlem ile uyuyor.

Iki PQ_SETNONBLOCKING bütün amacı uyumsuz yürütme ve sonrasında davranışları engelleme varsayılan geri koyarak izin dışı engelleme modunda bağlantıyı koymaktır çağırır. Dan documentation of PQsetnonblocking: (PQ_SETNONBLOCKING o işlev için tanımlanmış sadece bir takma isimdir):

Sets the nonblocking status of the connection.

int PQsetnonblocking(PGconn *conn, int arg);

Sets the state of the connection to nonblocking if arg is 1, or blocking if arg is 0. Returns 0 if OK, -1 if error.

In the nonblocking state, calls to PQsendQuery, PQputline, PQputnbytes, and PQendcopy will not block but instead return an error if they need to be called again.

Note that PQexec does not honor nonblocking mode; if it is called, it will act in blocking fashion anyway.

(PostgeSQLs fe-exec.c in) PQsetnonblocking kaynağında ayrıca baktığımızda, çağrı başarısız olabilir neden iki olası nedeni vardır:

/* PQsetnonblocking:
 * sets the PGconn's database connection non-blocking if the arg is TRUE
 * or makes it non-blocking if the arg is FALSE, this will not protect
 * you from PQexec(), you'll only be safe when using the non-blocking API.
 * Needs to be called only on a connected database connection.
 */
int
PQsetnonblocking(PGconn *conn, int arg)
{
 bool  barg;

 if (!conn || conn->status == CONNECTION_BAD)
  return -1;

 barg = (arg ? TRUE : FALSE);

 /* early out if the socket is already in the state requested */
 if (barg == conn->nonblocking)
  return 0;

 /*
  * to guarantee constancy for flushing/query/result-polling behavior we
  * need to flush the send queue at this point in order to guarantee proper
  * behavior. this is ok because either they are making a transition _from_
  * or _to_ blocking mode, either way we can block them.
  */
 /* if we are going from blocking to non-blocking flush here */
 if (pqFlush(conn))
  return -1;

 conn->nonblocking = barg;

 return 0;
}

Yani bağlantı ya bir şekilde kayboldu, ya da pqFlush bağlantı çıktı tamponunda artık şeyler gösteren, başarılı bir şekilde bitirmek vermedi.

Script kesinlikle sonraki aramalar için kayıp bağlantıyı fark ve bu tepki (veya daha fazla fark başarısız) gibi ilk vaka, zararsız olacaktır.

Bu non varsayılan olmayan engelleme durumundaki bir bağlantı var demektir ikinci durumda bırakır. Bu bağlantıyı yeniden kullanıyorlardı daha sonra aramaları etkileyebilir eğer ben bilmiyorum. Bunu güvenli oynamak istiyorsanız, bu durumda bağlantısını kapatın ve bir diğer yeni / kullanmak istiyorum.

Eğer PostgreSQL uyumsuz sorgularını göndermek için pg_send_query() işlevini kullanmaya çalışıyorlar gibi geliyor. Bu fonksiyonun amacı, PHP komut PostgreSQL sizin sorgu yürütmek ve sonuç hazır hale getirmek için beklerken diğer kod yürütme devam sağlamaktır.

docs için verilen örnek pg_send_query() PostgreSQL zaten başka bir sorguda çiğneme eğer bir sorgu göndermek gerektiğini göstermektedir:

if (!pg_connection_busy($dbconn)) {
  pg_send_query($dbconn, "select * from authors; select count(*) from authors;");
}

Eğer pg_send_query() yerine kullandığınız bir sebebi var mı pg_query()? Eğer komut sorgu yürütme bekliyor engellemek için izin verebilir, ben bu hataları görmek olmaz ki (kuşkusuz denedim olmadan) tahmin ediyorum.

Geçenlerde aynı sorunu vardı ve Henrik Opels cevabını yardımıyla PHP aslında geri engelleme modu için bağlantıyı ayarlamadan önce temizlemek için tampon beklemek olmadığını fark ettik.

'Engelleme modu için ayarlanamaz bağlantı' gönderme tamponu doldurmak için yeterince büyük bir sorgu ile trivially tekrarlanabilir (sonunda boşluk dolduruluyor yeterlidir). Küçük Sorgu ile ben yüke bağlıdır ve oldukça aralıklı düşünün.

aslında asenkron modu gerekir yoksa o https://bugs.php.net/bug.php?id=65015 de yama deneyin

This could occur if you are using threads and the connection is being reused. If is this the case you could use the PGSQL_CONNECT_FORCE_NEW like this:

pg_connect("...", PGSQL_CONNECT_FORCE_NEW)

Bu yeni bir veritabanı bağlantısı kaynak zorlar ama tavsiye: you could run out of connections clients, bu nedenle dikkatle iç konuları kullanarak bu yüzden kullanmayı unutmayın pg_close().

Bu message is from PHP. Son sürüme PHP güncellemek için çalışın - belki bu PHP bir hata olduğunu ve zaten sabittir.