Написание API в node.js с помощью MySQL DB, и я реализую довольно стандартный шаблон:
If exists then update
else insert
Это, конечно, работает нормально, пока к API не будет отправлено несколько одновременных запросов, и в этот момент If exists
по запросу 2 может быть выполнено до вставки запроса 1, что приводит к двум записям вместо одной.
Я знаю, что один из способов справиться с этим - убедиться, что БД имеет ограничение или ключ, который предотвращает дублирование записи, но в этом случае правила, определяющие, следует ли нам вставлять или обновлять, являются более сложными, и поэтому проверка должно быть сделано в коде.
Это звучало как хороший пример использования мьютекса / блокировки. Мне нужно, чтобы это было распространено, поскольку API может иметь несколько экземпляров, работающих как часть пула / фермы.
Я придумал следующую реализацию:
try {
await this.databaseConnection.knexRaw().raw(`SELECT GET_LOCK('lock1',10);`);
await this.databaseConnection.knexRaw().transaction(async (trx) => {
const existing = await this.findExisting(id);
if (existing) {
await this.update(myThing);
} else {
await this.insert(myThing);
}
});
} finally {
await this.databaseConnection.knexRaw().raw(`SELECT RELEASE_LOCK('lock1');`);
}
Кажется, все это работает нормально, и мои тесты теперь производят только одну вставку. Хотя, кажется, немного грубой силы / руководство. Будучи новичком в MySQL и узле (я пришел из C # и SQL Server фоне), этот подход вменяемый? Есть ли лучший подход?