何が起きた?
下記のようなロジックを作ったところ、入ってる
まで通るけど最後のpool.queryに入らずupdateできないことがありました。
test.js
var mysql = require('mysql2');
const pool = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password: 'password',
database: 'test_db'
});
// 関数呼び出し
test();
// 呼び出し用の関数準備
function test() {
pool.query("select * from emails", function (err, factDatas, fields) {
for (const obj of factDatas) {
pool.query(`select * from users where id = ${obj.user_id};`, function (err, user_rows, fields) {
console.log("入ってる");
pool.query(`update emails set new_user_id = ${user_rows[0].new_id} where user_id = ${obj.user_id};`, function (err, result, fields) {
if (err) throw err;
console.log(result);
});
});
}
});
}
解決方法
下記のように関数を切り出す(分割する)ことで動作しました。
test.js
var mysql = require('mysql2');
const pool = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password: 'password',
database: 'test_db'
});
// 関数呼び出し
test();
// 呼び出し用の関数準備
function test() {
pool.query("select * from emails", function (err, factDatas, fields) {
step1(factDatas);
});
}
// 分割した
async function step1(factDatas) {
for (const obj of factDatas) {
step2(obj);
await sleep(300); // スリープ処理を追加する
}
}
// 分割した
function step2(obj) {
pool.query(`select * from users where id = ${obj.user_id};`, function (err, user_rows, fields) {
console.log("入ってる");
step3(user_rows, obj);
});
}
// 分割した
function step3(user_rows, obj) {
pool.query(`update emails set new_user_id = ${user_rows[0].new_id} where user_id = ${obj.user_id};`, function (err, result, fields) {
if (err) throw err;
console.log(result);
});
}
// sleep関数を準備
function sleep(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time);
});
}
原因の予想
正直挙動を理解しきれていませんが、筆者としては処理が早すぎてupdateのトランザクションで弾かれたか、またはデッドロックになったのではないかと予想しています。