Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

Data locken in query

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben bezig met een service oriented project waar een database bij komt kijken. Uiteindelijk wordt het systeem door vele gebruikers tegelijkertijd gebruikt waardoor ik nu tegen wat synchronisatie vraagstukken aan loop.

Normaal gesproken wordt data alleen exclusief gelockt in een restricte transactie bij een Update of Insert; bij Select krijgt de data een shared lock. Goed, en nu het probleem.

We nemen een veel voorkomend probleem: data toevoegen als deze niet bestaat, of updaten als deze wel bestaat. De eerste stap is dan doorgaans om de data te selecteren, en op basis daarvan te bepalen wat daarna gebeurt (toevoegen als geen data gevonden, updaten bij wel gevonden).

Stel dat het veel tijd kost voordat een transactie gecommit kan worden als er data gemaakt moet worden omdat deze niet gevonden is. Nu is dit een race condition: twee threads kunnen een Select doen, en daarna allebei een Insert proberen. Dit is uiteraard niet de bedoeling.

Wat is het remedie hiertegen? Een Serializable transactie zet nog steeds shared locks op geselecteerde data. Gewoon keihard updaten en kijken wat de affected rows zijn werkt, maar bij 0 affected rows moet je alsnog inserten en heb je dezelfde race condition.

Wat een oplossing is, is het gebruik van hints. Dit is mij echter te database specifiek (Linq ondersteunt dit ook niet). Vandaar de vraag hoe jullie hier tegenaan kijken. Is er bijvoorbeeld een mogelijkheid om een stored procedure zegmaar atomic te laten uitvoeren?

Ik werk in Visual Studio 2008 met SQL Server 2005 Standard, maar het moet zo algemeen mogelijk blijven.

Verwijderd

Ik heb MS SQL Server nooit aangeraakt, maar je probleem is DB generiek. Als je met meer sessions dezelfde row aanpast wordt die eerst gelockt, geupdate en weer vrij gegeven. Elke database lost dat op zijn eigen manier op, dus moet je wel database specifieke oplossingen bedenken. Een oplossing is om niet multiple instances te gebruiken, maar een frontend voor je database te plakken, zodat je maar een instance van je database aanroept, qua performance win je dan de commit cycle.

Als je niks aan mijn reply hebt, heb je in ieder geval mijn medeleven :)