Mysql
 sql >> Baza danych >  >> RDS >> Mysql

wiele żądań do węzła express problem z synchronizacją mysql

Nie znam szczegółowo knexa i po szybkim wyszukiwaniu, knex obecnie nie obsługuje używania „limitu” w instrukcjach aktualizacji, więc tylko opis ogólnego podejścia.

Najpierw zaktualizuj wiersz pasujący do kryteriów, a następnie wybierz ten zaktualizowany wiersz.

Tak więc najpierw wykonaj operację aktualizacji, która przypisuje identyfikator bieżącego użytkownika do pierwszego nieprzetworzonego wiersza, który nie ma przypisanego użytkownika lub ma już przypisany ten sam użytkownik:

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

Myślę, że może to działać w ten sposób z knex przy użyciu surowego zapytania, ale nie próbowałem tego:

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

Spowoduje to wyszukanie pierwszego (najwcześniej utworzonego) wiersza, który jest nieprzypisany lub już przypisany do tego samego użytkownika, a następnie przypisze tego użytkownika. Dzieje się to za jednym razem.

Następnie możesz wyszukać wiersz przypisany do użytkownika:

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

Zauważ, że teraz jawnie szukamy tylko wiersza już przypisanego do użytkownika.

Połączone

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

Oczywiście nie musisz wybierać, jeśli nie chcesz od razu pracować z wierszem.

Problem polega na tym, że gdy wiele żądań jest obsługiwanych w tym samym czasie, musisz wyobrazić sobie wiele wystąpień kodu działających równolegle w tym samym czasie. Tak więc z oryginalnym kodem dwa żądania mogą dokonać wyboru w tym samym czasie, zanim którekolwiek z nich dokona aktualizacji. Tak więc oba z nich będą miały zwrócony ten sam wiersz.

Dzięki natychmiastowej aktualizacji wiersza w instrukcji, nawet jeśli dwie instrukcje działają równolegle, baza danych upewni się, że nie widzą tego samego wiersza.

Alternatywnym podejściem do rozwiązania byłoby użycie muteksu (np. async-mutex ) wokół oryginalnego kodu, aby upewnić się, że oryginalna operacja wyboru i aktualizacji jest niepodzielna (występuje za jednym razem), ale najprawdopodobniej wydłuży to czas odpowiedzi Twojej aplikacji, ponieważ w niektórych sytuacjach jedna operacja obsługi żądań będzie musiała poczekać na drugą jeden, aby kontynuować.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak powinienem audytować zmiany w tabeli MySQL (używając MySQL 4)?

  2. Szybkie spojrzenie na funkcje numeryczne SQL Server

  3. com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException:nie można wywołać wycofania, gdy autocommit=true

  4. Przesyłanie obrazu, ajax, php, mysql

  5. Jak przekształcić wyniki zapytania sql w tabelę przestawną za pomocą tablic php?