J'ai un script de console (dans l'application yii2) pour changer les noms d'utilisateur dans DB (postgreSQL) et écrire les données changelog dans le fichier csv. J'utilise pour la boucle pour faire des changements dans les vracs de 100 utilisateurs par offset.Le script de la console PHP (yii2) arrête de fonctionner au milieu du processus d'exécution
public function actionTest()
{
$query = User::find()->where(['username' => '']);
$total = $query->count(); // SQL variant - SELECT COUNT(*) FROM user WHERE username = ''
$data = [];
$filePath = '/path/to/folder/log.csv';
for ($offset = 0; $offset <= $total; $offset += 100) {
/** @var User[] $users */
$users = $query->orderBy(['id' => SORT_ASC])->limit(100)->offset($offset)->all(); // SQL variant - SELECT * FROM user WHERE username = '' ORDER BY id ASC OFFSET 0 LIMIT 100
foreach ($users as $user) {
User::updateAll(['username' => 'newUsername'], ['id' => $user->id]); // SQL variant - UPDATE user SET username = 'newUsername' WHERE id = 1
$data[] = ['username' => 'newUsername']; // collect data to generate csv-file in the future
}
$csvObj = new CSV(); // "mnshankar/csv": "1.8"
$csvObj->with($data, false, 'a+')->put($filePath, 'a+');
$data = [];
}
}
Le problème est que ce script cesse d'obtenir des données de droite DB au milieu du montant total des utilisateurs, donc j'obtenir 0 articles dans tableau $ users. Par exemple, si j'ai $ total = 15000, il arrête de fonctionner après itération avec $ offset = 7500, si $ total = 7500, il arrête de fonctionner après itération avec $ offset = 3800, si $ total = 3800, il cesse de fonctionner après itteration avec $ offset = 1900 etc.
J'ai essayé d'écrire simple test pour cette boucle avec la fonction pg_ * et il fonctionne correctement:
public function actionPgTest()
{
$dbConnection = pg_connect("host=localhost port=8080 dbname=user_db user=some_guy password=some_pass");
$total = pg_query($dbConnection,'SELECT COUNT(*) FROM user WHERE username = \'\'');
$total = pg_fetch_array($total)['count'];
for ($offset = 0; $offset <= $total; $offset += 100) {
$query = 'SELECT * FROM user WHERE username = \'\' ORDER BY id ASC LIMIT 100 OFFSET ' . $offset;
$users = pg_query($dbConnection,$query);
$users = pg_fetch_all($users);
sleep(3);
}
pg_close();
}
aussi, j'ai essayé de le faire avec bash -script et cela fonctionne aussi correctement:
#!/bin/bash count_query="select count(*) FROM \"user\" WHERE username = ''" count=$(echo $count_query | psql -U user -Atq user_db) query_base="select id FROM \"user\" WHERE username = '' LIMIT 100 OFFSET " for offset in $(seq 0 100 $count); do echo $query_base$offset| psql -U user -Atq user_db sleep 3; done;
En outre, j'ai essayé d'exécuter le script sans générer de fichier CSV et j'ai eu le même problème juste au milieu.
Pas vraiment. J'ai ajouté des données de décalage à stdout pour le voir dans la console à chaque itération et toujours moins que le nombre total d'utilisateurs jusqu'à la fin du script. J'ai également ajouté les données de compte des utilisateurs à stdout et chaque fois quelque chose comme ça: Nombre total d'utilisateurs = 15000, nombre d'utilisateurs actuel = 100, décalage actuel = 100 Nombre total d'utilisateurs = 15000, nombre d'utilisateurs actuel = 100, décalage actuel = 200 ... Nombre total d'utilisateurs = 15000, nombre d'utilisateurs actuel = 100, décalage actuel = 7500 Nombre total d'utilisateurs = 15000, nombre d'utilisateurs actuel = 0, décalage actuel = 7600 et à partir de ce moment, il n'y a pas de données dans la requête – Aksafan