sql >> Databáze >  >> RDS >> Mysql

více požadavků na uzel vyjadřuje problém se synchronizací mysql

Neznám knex podrobně a z rychlého vyhledávání knex v současné době nepodporuje použití "limit" na aktualizačních příkazech, takže pouze popis obecného přístupu.

Nejprve proveďte aktualizaci řádku, který odpovídá kritériím, a poté vyberte aktualizovaný řádek.

Nejprve tedy proveďte operaci aktualizace, která přiřadí aktuální ID uživatele prvnímu nezpracovanému řádku, který buď nemá přiřazeného žádného uživatele, nebo již má přiřazeného stejného uživatele:

update rows 
    set assignedTo = user.id 
    where assignedTo=0 or assignedTo=user.id 
    order by createdAt asc 
    limit 1

Myslím, že to může fungovat takto s knex pomocí nezpracovaného dotazu, ale nezkoušel jsem to:

await knex.raw('update rows set assignedTo = :userid where assignedTo=0 or assignedTo= :userid  order by createdAt asc limit 1', {userid: user.id})

Toto vyhledá první řádek (nejprve vytvořenýAt), který není přiřazen nebo je již přiřazen stejnému uživateli, a poté tohoto uživatele přiřadí. To se stane jedním tahem.

Poté můžete vyhledat řádek přiřazený uživateli:

const notProcessed = await knex('rows')
    .select('*'')
    .whereRaw(`status='Not-Processed' and assignedTo=${user.id}`)
    .orderByRaw('createdAt asc')
    .first();

Všimněte si, jak nyní explicitně hledáme pouze řádek již přiřazený uživateli.

Kombinovaný

await knex.raw('update rows set assignedTo = :userid where assignedTo=0 or assignedTo= :userid  order by createdAt asc limit 1', {userid: user.id})
const notProcessed = await knex('rows')
    .select('*'')
    .whereRaw(`status='Not-Processed' and assignedTo=${user.id}`)
    .orderByRaw('createdAt asc')
    .first();

Pokud nechcete s řádkem pracovat okamžitě, výběr samozřejmě nepotřebujete.

Problém je v tom, že když se zpracovává více požadavků současně, musíte si představit více instancí kódu běžících ve stejnou dobu paralelně. Takže s vaším původním kódem mohou dva požadavky provést váš výběr současně, než kterýkoli z nich provede aktualizaci. Oběma se tedy vrátí stejný řádek.

Okamžitou aktualizací řádku v příkazu, i když dva příkazy běží paralelně, databáze zajistí, že nevidí stejný řádek.

Alternativním přístupem k řešení by bylo použití mutexu (jako např. async-mutex ) kolem vašeho původního kódu, abyste se ujistili, že vaše původní operace výběru a aktualizace je atomická (proběhne najednou), ale to s největší pravděpodobností prodlouží dobu odezvy vaší aplikace, protože v některých situacích bude muset jedna operace zpracování požadavku čekat na druhou. jeden na pokračování.




  1. Jak přidat dny k datu v MySQL

  2. Jak vytvořit databázi v kontejneru databázového dockeru?

  3. Jak funguje SQLite Total()

  4. Chyba 1329:Žádná data – nebylo načteno, vybráno ani zpracováno nula řádků – i když je vše hotovo