Je tente de charger des données dans une base de données MySQL en utilisant l'instruction LOAD DATA LOCAL INFILE
. Sur des fichiers normaux, cela fonctionne bien.
Si je crée un fichier temporaire avec File::Temp
, stocke des données CSV dedans, ferme le fichier et les charge directement dans la base de données en utilisant
$dbh->do("LOAD DATA LOCAL INFILE '$tempfile' INTO TABLE $temptable FIELDS TERMINATED BY ',');
les deux derniers enregistrements sont systématiquement omis. Cependant, si j'effectue une action avec le fichier temporaire entre sa création et son chargement, par exemple avec
`touch $tempfile`;
tout fonctionne comme prévu.
Est-ce un problème avec le pilote MySQL ayant des difficultés avec les fichiers temporaires fraîchement créés ? Est-ce un problème de système de fichiers (ext4), peut-être un problème de vidage de cache qui ne se produit pas assez rapidement ? Est-ce que j'oublie quelque chose ici ?
ÉDIT : En fait, tous les enregistrements sont omis si le fichier CSV temporaire n'est pas créé par une sous-routine de conversion de format, mais à la main comme montré ci-dessous. J'ai également inclus le code pour l'interaction avec la base de données. Notez le touch $tmpfh
en commentaire, qui, s'il est décommenté, ferait fonctionner l'exemple.
Ajouter UNLINK => 0
à File::Temp->new()
ne change rien.
my $tmpfh = File::Temp->new();
print $tmpfh <connect("DBI:mysql:$dbname:$dbserver", $username, $pwd);
# supprimer et recréer la table temporaire
$dbh->do("DROP TABLE IF EXISTS $temptable") or die;
$dbh->do("CREATE TABLE $temptable (
`id` INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`header` VARCHAR(255) NOT NULL,
`sequence` MEDIUMBLOB)")
or die;
# charger les données dans la table temporaire
my $nrecords = $dbh->do("LOAD DATA LOCAL INFILE '$tmpfh'
INTO TABLE $temptable
FIELDS TERMINATED BY ','
(header, sequence)")
or die;
$dbh->disconnect();
printf "Chargé %d enregistrements de %s dans %s sur %s.\n", $nrecords, $tmpfh, $dbname, $dbserver;