Есть ли лучший способ обработать SELECT => INSERT в параллельных ситуациях, кроме UNIQUE INDEX в Postgres? - PullRequest
0 голосов
/ 27 мая 2020

Для обратной совместимости в моем приложении я создаю новые модели «на лету» при первом запросе.

Псевдокод:

let results = await Model.findAll({ where });
if(results.length === 0) {
    await Model.bulkInsertDefaults();
    results = Model.findAll({ where });
}
return results;

Проблема заключается в параллелизме. Если два пользователя обращаются к запросу одновременно, я получаю повторяющиеся значения. Я попытался реализовать транзакцию:

try {
    let transaction = await sequelize.transaction()
    let results = await Model.findAll({ where, transaction });
    if(results.length === 0) {
        await Model.bulkInsertDefaults(transaction);
        results = Model.findAll({ where, transaction });
    }
    await transaction.commit();
    return results;
} catch(e) {
    await transaction.rollback();
}

Что, похоже, не помогло.

Таким образом, я просто добавил UNIQUE INDEX в свою таблицу:

CREATE UNIQUE INDEX idx_p_title_p_id ON p(title, p_id)

Который должен сделать второй одновременный возврат запроса. Это далеко не идеально, но этого вполне достаточно.

Есть ли лучший способ справиться с этой ситуацией с помощью какой-то блокировки? Чтобы второй запрос повторял попытку, пока не будет выполнена первая транзакция?

...