Cerco di farla breve ma è un po' lunghina.
Sto lavorando per un istituto di ricerca che si occupa di biologia computazionale e robetta simile.
Nell'ambito della creazione di un webservice, ho creato uno script PHP di importazione dati che, dopo aver verificato se l'istituto che rilascia questi dati li ha aggiornati rispetto alla versione importata precedentemente, scarica un file dati (una sorta di CSV, ma con il tab come separatore), e li importa nel nostro database.
Quello che accade è, per quanto sembri assurdo a me stesso, che il processo di importazione sul file già scaricato in precedenza (dallo stesso script, o scaricato "a mano") va a gonfie vele, mentre il processo di importazione che scarichi da capo il file abbia sempre lo stesso identico problema e non inserisca gli ultimi 9 record (su 104.000 e rotti).
Non si tratta di un problema di timeout e credo neanche di memoria, nè di file corrotto in qualche modo (lo stesso file che non viene importato completamente appena scaricato, viene importato ad un secondo tentativo, commentando la parte che scarica i dati e lasciando quella che li importa).
L'errore restituito da mysql sulle righe fatali è un "Column count doesn't match value count", per cui ho subito pensato ad un problema nell'esplodere i campi dalla riga-record.
Per verificare la cosa ho estratto da shell le ultime righe del file (quelle problematiche) e aprendo il file con un editor ed evidenziando i caratteri nascosti sembrava esserci in ognuna delle righe "difettose" un tab diverso dagli altri (con lo stesso simbolo degli altri tab ma con in più dello spazio subito dopo, che in realtà non è un carattere di spazio... era tutto un unico carattere),che avrebbe poruro magari farmi esplodere male (un campo in più o in meno al moemnto dell'inserimento nel database)
Perplesso dalla cosa ho visualizzato in esadecimale una riga "non buona", ma tra il tab e il carattere successivo non c'era niente.
Ricordandomi che la prima volta avevo due script separati per download e import, e tutto era andato bene, ho fatto allora un po' di test: ho fatto almeno 15 test su 3 distinte macchine e, per quanto sembri assurdo da qualsiasi punto di vista, tutte le volte lo stesso identico file viene correttamente importato dallo stesso identico codice, se isolato, ma non nel processo completo download+import (prima resetto il database in modo che lo script trovi un file "aggiornato", poi lancio lo script completo che si blocca sempre con lo stesso errore sulla stessa riga, poi mantengo il file scaricato nella prova precedente ma commento tutta la parte di verifica aggiornamento e download, e quello stesso file viene importato).
Poichè questo script andrà in un crontab non posso spezzare la cosa in due fasi (non saprei quando il primo script ha finito il download, e qualsiasi scelta di tempificazione per lanciare l'import, fosse anche ad un giorno di distanza, sarebbe arbitraria. Probabilmente con un lungo intervallo funzionerebbe, m sarebbe arbitraria ed indeterministica, e questa non sarebbe cosa buona e giusta :P
Aggiungo che se dirotto le query su un file esterno, rifaccio il test con download e senza download e poi confronto i due file generati con diff, quello che ottengo è questo:
codice:
104285c104285,104293
< INSERT INTO `ssgi_test2` VALUES ('TC407206','','','','homologue to Cluster: PREDICTED: similar to s');
---
> INSERT INTO `ssgi_test2` VALUES ('TC407206','','','','homologue to Cluster: PREDICTED: similar to serine carboxypeptidase 1 precursor protein; n=1; Equus caballus|Rep:, partial (44%)','GGAATAAGTTGGATATGATCATCTTCTAATCCGTTCCCATTCCCAAGTCCTTGCACGTGTGGCTCCTGGC');
> INSERT INTO `ssgi_test2` VALUES ('TC407207','','','','similar to Cluster: Putative uncharacterized protein; n=1; Plasmodium vivax|Rep: Putative uncharacterized, partial (2%)','TAAGTAGTACAGTCTATCATTCAGCTTATCACTTAATACATAGGTCTGCACTAGAGCCTGTTTTTTGTTT');
> INSERT INTO `ssgi_test2` VALUES ('TC407208','','','','similar to Cluster: PREDICTED: similar to koyt binding protein 1 isoform 1; n=1; Equus caballus|Rep: PREDICTED:, partial (60%)','AGTCCTAGGCAGACCTAAAGGAAAAGCTCCTTAAACACCCTCTTCTACATCAGGGATAGGAAAGAAATAT');
> INSERT INTO `ssgi_test2` VALUES ('TC407209','','','','weakly similar to Cluster: Putative MHC class I related antigen; n=1; Sus scrofa|Rep: Putative MHC class I related, partial (6%)','TACTGTTCAAGAGTCCTATAGTATGAGGCTTTCCTCTTAACTTTCAGCAAGATCTGTCTGTTAAATTGGG');
> INSERT INTO `ssgi_test2` VALUES ('TC407210','','','','similar to Cluster: Endonuclease reverse transcriptase; n=1; Bos taurus|Rep: Endonuclease reverse, partial (15%)','');
> INSERT INTO `ssgi_test2` VALUES ('TC407211','','','','weakly similar to Cluster: PREDICTED: similar to LINE-1 reverse transcriptase homolog; n=1; Canis lupus familiaris|, partial (10%)','TTGCAGTTTTCTGTGTATAGGTTCTGCATCTGCACATTCAACCAACATGAATGGTATAGTACTGTAGTAT');
> INSERT INTO `ssgi_test2` VALUES ('TC407212','','','','homologue to Cluster: Putative uncharacterized protein; n=1; Borrelia garinii|Rep: Putative uncharacterized, partial (16%)','CCTGCTCCTTATTGTTATATTTAAAAATCTCCCAGATTCAAGTATCATGTGGAGAAAGAATGGGTAAAGA');
> INSERT INTO `ssgi_test2` VALUES ('TC407213','','','','similar to Cluster: Putative uncharacterized protein; n=1; Lyngbya sp. PCC 8106|Rep: Putative uncharacterized, partial (3%)','ATCTAAGCCTCTGCCTCCCCGACCTCAGGATTCAGGGGACAAAGCCAGTCCAAACGACTCAGGGGACAAG');
> INSERT INTO `ssgi_test2` VALUES ('TC407214','','','','similar to Cluster: Putative uncharacterized protein; n=1; Pichia stipitis|Rep: Putative uncharacterized, partial (3%)','AGGCCAGGATTTTTATAATTTACACAGCAATCAGGACTAAAAGGGAAAAGGTTCAGGTTAAAGCCTAACT');
insomma sembra proprio che ad una certa riga (sempre quella) la query venga troncata... tra l'altro in un punto in cui non c'è proprio niente di strano...
Non so che pesci prendere... i sospetti si concentrano sulla fase di download, come se in qualche modo il file "a fresco" non fosse ancora "buono".
Vi riporto il codice di download (il download avviene tramite post perchè, non so per quale motivo l'istituto che rilascia questi dati li ha "nascosti" dietro un post.. non sembra esserci un url direttamente accessibile da cui prendere i dati in GET).
Codice PHP:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
$output = fopen(DATA_FILE,'wb') or die("controllare i permessi");
curl_setopt($ch, CURLOPT_FILE, $output);
curl_setopt ($ch, CURLOPT_POST, 1);
$data = array(
'Download' => 'Download',
'db' => 'pest',
'gudb' => 'pig',
'searchby'=> ''
);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
qualche idea?