sql >> Database teknologi >  >> RDS >> Mysql

flere anmodninger om node express mysql-synkroniseringsproblem

Jeg kender ikke knex i detaljer, og fra en hurtig søgning understøtter knex i øjeblikket ikke brugen af ​​"limit" på opdateringsudsagn, så kun en beskrivelse af den generelle tilgang.

Foretag først en opdatering for rækken, der matcher kriterierne, og vælg derefter den opdaterede række.

Så lav først en opdateringshandling, der tildeler det aktuelle bruger-id til den første ubehandlede række, der enten ikke har nogen bruger tildelt eller allerede har den samme bruger tildelt:

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

Jeg tror, ​​det kan fungere sådan her med knex ved hjælp af en rå forespørgsel, men har ikke prøvet det:

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

Dette vil lede efter den første (tidligst oprettede At) række, der ikke er tildelt eller allerede er tildelt den samme bruger, og derefter tildele denne bruger. Dette sker på én gang.

Du kan derefter søge efter den række, der er tildelt brugeren:

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

Bemærk, hvordan vi nu eksplicit kun ser efter en række, der allerede er tildelt til brugeren.

Kombineret

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();

Du behøver naturligvis ikke vælge, hvis du ikke vil arbejde med rækken med det samme.

Problemet er, at når flere anmodninger håndteres på samme tid, skal du forestille dig, at flere forekomster af koden kører på samme tid parallelt. Så med din originale kode kunne to anmodninger gøre dit valg på samme tid, før nogen af ​​dem opdaterer. Så begge vil have den samme række returneret.

Ved straks at opdatere rækken i sætningen, selv når to sætninger kører parallelt, sørger databasen for, at de ikke ser den samme række.

En alternativ tilgang til en løsning ville være at bruge en mutex (som f.eks. async-mutex ) omkring din originale kode for at sikre, at din oprindelige udvælgelses- og opdateringsoperation er atomisk (sker på én gang), men dette vil højst sandsynligt øge responstiden for din applikation, fordi i nogle situationer vil en anmodningshåndtering vente på en anden en for at fortsætte.




  1. tidszoneafstemning med SQL

  2. OracleDataSource vs. Oracle UCP PoolDataSource

  3. PDO::FETCH_CLASS med flere klasser

  4. Hvordan opretter man en kompleks virtuel kolonne i en veltalende model?