Я написал небольшой скрипт Node для чтения записей из таблицы базы данных Oracle, вызова внешнего Web-сервиса, который выполняет преобразование, и затем вставки результатов в другую таблицу. Поскольку мне нужно повторить тот же процесс для более чем 70 миллионов записей, я выбираю 10K строк за раз и выполняю вставку с помощью executeMany из Oracle-узла.
Вот код:
let insertQuery = `INSERT INTO ${start_table}_TOKEN_MASK (${id_field1}, ${id_field2}, TOKEN, CARD_NUMBER_MASK, CARD_NUMBER) VALUES (:id1, :id2, :token, :mask, :cardNumber)`;
function process_chunk() {
counter++;
// SELECT CARDS
connection.execute(`SELECT
${start_table}.${id_field1},
${start_table}.${id_field2},
${start_table}.${card_field}
FROM ${start_table}
LEFT JOIN ${start_table}_TOKEN_MASK ON ${start_table}.${id_field1} = ${start_table}_TOKEN_MASK.${id_field1}
WHERE TOKEN IS NULL AND ROWNUM <= ${max_per_run}`).then(async (res) => {
if (res.rows.length <= 0) {
console.log(`All done.`);
console.timeEnd('mapping');
connection.close();
process.exit(0);
}
console.log(`Fetched ${res.rows.length} rows.`);
var binds = [];
try{
console.log(`Starting tokenization...`);
await Promise.map(res.rows, async (row) => {
const mask = `${row[2].toString().substring(0,4)}.${row[2].toString().substring(4,6)}${'X'.repeat(2)}.${'X'.repeat(4)}.${row[2].toString().substring(row[2].toString().length - 4)}`;
const token = await Tokenize(row[2]);
binds.push([row[0], row[1], token, mask, row[2]]);
}, {concurrency: 150}).then(async () => {
// Send chunk to DB
console.log(`Sending to DB...`);
// Prevent failure on insertmany, dividing inserts into multiple transactions
var chunks = splitArray(binds, 5000);
await Promise.map(chunks, async (chunk) => {
const insertResult = await connection.executeMany(insertQuery, chunk, { autoCommit: true });
console.log(`Inserted ${insertResult.rowsAffected} rows. Commit.`);
}, {concurrency: 1}).then(() => {
console.log(`Chunk ${counter} tokenized.`);
process_chunk();
});
});
}
catch(err){
console.error(err);
process.exit(1);
}
}).catch(err => {
console.error(err);
});
}
В конце процесса я вижу, что в новой таблице (где вставки были сделаны) есть записи, но каждый кортеж смешан, например:
ID_FIELD1, ID_FIELD2, TOKEN, CARD_NUMBER_MASK, CARD_NUMBER
1 2 1234 456789 458755
2 3 1235 456790 458789
Что показывает, что связки так или иначе "смешиваются" либо вставкой, либо драйвером оракула.
Есть идеи, что может произойти?