{"id":19909,"date":"2026-06-11T15:15:29","date_gmt":"2026-06-11T13:15:29","guid":{"rendered":"https:\/\/webhosting.de\/database-row-locking-mysql-concurrency-optimieren-performance-locks\/"},"modified":"2026-06-11T15:15:29","modified_gmt":"2026-06-11T13:15:29","slug":"database-rijvergrendeling-mysql-concurrency-optimaliseren-prestaties-vergrendelingen","status":"publish","type":"post","link":"https:\/\/webhosting.de\/nl\/database-row-locking-mysql-concurrency-optimieren-performance-locks\/","title":{"rendered":"Inzicht in database rijvergrendeling en gelijktijdigheidsproblemen in MySQL"},"content":{"rendered":"<p><strong>Databaserij<\/strong> Locking bepaalt in MySQL precies welke transactie welke rijen wanneer mag lezen of schrijven, en biedt zo bescherming tegen verloren updates en \u2018dirty reads\u2019. Ik laat stap voor stap zien hoe vergrendelingen, <strong>MVCC<\/strong> en hoe isolatieniveaus op elkaar inwerken, waar er problemen met gelijktijdigheid ontstaan en hoe ik query\u2019s, indexen en transacties zo kan opzetten dat blokkades worden voorkomen.<\/p>\n\n<h2>Centrale punten<\/h2>\n<p>Om je snel een idee te geven van waar ik me in dit artikel op richt, zet ik de belangrijkste richtlijnen op een rijtje en zet ik ze kort naast elkaar. Zo krijg je een overzichtelijk kader voor de volgende, meer diepgaande <strong>Toelichtingen<\/strong>.<\/p>\n<ul>\n  <li><strong>Rijsloten<\/strong> Beperk conflicten tot afzonderlijke rijen in plaats van hele tabellen.<\/li>\n  <li><strong>MVCC<\/strong> maakt snel lezen mogelijk zonder permanente gedeelde vergrendelingen.<\/li>\n  <li><strong>Isolatie<\/strong> bepaalt welke afwijkingen zijn toegestaan.<\/li>\n  <li><strong>Gap\/Volgende-toets<\/strong> indexgaten tegen fantomen afsluiten.<\/li>\n  <li><strong>Beste praktijken<\/strong> verminderen blokkeringen en deadlocks aanzienlijk.<\/li>\n<\/ul>\n<p>Vervolgens zet ik deze punten om in concrete maatregelen waarmee ik productieve MySQL-instanties veiliger en sneller houd. Elke aanbeveling is erop gericht om minder <strong>Blokkeren<\/strong>, consistente gegevens en duidelijke diagnostische trajecten.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/06\/mysql-serverraum-9081.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Waarom controle op gelijktijdigheid noodzakelijk is<\/h2>\n<p>Gelijktijdige toegangen botsen op elkaar zodra meerdere sessies dezelfde regels willen lezen of schrijven, en daarom kies ik voor duidelijke <strong>Transactielimieten<\/strong> Acht. Zonder regels dreigen er verloren updates, dirty reads, non-repeatable reads en phantoms, die uiteindelijk tot verkeerde beslissingen in de applicatiecode leiden. Ik voorkom dit door leesconsistentie te waarborgen en schrijfconflicten vroegtijdig zichtbaar te maken, in plaats van ze stilzwijgend te overschrijven. Hoe meer parallelle gebruikers actief zijn, hoe belangrijker kleine lock-objecten en korte <strong>Wachtijden<\/strong>. Wie dit negeert, riskeert gegevensfouten, lange wachtrijen en time-outs.<\/p>\n\n<h2>De basisprincipes van rijvergrendeling in MySQL<\/h2>\n<p>Row Locking zet vergrendelingen op afzonderlijke rijen, zodat andere rijen vrij blijven en meer <strong>Parallellisme<\/strong> ontstaat. Een exclusieve lock beschermt schrijfbewerkingen tot aan de commit, terwijl leesbewerkingen, afhankelijk van het isolatieniveau, gebruikmaken van gedeelde locks of MVCC-snapshots. Intent-locks dienen als signalen op een hoger niveau, zodat de engine de lock-compatibiliteit sneller kan controleren. Ik merk altijd op dat zelfs kleine updates veel regels kunnen be\u00efnvloeden als WHERE-voorwaarden onnauwkeurig zijn en er geen <strong>Index<\/strong> leidt tot. Nauwkeurigheid in het filter voorkomt brede uitsluitingsgebieden en ontziet de concurrency.<\/p>\n<p>Ook de interactie met de indexen is belangrijk, want InnoDB vergrendelt via indexpaden; ontbrekende of ongeschikte sleutels vergroten het aantal betrokken rijen aanzienlijk. Als een statement een volledige scan uitvoert, wordt het lock-veld groter, wat wachttijden verlengt en deadlocks in de hand werkt. Daarom plan ik vanaf het begin de juiste sleutels voor veelvoorkomende paden en houd ik de WHERE-clausules zo specifiek mogelijk. Zo blijven mijn vergrendelingen beperkt en komen andere transacties sneller aan de <strong>Toegang<\/strong>. Dat is de eenvoudigste manier om het vergrendelingsmechanisme soepel te laten werken.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/06\/mysql_datenbank_probleme_4837.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Pessimistische versus optimistische locking<\/h2>\n<p>Bij pessimistisch locking wordt uitgegaan van conflicten en wordt er al vroeg geblokkeerd, wat de integriteit versterkt, maar tijd kost, terwijl <strong>optimistisch<\/strong> Systemen controleren pas aan het einde of er gegevens zijn gewijzigd. In praktijkgerichte MySQL-configuraties combineer ik beide: voor kritieke accounts boek ik met FOR UPDATE, voor entiteiten die zelden conflicteren gebruik ik versies. Een versiekolom of een tijdstempel stelt me in staat om bij de update vast te stellen of iemand sneller was, zonder de rij permanent te blokkeren. Als er een conflict optreedt, herhaal ik de transactie gericht of voer ik aangepaste bedrijfslogica uit. Zo verdeel ik de belasting netter, verminder ik wachttijden en houd ik de <strong>Correctheid<\/strong> hoog.<\/p>\n<p>Ik kies de strategie per use case: bij veel gelijktijdige leestoegangen werken optimistische benaderingen goed, terwijl voor zeer kritieke financi\u00eble of voorraadboekingen korte, maar duidelijke exclusieve vergrendelingen de beste keuze zijn. Het doel blijft altijd om slechts zoveel als nodig te blokkeren en conflicten vroegtijdig te herkennen. Met deze aanpak vermijd ik langgerekte ketens van wachtende sessies. Hierdoor stijgt de doorvoer en <strong>Betrouwbaarheid<\/strong> in het dagelijks leven.<\/p>\n\n<h2>Inzicht in isolatieniveaus en MVCC<\/h2>\n<p>De isolatiegraad bepaalt hoeveel afwijkingen ik toestaat en hoe streng MySQL vergrendelt; daarom kies ik het niveau bewust op basis van de use case. READ COMMITTED voorkomt 'dirty reads', REPEATABLE READ houdt de waarden van een transactie consistent en SERIALIZABLE zorgt voor de strengste volgorde. InnoDB maakt gebruik van <strong>MVCC<\/strong>, zodat lezers bijna altijd zonder shared locks kunnen werken en toch consistente snapshots te zien krijgen. Wie hiermee werkt, moet begrijpen wanneer gap- en next-key-locks extra in werking treden om phantoms te voorkomen. Voor meer achtergrondinformatie is het de moeite waard om eens te kijken naar <a href=\"https:\/\/webhosting.de\/nl\/mysql-isolatieniveau-hosting-server-consistentie-transacties\/\">Details over isolatieniveaus<\/a>, zodat je de effecten per niveau goed kunt inschatten.<\/p>\n<p>In de volgende tabel worden gangbare beveiligingsniveaus gerangschikt op basis van typische afwijkingen en de invloed op blokkeringen, zodat ik de juiste keuze kan maken en onnodige <strong>Blokkeren<\/strong> vermijden.<\/p>\n<table>\n  <thead>\n    <tr>\n      <th>Isolatieniveau<\/th>\n      <th>Toegestane afwijkingen<\/th>\n      <th>Lock-gedrag (vereenvoudigd)<\/th>\n      <th>Typisch gebruik<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>NIET-VASTGELEGD LEZEN<\/td>\n      <td>Dirty Reads, Non-Repeatable, Phantoms<\/td>\n      <td>Nauwelijks beperkingen, hoge <strong>Risico's<\/strong><\/td>\n      <td>Zelden zinvol<\/td>\n    <\/tr>\n    <tr>\n      <td>READ COMMITTED<\/td>\n      <td>Niet-herhaalbaar, fantoomwaarden<\/td>\n      <td>Lezers gebruiken MVCC, schrijvers <strong>X-Locks<\/strong><\/td>\n      <td>Rapporten, API's met veel leesverzoeken<\/td>\n    <\/tr>\n    <tr>\n      <td>HERHAALBAAR LEZEN<\/td>\n      <td>Phantoms in de aanbieding bij Next-Key<\/td>\n      <td>Sterke consistentie bij het lezen, gericht <strong>Gap<\/strong>-Vergrendelen<\/td>\n      <td>Standaard in InnoDB<\/td>\n    <\/tr>\n    <tr>\n      <td>SERIALISABLE<\/td>\n      <td>Geen afwijkingen<\/td>\n      <td>Breder, lager <strong>Parallellisme<\/strong><\/td>\n      <td>Zeer kritieke processen<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n<p>Ik begin meestal met REPEATABLE READ en pas dit gericht aan als query\u2019s te veel vertraging oplopen door Next-Key-locks. Omgekeerd gebruik ik SERIALIZABLE alleen wanneer dat vanuit functioneel oogpunt onvermijdelijk is, omdat de wachttijden anders oplopen. Door een duidelijke keuze per workload houd ik gegevens consistent en bescherm ik tegelijkertijd de <strong>Prestaties<\/strong>. Deze aanpak bespaart supporttijd, omdat er minder vaak onverwachte pieken in het aantal vergrendelingen optreden. Zo blijft het systeem voorspelbaar, ook als het aantal gebruikers toeneemt.<\/p>\n\n<h2>MySQL-concurrency in de praktijk<\/h2>\n<p>Goede concurrency begint bij duidelijk geformuleerde query\u2019s die alleen de werkelijk benodigde rijen opleveren, zodat InnoDB kleine <strong>Rij<\/strong>-vergrendelingen kan instellen. Ik zorg ervoor dat filtervoorwaarden sargable zijn, dat wil zeggen dat ze via indexen lopen en geen functieaanroepen op kolommen vereisen. Updates houd ik gericht: duidelijke WHERE-clausule, geschikte index, geen onnodige joins in dezelfde instructie. Voor reserveringen gebruik ik FOR UPDATE spaarzaam en alleen voor de daadwerkelijk betrokken records. Bovendien vermijd ik lange gebruikersinteracties tussen BEGIN en COMMIT, want elke seconde verhoogt de <strong>wachttijd<\/strong> andere sessies.<\/p>\n<p>Bij invoegingen in drukke indexruimtes houd ik er rekening mee dat er Next-Key-locks kunnen optreden, waardoor meer transacties in de wachtrij terechtkomen. Ik spreid hotspots door sleutelruimten te verspreiden of het schrijfpad te ontlasten in een kleine, afzonderlijke wachtrij. Zo verminder ik de botsingen op de drukste tabel. Deze verfijning heeft een groter effect dan het verhogen van time-outs, omdat er minder <strong>Conflicten<\/strong> over het algemeen ontstaan. Juist daarom is het de moeite waard om het dataverkeer v\u00f3\u00f3r de livegang te meten.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/06\/mysql-row-locking-concurrency-9835.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Typische problemen met gelijktijdigheid: blokkering, deadlocks, omvang van vergrendelingen<\/h2>\n<p>Er ontstaat een blokkering wanneer een transactie wacht op een regel die al is vergrendeld; daarom houd ik transacties kort en de betreffende <strong>Aantal<\/strong> beperk. Deadlocks treden op wanneer twee transacties elkaar blokkeren; MySQL herkent dit en breekt een van beide af. Ik reageer hierop met gerichte herhalingspogingen en een consistente toegangsvolgorde in alle codepaden. Lock-escalatie komt in InnoDB minder vaak voor, maar interne limieten beperken de beheersinspanning; grote scans brengen de engine dichter bij dergelijke grenzen. Wie herhaaldelijk deadlocks ziet, moet de <a href=\"https:\/\/webhosting.de\/nl\/database-impasse-detectie-afhandeling-hosting-infrastructuur\/\">Detectie en afhandeling van deadlocks<\/a> systematisch controleren en de bronnen van conflicten wegnemen, in plaats van alleen de time-outs te verlengen.<\/p>\n<p>Mijn ervaring leert dat er drie patronen zijn die voor bijzonder veel wachttijd zorgen: niet-ge\u00efndexeerde filters op veelgebruikte tabellen, FOR UPDATE zonder exacte WHERE-clausule en uitgebreide bedrijfslogica tussen de lees- en schrijfstap. Ik los dit op door elk pad afzonderlijk te meten, de vergrendelingsduur te verkorten en de SQL-statements af te stemmen op indexpaden. Kleine aanpassingen aan het filter of aan de volgorde van de updates lossen vaak hele knelpunten op. Dergelijke correcties zijn goedkoper dan meer <strong>Hardware<\/strong>, omdat ze een blijvend effect hebben. Pas daarna is het de moeite waard om na te denken over verticale of horizontale schaalvergroting.<\/p>\n\n<h2>Beste praktijken tegen blokkeringen en deadlocks<\/h2>\n<p>Ik rond transacties snel af en laat geen invoerformulieren openstaan terwijl er locks worden vastgehouden, omdat elke seconde onnodige <strong>Wachtrijen<\/strong> Ik zorg ervoor dat tabellen en rijen altijd in dezelfde volgorde worden verwerkt om cyclische afhankelijkheden te voorkomen. Voor louter leesbewerkingen volstaat READ COMMITTED vaak, terwijl ik bij kritieke updates REPEATABLE READ of tijdelijk FOR UPDATE gebruik. Indexontwerp blijft een must: zonder de juiste sleutel blokkeert een statement al snel veel te veel rijen. Foutafhandeling hoort er ook bij: ik vang deadlock-fouten op, log alle details en probeer een korte, nette <strong>Opnieuw proberen<\/strong>.<\/p>\n<p>Monitoring maakt het pakket compleet: ik houd wachttijden, deadlock-aantallen en queryplannen in de gaten en optimaliseer eerst de opvallende pieken. Kleine verbeteringen in hotpaths leveren enorm veel op, omdat ze effect hebben op elke query. Zo zorg ik voor minder blokkades, meer doorvoer en betrouwbare responstijden. Deze aanpak werkt in de dagelijkse praktijk veel beter dan grootschalige herontwerpen. Strakke routines zijn beter dan algemene <strong>Acties<\/strong> bijna altijd.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/06\/techoffice2976.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>MySQL-specifieke tips voor een hogere gelijktijdigheid<\/h2>\n<p>Ik maak bewust gebruik van autocommit: afzonderlijke statements hebben hier baat bij, terwijl samenhangende wijzigingen in een korte, duidelijke <strong>Transactie<\/strong> landt. SELECT \u2026 FOR UPDATE gebruik ik spaarzaam en alleen voor records die ik echt moet reserveren. Lange rapporten verplaats ik naar replica\u2019s of analytische systemen, zodat OLTP-workloads niet hoeven te wachten. Daarnaast controleer ik regelmatig welke statements ongewoon veel locks vasthouden en waarom. Wie zich hier verder in wil verdiepen, moet de <a href=\"https:\/\/webhosting.de\/nl\/mysql-opslagengine-innodb-myisam-webhosting-serverflux\/\">Opslagengine InnoDB<\/a> en indexlay-outs zorgvuldig beoordelen in de context van het eigen schema, voordat de volgende release live gaat.<\/p>\n<p>Ik minimaliseer hotspots door de primaire sleutels zo te kiezen dat de schrijfbelasting niet voortdurend aan het einde van een monotoon groeiende index samenkomt. Ook splits ik batchbewerkingen op in kleine stukjes om geen lange exclusieve vergrendelingen te veroorzaken. Met deze aanpak blijven vergrendelingen korter en neemt de contention meetbaar af. Hierdoor daalt het foutenpercentage en reageert de applicatie soepeler. Zo cre\u00eber ik reserves zonder meteen nieuwe <strong>Server<\/strong> opbouwen.<\/p>\n\n<h2>Monitoring en analyse: wat ik meet<\/h2>\n<p>Ik begin met statistieken over lock-wachttijden, het aantal deadlocks, lange transacties en de belangrijkste statements op basis van looptijd, zodat ik de grootste <strong>Hendel<\/strong> herken. Het Performance Schema, SHOW ENGINE INNODB STATUS en de logbestanden met trage query\u2019s geven me concrete aanwijzingen. Daarna bekijk ik de uitvoeringsplannen van de slechtste query's en controleer ik of er indexen ontbreken of dat filters niet op de index kunnen worden gefilterd. Zodra ik knelpunten heb verholpen, observeer ik het effect gedurende meerdere piekperiodes. Deze cyclus van meten, aanpassen en verifi\u00ebren zorgt ervoor dat de <strong>kwaliteit<\/strong> de concurrentie merkbaar toeneemt.<\/p>\n<p>Voor betrouwbare conclusies heb ik realistische testgegevens en echte toegangsmodellen nodig, niet alleen synthetische single-shot-tests. Belastingsprofielen met gelijktijdige sessies laten zien hoe locks echt werken. Dergelijke tests brengen verborgen hotspots aan het licht die in de dagelijkse praktijk anders pas laat opvallen. Wie releases op deze manier test, voorkomt verrassingen in de live-omgeving. Dat bespaart op de lange termijn kosten, tijd en zenuwen. <strong>Bekijk<\/strong>.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/06\/mysql_locking_problem_3021.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Hostingomgeving en databaseprestaties<\/h2>\n<p>Goede concurrency is afhankelijk van snelle hardware, want elke IO-vertraging verlengt de <strong>Sluitsnelheid<\/strong>. Ik let op snelle SSD\u2019s, voldoende RAM voor bufferpools en korte verbindingswegen tussen de app en de database. CPU-reserves helpen om parallelle query\u2019s zonder opstoppingen uit te voeren. Ik verminder netwerkvertragingen consequent, zodat roundtrips de effectieve blokkeringstijd niet opdrijven. Wie deze randvoorwaarden in het oog houdt, krijgt responsieve <strong>Diensten<\/strong> en minder miskramen.<\/p>\n<p>Ook doordachte schaalbaarheidstrajecten zijn belangrijk: read-replica\u2019s voor rapportages, sharding voor zeer grote datasets en afzonderlijke systemen voor analyse-workloads. Ik kies pas na metingen welke optie de moeite waard is en vermijd overhaaste beslissingen. Architectuur en SQL-discipline vullen elkaar aan; zonder goed opgestelde query's biedt hardware slechts een kortstondige oplossing. Met een goede mix verminder ik lock-conflicten aanzienlijk. Het resultaat is een betrouwbare gebruikerservaring zonder opvallende <strong>Wachttijden<\/strong>.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/06\/mysql-zeilensperrung-4839.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Lock-types in InnoDB in detail<\/h2>\n<p>Om weloverwogen beslissingen te nemen over querypaden, ben ik goed op de hoogte van de belangrijkste soorten locks: record-locks vergrendelen afzonderlijke indexvermeldingen, gap-locks vergrendelen de ruimte tussen twee indexvermeldingen, en next-key-locks zijn een combinatie van beide. Deze laatste voorkomen phantoms bij range-scans. Insert-Intention-Locks geven aan dat er iets ingevoegd gaat worden en maken het mogelijk om tegelijkertijd dingen in verschillende openingen in te voegen, zonder elkaar onnodig in de weg te zitten. Bij eenduidige zoekopdrachten via een unieke index beperkt InnoDB de vergrendeling tot een record-lock, wat blokkades minimaliseert. Zodra er een range-predikaat in het spel komt (BETWEEN, &gt;, LIKE met voorvoegsel), treedt vaak een next-key-lock in werking en daarmee een breder vergrendelingsgebied.<\/p>\n<p>Daarom ontwerp ik query\u2019s zo dat ze zoveel mogelijk op unieke of zeer selectieve indexen terechtkomen. Niet alleen WHERE is bepalend: ook ORDER BY, LIMIT en de volgorde van JOIN\u2019s be\u00efnvloeden het gekozen indexpad \u2013 en daarmee de omvang van de vergrendelingen. Een gerichte herschrijving die gebruikmaakt van een ORDER BY met een passende index kan Next-Key-locks voorkomen en de wachttijden aanzienlijk verkorten.<\/p>\n\n<h2>Locking-reads doelgericht inzetten<\/h2>\n<p>Locking-reads zijn handig als ik rijen moet reserveren of concurrerende updates moet co\u00f6rdineren. In MySQL gebruik ik:<\/p>\n<ul>\n  <li>SELECT \u2026 FOR UPDATE: exclusieve vergrendeling op gelezen rijen, geschikt voor reserveringen voorafgaand aan een update.<\/li>\n  <li>SELECT \u2026 FOR SHARE (of LOCK IN SHARE MODE in oudere versies): gedeelde vergrendeling om consistente, alleen-lezen-bewerkingen te garanderen.<\/li>\n  <li>NOWAIT en SKIP LOCKED: voorkom lange wachttijden \u2013 NOWAIT stopt onmiddellijk, SKIP LOCKED slaat geblokkeerde regels over.<\/li>\n<\/ul>\n<p>Een veelgebruikt patroon voor takenwachtrijen:<\/p>\n<pre><code>START TRANSACTION;\nSELECT id, payload\nFROM jobs\nWHERE status = 'ready'\nORDER BY priority, id\nLIMIT 50\nFOR UPDATE SKIP LOCKED;\n-- markeer als 'processing' en commit\nUPDATE jobs SET status = 'processing' WHERE id IN (...);\nCOMMIT;<\/code><\/pre>\n<p>Zo verwerk ik taken parallel zonder dat ze elkaar blokkeren. Belangrijk blijft: nauwkeurige WHERE-clausules, een geschikte index op (status, priority, id) en korte transacties.<\/p>\n\n<h2>Metadata Locks (MDL) begrijpen<\/h2>\n<p>Naast rijvergrendelingen bestaan er metadatavergrendelingen die DDL en DML co\u00f6rdineren. Elke lopende query houdt een MDL-leesvergrendeling op de betreffende tabellen vast; DDL vereist exclusieve MDL-vergrendelingen. Een ondoordacht gestarte ALTER TABLE kan daarom wachten tot lange transacties of rapporten zijn voltooid \u2013 omgekeerd blokkeert een DDL op zijn beurt weer nieuwe DML-toegangen. Ik plan schemawijzigingen daarom buiten de piekuren, verkort de transactieduur en controleer v\u00f3\u00f3r implementaties of sessies tabellen minutenlang openhouden. Online DDL-varianten verlichten veel problemen, maar vervangen geen discipline bij transactietijden. Bij de monitoring let ik specifiek op MDL-waits, omdat deze vermijdbare opstoppingen signaleren.<\/p>\n\n<h2>Vreemde sleutels, cascades en indexverplichting<\/h2>\n<p>Foreign keys verbeteren de gegevenskwaliteit, maar vergroten de lock-footprint. InnoDB controleert de consistentie via indexen \u2013 als deze ontbreken op de foreign key-kolommen, dreigen er uitgebreide scans en langdurige vergrendelingen. Daarom zorg ik voor indexen op elke verwijzende kolom. Cascading updates\/deletes kunnen meerdere tabellen in \u00e9\u00e9n transactie vergrendelen en zo deadlocks bevorderen. Ik definieer een vaste toegangsvolgorde voor alle betrokken tabellen en houd wijzigingen klein. Waar cascades in de praktijk zeldzaam zijn, onderzoek ik alternatieven: expliciete, korte stappen met duidelijke WHERE-voorwaarden, om de vergrendelingsduur voorspelbaar te houden.<\/p>\n\n<h2>Auto-increment, hotspots en bulk-invoegingen<\/h2>\n<p>Primair sleutels die monotoon toenemen, veroorzaken aan het einde van de geclusterde index een hotspot. Veel parallelle invoegingen komen daar samen, wat de wachttijden verlengt. Ik spreid sleutels (bijvoorbeeld door middel van partitiesleutels of voorafgaande entiteits-ID's) of gebruik korte batchgroottes die netjes worden vastgelegd. Ik regel het auto-increment-gedrag via de lock-mode: voor OLTP geef ik de voorkeur aan instellingen die parallelle inserts toestaan en slechts kort blokkeren. Bij grote batches controleer ik of een COPY-achtig pad of kleine, herhaalbare subsets sneller zijn. Belangrijk blijft: maak indexen pas aan na grote laadprocessen of ontlast secundaire indexen tijdens het laden om invoeghotspots te verminderen.<\/p>\n\n<h2>Replicatie en consistente leesbewerkingen<\/h2>\n<p>Bij het lezen van replica\u2019s houd ik rekening met vertragingen: anders kan een rapport verouderde gegevens weergeven. Voor consistente snapshots start ik transacties bewust met WITH CONSISTENT SNAPSHOT en stel ik READ ONLY in als er alleen wordt gelezen. Zo behoud ik een stabiel overzicht over meerdere statements \u2013 zonder onnodige blokkades. Tegelijkertijd zorg ik ervoor dat de applicatie bij replicatievertragingen tolerante paden heeft of indien nodig uitwijkt naar de primaire server, wanneer absolute actualiteit cruciaal is. Dit vermindert verrassingen en verklaart schijnbare \u201eanomalie\u00ebn\u201c, die in werkelijkheid slechts replicatielatenties zijn.<\/p>\n\n<h2>Configuratie en herhalingsstrategie\u00ebn<\/h2>\n<p>Ik pas lock-wachttijden en detectie op een zinvolle manier aan: een redelijke innodb_lock_wait_timeout voorkomt dat sessies minutenlang vastlopen. Ik herken deadlocks proactief en maak een duidelijk onderscheid: fout 1213 (deadlock) haal ik kort op met backoff en jitter; fout 1205 (lock wait timeout) beschouw ik als een signaal om het querypad te optimaliseren. innodb_deadlock_detect helpt bij veel korte transacties; bij extreem hoge parallelliteit kan de kosten-batenverhouding doorslaan \u2013 dan is het ontlasten van de hotspots bijna altijd de betere oplossing dan alleen maar aan de parameters draaien.<\/p>\n<p>Herhalingen zijn alleen veilig als bewerkingen idempotent zijn. Ik ontwerp updatepaden zo dat een herhalingspoging dezelfde eindtoestand bereikt (bijvoorbeeld met versiekolommen, deterministische sets in plaats van incrementen of duidelijke zakelijke gebeurtenissen). Zo voorkom ik dubbele boekingen en houd ik de code robuust tegen onvermijdelijke conflicten.<\/p>\n\n<h2>Voorbeelden: batches zonder brede blokkades<\/h2>\n<p>Grote wijzigingen verdeel ik op basis van de primaire sleutel in kleine, ge\u00efndexeerde stukjes:<\/p>\n<pre><code>-- Voorbeeld: in batches verwijderen\nSET @last_id = 0;\nWHILE 1 DO\n  DELETE FROM events\n  WHERE id &gt; @last_id\n  ORDER BY id\n  LIMIT 1000;\n  SET @rows = ROW_COUNT();\n  IF @rows = 0 THEN LEAVE; END IF;\n  SET @last_id = (SELECT MAX(id) FROM events WHERE id &lt;= @last_id + 1000);\nEND WHILE;<\/code><\/pre>\n<p>Dit patroon houdt transacties kort, verkort de duur van locks en geeft andere workloads de ruimte. Bij bulkupdates ga ik op dezelfde manier te werk: ik selecteer eerst de doel-ID\u2019s in een tijdelijke set (of via een LIMIT-venster), schrijf vervolgens gericht en commit snel.<\/p>\n\n<h2>Handleiding voor snelle diagnose<\/h2>\n<p>Als de wachttijden oplopen, werk ik in een vaste volgorde:<\/p>\n<ol>\n  <li>Het probleem afbakenen: welke tabellen, welke query's, op welk tijdstip?<\/li>\n  <li>Wachtrijen zichtbaar maken: in Performance Schema de data_locks\/data_lock_waits en blokkerende PID\u2019s vaststellen; daarnaast de huidige InnoDB-status controleren.<\/li>\n  <li>Queryplan controleren: maakt de query gebruik van de verwachte index? Zijn de predicaten indexeerbaar?<\/li>\n  <li>Het aantal vergrendelingen verminderen: WHERE-voorwaarden verfijnen, indexen toevoegen, range-scans vermijden, vergrendelingslezen beperken.<\/li>\n  <li>De transactieduur verkorten: interacties en externe oproepen uit de transactie verwijderen, result sets verkleinen.<\/li>\n  <li>Herhalen en meten: controleer en vergelijk de piekwaarden opnieuw na de wijziging.<\/li>\n<\/ol>\n<p>Deze aanpak voorkomt dat men op goed geluk te werk gaat. In plaats van de time-outs te verhogen, pak ik de oorzaken aan \u2013 dat is duurzamer en meestal ook sneller.<\/p>\n\n<h2>Operationele valkuilen vermijden<\/h2>\n<p>Er zijn drie zaken waar ik tijdens het gebruik extra op let: ten eerste schakel ik autocommit niet per ongeluk globaal uit \u2013 dat verlengt vergrendelingen ongemerkt. Ten tweede voorkom ik dat connection pools transacties doorgeven die al openstaande vergrendelingen bevatten. Ten derde gebruik ik savepoints gericht voor gedeeltelijke terugdraaiingen, maar verwacht ik niet dat ze de duur van de locks verkorten: de vergrendeling blijft bestaan tot de commit of rollback. Een strikte discipline in de applicatielaag leidt hier direct tot kortere wachttijden.<\/p>\n\n<h2>In het kort: de belangrijkste lessen<\/h2>\n<p>Row Locking zorgt voor gegevensconsistentie, maar alleen in combinatie met <strong>MVCC<\/strong>, de juiste isolatieniveaus en een goed indexontwerp komen de sterke punten ervan volledig tot hun recht. Ik houd transacties kort, filter gericht en gebruik FOR UPDATE alleen wanneer reservering vanuit functioneel oogpunt noodzakelijk is. Ik verminder conflicten door consistente toegangsvolgordes en duidelijke herhalingspogingen bij deadlocks. Ik kies isolatieniveaus per use case en observeer hoe gap- en next-key-locks uitwerken. Wie meet en regelmatig bijstelt, bereikt hoge <strong>Concurrentie<\/strong> zonder verrassingen.<\/p>\n<p>Uiteindelijk zijn er drie dingen die tellen: kleine lock-objecten, korte verwerkingstijden en traceerbare querypaden. Met deze principes draaien MySQL-workloads betrouwbaar, zelfs als er veel gebruikers tegelijkertijd actief zijn. Ik zet in op herhaalbare tests, zinvolle statistieken en gerichte optimalisaties in plaats van grote aanpassingen. Zo blijven gegevens correct, blijven responstijden laag en komen deadlocks zelden voor. Dat is precies wat elk team verwacht van een responsieve <strong>Database<\/strong>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Leer hoe database rijvergrendeling werkt en hoe u MySQL gelijktijdigheid kunt optimaliseren. Voorkom transactieblokkering en deadlocks met praktische tips.<\/p>","protected":false},"author":1,"featured_media":19902,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[781],"tags":[],"class_list":["post-19909","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-datenbanken-administration-anleitungen"],"acf":[],"_wp_attached_file":null,"_wp_attachment_metadata":null,"litespeed-optimize-size":null,"litespeed-optimize-set":null,"_elementor_source_image_hash":null,"_wp_attachment_image_alt":null,"stockpack_author_name":null,"stockpack_author_url":null,"stockpack_provider":null,"stockpack_image_url":null,"stockpack_license":null,"stockpack_license_url":null,"stockpack_modification":null,"color":null,"original_id":null,"original_url":null,"original_link":null,"unsplash_location":null,"unsplash_sponsor":null,"unsplash_exif":null,"unsplash_attachment_metadata":null,"_elementor_is_screenshot":null,"surfer_file_name":null,"surfer_file_original_url":null,"envato_tk_source_kit":null,"envato_tk_source_index":null,"envato_tk_manifest":null,"envato_tk_folder_name":null,"envato_tk_builder":null,"envato_elements_download_event":null,"_menu_item_type":null,"_menu_item_menu_item_parent":null,"_menu_item_object_id":null,"_menu_item_object":null,"_menu_item_target":null,"_menu_item_classes":null,"_menu_item_xfn":null,"_menu_item_url":null,"_trp_menu_languages":null,"rank_math_primary_category":null,"rank_math_title":null,"inline_featured_image":null,"_yoast_wpseo_primary_category":null,"rank_math_schema_blogposting":null,"rank_math_schema_videoobject":null,"_oembed_049c719bc4a9f89deaead66a7da9fddc":null,"_oembed_time_049c719bc4a9f89deaead66a7da9fddc":null,"_yoast_wpseo_focuskw":null,"_yoast_wpseo_linkdex":null,"_oembed_27e3473bf8bec795fbeb3a9d38489348":null,"_oembed_c3b0f6959478faf92a1f343d8f96b19e":null,"_trp_translated_slug_en_us":null,"_wp_desired_post_slug":null,"_yoast_wpseo_title":null,"tldname":null,"tldpreis":null,"tldrubrik":null,"tldpolicylink":null,"tldsize":null,"tldregistrierungsdauer":null,"tldtransfer":null,"tldwhoisprivacy":null,"tldregistrarchange":null,"tldregistrantchange":null,"tldwhoisupdate":null,"tldnameserverupdate":null,"tlddeletesofort":null,"tlddeleteexpire":null,"tldumlaute":null,"tldrestore":null,"tldsubcategory":null,"tldbildname":null,"tldbildurl":null,"tldclean":null,"tldcategory":null,"tldpolicy":null,"tldbesonderheiten":null,"tld_bedeutung":null,"_oembed_d167040d816d8f94c072940c8009f5f8":null,"_oembed_b0a0fa59ef14f8870da2c63f2027d064":null,"_oembed_4792fa4dfb2a8f09ab950a73b7f313ba":null,"_oembed_33ceb1fe54a8ab775d9410abf699878d":null,"_oembed_fd7014d14d919b45ec004937c0db9335":null,"_oembed_21a029d076783ec3e8042698c351bd7e":null,"_oembed_be5ea8a0c7b18e658f08cc571a909452":null,"_oembed_a9ca7a298b19f9b48ec5914e010294d2":null,"_oembed_f8db6b27d08a2bb1f920e7647808899a":null,"_oembed_168ebde5096e77d8a89326519af9e022":null,"_oembed_cdb76f1b345b42743edfe25481b6f98f":null,"_oembed_87b0613611ae54e86e8864265404b0a1":null,"_oembed_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_oembed_time_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_tldname":null,"_tldclean":null,"_tldpreis":null,"_tldcategory":null,"_tldsubcategory":null,"_tldpolicy":null,"_tldpolicylink":null,"_tldsize":null,"_tldregistrierungsdauer":null,"_tldtransfer":null,"_tldwhoisprivacy":null,"_tldregistrarchange":null,"_tldregistrantchange":null,"_tldwhoisupdate":null,"_tldnameserverupdate":null,"_tlddeletesofort":null,"_tlddeleteexpire":null,"_tldumlaute":null,"_tldrestore":null,"_tldbildname":null,"_tldbildurl":null,"_tld_bedeutung":null,"_tldbesonderheiten":null,"_oembed_ad96e4112edb9f8ffa35731d4098bc6b":null,"_oembed_8357e2b8a2575c74ed5978f262a10126":null,"_oembed_3d5fea5103dd0d22ec5d6a33eff7f863":null,"_eael_widget_elements":null,"_oembed_0d8a206f09633e3d62b95a15a4dd0487":null,"_oembed_time_0d8a206f09633e3d62b95a15a4dd0487":null,"_aioseo_description":null,"_eb_attr":null,"_eb_data_table":null,"_oembed_819a879e7da16dd629cfd15a97334c8a":null,"_oembed_time_819a879e7da16dd629cfd15a97334c8a":null,"_acf_changed":null,"_wpcode_auto_insert":null,"_edit_last":null,"_edit_lock":null,"_oembed_e7b913c6c84084ed9702cb4feb012ddd":null,"_oembed_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_time_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_03514b67990db061d7c4672de26dc514":null,"_oembed_time_03514b67990db061d7c4672de26dc514":null,"rank_math_news_sitemap_robots":null,"rank_math_robots":null,"_eael_post_view_count":"371","_trp_automatically_translated_slug_ru_ru":null,"_trp_automatically_translated_slug_et":null,"_trp_automatically_translated_slug_lv":null,"_trp_automatically_translated_slug_fr_fr":null,"_trp_automatically_translated_slug_en_us":null,"_wp_old_slug":null,"_trp_automatically_translated_slug_da_dk":null,"_trp_automatically_translated_slug_pl_pl":null,"_trp_automatically_translated_slug_es_es":null,"_trp_automatically_translated_slug_hu_hu":null,"_trp_automatically_translated_slug_fi":null,"_trp_automatically_translated_slug_ja":null,"_trp_automatically_translated_slug_lt_lt":null,"_elementor_edit_mode":null,"_elementor_template_type":null,"_elementor_version":null,"_elementor_pro_version":null,"_wp_page_template":null,"_elementor_page_settings":null,"_elementor_data":null,"_elementor_css":null,"_elementor_conditions":null,"_happyaddons_elements_cache":null,"_oembed_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_time_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_time_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_59808117857ddf57e478a31d79f76e4d":null,"_oembed_time_59808117857ddf57e478a31d79f76e4d":null,"_oembed_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_time_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_81002f7ee3604f645db4ebcfd1912acf":null,"_oembed_time_81002f7ee3604f645db4ebcfd1912acf":null,"_elementor_screenshot":null,"_oembed_7ea3429961cf98fa85da9747683af827":null,"_oembed_time_7ea3429961cf98fa85da9747683af827":null,"_elementor_controls_usage":null,"_elementor_page_assets":null,"_elementor_screenshot_failed":null,"theplus_transient_widgets":null,"_eael_custom_js":null,"_wp_old_date":null,"_trp_automatically_translated_slug_it_it":null,"_trp_automatically_translated_slug_pt_pt":null,"_trp_automatically_translated_slug_zh_cn":null,"_trp_automatically_translated_slug_nl_nl":null,"_trp_automatically_translated_slug_pt_br":null,"_trp_automatically_translated_slug_sv_se":null,"rank_math_analytic_object_id":null,"rank_math_internal_links_processed":"1","_trp_automatically_translated_slug_ro_ro":null,"_trp_automatically_translated_slug_sk_sk":null,"_trp_automatically_translated_slug_bg_bg":null,"_trp_automatically_translated_slug_sl_si":null,"litespeed_vpi_list":null,"litespeed_vpi_list_mobile":null,"rank_math_seo_score":null,"rank_math_contentai_score":null,"ilj_limitincominglinks":null,"ilj_maxincominglinks":null,"ilj_limitoutgoinglinks":null,"ilj_maxoutgoinglinks":null,"ilj_limitlinksperparagraph":null,"ilj_linksperparagraph":null,"ilj_blacklistdefinition":null,"ilj_linkdefinition":null,"_eb_reusable_block_ids":null,"rank_math_focus_keyword":"Database Row","rank_math_og_content_image":null,"_yoast_wpseo_metadesc":null,"_yoast_wpseo_content_score":null,"_yoast_wpseo_focuskeywords":null,"_yoast_wpseo_keywordsynonyms":null,"_yoast_wpseo_estimated-reading-time-minutes":null,"rank_math_description":null,"surfer_last_post_update":null,"surfer_last_post_update_direction":null,"surfer_keywords":null,"surfer_location":null,"surfer_draft_id":null,"surfer_permalink_hash":null,"surfer_scrape_ready":null,"_thumbnail_id":"19902","footnotes":null,"_links":{"self":[{"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/posts\/19909","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/comments?post=19909"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/posts\/19909\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/media\/19902"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/media?parent=19909"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/categories?post=19909"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/nl\/wp-json\/wp\/v2\/tags?post=19909"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}