2009-02-12 15 views
8

disconnect invalidates 1 active statement handle (either destroy statement handles or call finish on them before disconnecting)Apache neden mod_perl programımın "1 etkin bildirim tutamacını geçersiz kıldığını" şikayet ediyor?

MySQL veri başarıyla işletilirse, yakalar ama Apache kendi hata günlüğünde yukarıdaki mesajı oluşturmasına neden olur Aşağıdaki kodu:

my $driver = "mysql"; 
my $server = "localhost:3306"; 
my $database = "test"; 
my $url  = "DBI:$driver:$database:$server"; 
my $user  = "apache"; 
my $password = ""; 

#Connect to database 
my $db_handle = DBI->connect($url, $user, $password) 
    or die $DBI::errstr; 

#SQL query to execute 
my $sql = "SELECT * FROM tests WHERE id=?"; 

#Prepare SQL query 
my $statement = $db_handle->prepare($sql) 
     or die "Couldn't prepare query '$sql': $DBI::errstr\n"; 

#Execute SQL Query 
$statement->execute($idFromSomewhere) 
    or die "Couldn't execute query '$sql': $DBI::errstr\n"; 

#Get query results as hash 
my $results = $statement->fetchall_hashref('id'); 

$db_handle->disconnect(); 
  • görmezden gelerek herhangi korkunç sonuçları olacak mı bahsedilen hata/uyarı? Kod bir hafta boyunca herhangi bir yan etki olmadan çalıştırılıyor.

  • kodunda bir sorun var mı, yoksa bu sadece zararsız bir uyarı mı?

Düzenleme

Kod mod_perl eliyle yürütülür.

+0

Hey Brian, başlığı düzenlediğiniz için teşekkürler. Tüm kitaplarınızı daha önce okudum. – GeneQ

cevap

12

$db_handle->disconnnect();'dan önce $statement->finish(); numaralı telefonu aramanız gerekir. Tüm satırları almıyorsanız, normal olarak finish numaralı telefonu aramanız gerekmez. Tüm sonuçları bir döngü içinde fetchrow_array kullanarak alırsanız, döngüyü iptal etmediğiniz sürece bitirme işlemini yapmazsınız.

Neden MySQL sürücüsünün neden bir fetchall_hashref ifadesini bitirmediğinden emin değilim. Manuel sorgu bir hata nedeniyle iptal olabileceğini öne sürdü:

If an error occurs, fetchall_hashref returns the data fetched thus far, which may be none. You should check $sth->err afterwards (or use the RaiseError attribute) to discover if the data is complete or was truncated due to an error.

+0

Teşekkürler, bu hile yaptı. O'Reilly DBI kitabını ve Perl belgelerini okumak, aksi halde önermekle birlikte. 16 dakikada çözüldü! Stackoverflow'a git! – GeneQ

+0

Sorumu "neden" kısmına cevapladığınız için teşekkürler Paul. ;-) 15 bin karma hakkınızı hak ediyorsunuz. – GeneQ

+0

Veriler iyi. Bir hafta boyunca sürekli yaklaşık 1K kişi tarafından dövüldü. Evet, belgeler öyle diyor. Her neyse, sadece MySQL sürücüsü olabilir. Bitirdikten sonra() uyarıların görünmesi durdu. DBI ve MYSQL'in en son sürümüne geçeceğim ve neler olacağını göreceğim. – GeneQ

3

Bu tanıtıcı hala etkin olma kaynaklanır. Normalde kendini kapatmalı ama ondan tüm verileri almıyor gibisin. DBI perldoc Gönderen:

When all the data has been fetched from a SELECT statement, the driver should automatically call finish for you. So you should not normally need to call it explicitly except when you know that you've not fetched all the data from a statement handle. The most common example is when you only want to fetch one row, but in that case the selectrow_* methods are usually better anyway. Adding calls to finish after each fetch loop is a common mistake, don't do it, it can mask genuine problems like uncaught fetch errors.

+0

Teşekkürler. Bunu da okudum ve zorunlu olmadığını düşündüm. – GeneQ

+0

Ama o fetchall_hashref arıyor - bu tüm sonuçları almak gerekiyordu! –

+0

iyi nokta, bunu yakalamadı. Emin olmanın tek yolu, tahmin ettiğim fetchall'daki hataları kontrol etmektir. – wds

0

olsa da, ben biraz farklı koşullarda aynı uyarıyı deneyimli ve bunu önermek istedim (o olduğunu manual iddialar ne olduğunu) bu uyarıyı var muhtemelen nedeni Burada kendi sorumu açmak yerine.

Bazı satırları almak için bir sorgu gerçekleştirirseniz, yalnızca bu senaryoda kendinizi bulabilirsiniz, ancak yalnızca eşleşen veya bulunmayan satırların olup olmadığını bilmek amacıyla. Benim durumumda, bir eşleşme bulunursa ve başka bir şekilde girilirse satırları güncelleriz.

Bulunan satırlarla hiçbir şey yapılmadığı için, bunun uyarıyı takip etmenin uygun olduğu bir senaryo oluşturduğuna inanıyorum. Bu nedenle, bağlantıyı kesmeden önce seçim işleyicimde finish() numaralı telefonu arıyorum.

Feragatname: DBI için yeni olmak, potansiyel olarak daha iyi bir yaklaşım var. the documentation hariç ->do() kullanmış olsaydım, 'un tekrar tekrar çalıştırıldığında kullanılmamasına dikkat etmeliydim - ayrıca bazı nedenlerden ötürü de SELECT ifadesi de kaldırıldı!Bu başkası ve kimseye yanıltıcı ediyorsam yaklaşımım düzeltmek çekinmeyin yardımcı

$selectHandler = $dbh->prepare($queryString) or die "Cannot prepare: ".$dbh->errstr; 
#Loop through a list of keys to check existence { 
    $selectHandler.execute($uniqueID); 
    $found = 0; 
    $found = $selectHandler->fetch(); 
    if (!$found) { 
     # Do an insert of $uniqueID 
    } else { 
     # Do an update of $uniqueID 
    } 
#} 
# Having not done anything with the selectHandler's result (when rows were 
# found) close it now that the loop is complete 
$selectHandler->finish(); # we don't need you any more select handler! 
$dbh->disconnect or warn "Disconnection error: $DBI::errstr\n"; 

Umut: Burada

Ben indi ettiğini gösteren bazı Perl yalancı kod olduğunu.

İlgili konular