sql >> Database >  >> RDS >> Mysql

Wanneer gebruik je SELECT ... VOOR UPDATE?

De enige draagbare manier om consistentie tussen kamers en tags te bereiken en ervoor te zorgen dat kamers nooit worden geretourneerd nadat ze zijn verwijderd, is ze te vergrendelen met SELECT FOR UPDATE .

In sommige systemen is vergrendeling echter een neveneffect van gelijktijdigheidscontrole en bereikt u dezelfde resultaten zonder FOR UPDATE op te geven. expliciet.

Om dit probleem op te lossen, moet Thread 1 SELECT id FROM rooms FOR UPDATE , waardoor wordt voorkomen dat Thread 2 wordt verwijderd uit rooms totdat draad 1 klaar is. Klopt dat?

Dit hangt af van het gelijktijdigheidsbeheer dat uw databasesysteem gebruikt.

  • MyISAM in MySQL (en verschillende andere oude systemen) vergrendelt de hele tabel voor de duur van een zoekopdracht.

  • In SQL Server , SELECT query's plaatsen gedeelde vergrendelingen op de records / pagina's / tabellen die ze hebben onderzocht, terwijl DML query's plaatsen updatevergrendelingen (die later worden gepromoveerd tot exclusieve of gedegradeerd tot gedeelde vergrendelingen). Exclusieve sloten zijn niet compatibel met gedeelde sloten, dus ofwel SELECT of DELETE query wordt vergrendeld totdat een andere sessie wordt vastgelegd.

  • In databases die MVCC . gebruiken (zoals Oracle , PostgreSQL , MySQL met InnoDB ), een DML query maakt een kopie van het record (op de een of andere manier) en over het algemeen blokkeren lezers geen schrijvers en vice versa. Voor deze databases, een SELECT FOR UPDATE zou handig zijn:het zou ofwel SELECT . vergrendelen of de DELETE query totdat een andere sessie zich commit, net als SQL Server doet.

Wanneer moet men REPEATABLE_READ gebruiken? transactie-isolatie versus READ_COMMITTED met SELECT ... FOR UPDATE ?

Over het algemeen REPEATABLE READ verbiedt geen fantoomrijen (rijen die zijn verschenen of verdwenen in een andere transactie, in plaats van te worden gewijzigd)

  • In Oracle en eerder PostgreSQL versies, REPEATABLE READ is eigenlijk een synoniem voor SERIALIZABLE . Kort gezegd betekent dit dat de transactie geen wijzigingen meer ziet die zijn aangebracht nadat deze is gestart. Dus in deze opstelling is de laatste Thread 1 query zal de kamer retourneren alsof deze nooit is verwijderd (wat al dan niet is wat je wilde). Als je de kamers niet wilt tonen nadat ze zijn verwijderd, moet je de rijen vergrendelen met SELECT FOR UPDATE

  • In InnoDB , REPEATABLE READ en SERIALIZABLE zijn verschillende dingen:lezers in SERIALIZABLE mode zet next-key locks op de records die ze evalueren, waardoor de gelijktijdige DML effectief wordt voorkomen op hen. Je hebt dus geen SELECT FOR UPDATE nodig in serialiseerbare modus, maar heb ze wel nodig in REPEATABLE READ of READ COMMITED .

Merk op dat de standaard over isolatiemodi voorschrijft dat u bepaalde eigenaardigheden niet in uw zoekopdrachten ziet, maar niet definieert hoe (met vergrendeling of met MVCC of anderszins).

Als ik zeg "je hebt SELECT FOR UPDATE niet nodig" " Ik had eigenlijk moeten toevoegen "vanwege bijwerkingen van bepaalde database-engine-implementaties".



  1. Waarom is het resultaat van de rijen met explain niet gelijk aan count()?

  2. SQLiteDiskIOException:foutcode 10:schijf-I/O-fout wordt opnieuw ingesteld op ICS en Samsung Nexus op DROP TABLE

  3. Postgresql:het pg_hba.conf-bestand vinden met Mac OS X

  4. Een inconsistente PostgreSQL-slave opnieuw opbouwen