sql >> Databasteknik >  >> RDS >> Database

Om du använder indexerade vyer och MERGE, läs detta!

Fellow MVP Jamie Thomson påpekade nyligen att det finns en "fel resultat"-bugg i SQL Server som kan visa sig när följande villkor är uppfyllda:

  • Du har en indexerad vy som sammanfogar minst två tabeller;
  • dessa tabeller är begränsade i endera riktningen av en främmande nyckel med en kolumn;
  • du utför uppdateringar av bastabellen/tabellerna med MERGE som inkluderar både UPDATE och (DELETE eller INSERT ) insatser; och,
  • du skickar sedan frågor som refererar till indexet på vyn (avsiktligt eller inte).

Tyvärr är Knowledge Base-artikeln som beskriver problemet (KB #2756471) ganska lätt på detaljer. De berättar inte för dig hur du ska återskapa problemet, eller ens vad, specifikt, du bör leta efter för att se om detta påverkar dig; och de nämner inte ens MERGE (vilket faktiskt är kärnan i problemet, inte NOEXPAND , och inte en enkel uppdatering). Det finns några ytterligare detaljer i Connect-objektet som ledde till korrigeringen; förhoppningsvis kommer KB-artikeln att uppdateras med mer information inom kort.

Under tiden kan resultatet du se är felaktig data – eller bättre uttryckt, inaktuella data :Frågan kan visa dig den gamla versionen av de uppdaterade raden/raderna! Jag tillbringade några minuter med att försöka återskapa detta scenario i AdventureWorks, och misslyckades totalt. Tack och lov skrev Paul White (blogg | @SQL_Kiwi) ett enastående inlägg som beskrev scenariot och visade en fullständig repro av problemet.

Jag tror inte att jag kan betona hur allvarligt detta är.

Miljontals kunder använder säkert indexerade vyer, många av dem har migrerat sin DML-kod för att använda MERGE , och ett stort antal av dem finns på Enterprise Edition (eller är det inte men använder NOEXPAND ledtråd eller hänvisar direkt till indexet). Paul var snabb med att påpeka att NOEXPAND krävs inte för att reproducera problemet i Enterprise Edition, och upptäckte också många av de andra detaljerna som krävs för att reproducera felet.

Detta inlägg är inte avsett att stjäla någon åska från Jamies eller Pauls inlägg; bara ett försök att upprepa oron och öka medvetenheten om denna fråga. Om du har för vana att ignorera kumulativa uppdateringar, väljer att vänta på Service Pack och det finns någon chans att det här problemet kan påverka dig just nu, är du skyldig dig själv, för att inte tala om dina intressenter och kunder, att ta denna fråga på allvar.

Så vad ska du göra?

Nåväl, vad du gör härnäst beror på vilken version och utgåva av SQL Server du kör, och om felet faktiskt påverkar dig (eller skulle kunna).

    SQL Server 2008 SP3
    SQL Server 2008 R2 SP1/SP2
    SQL Server 2012 RTM/SP1

    Dina alternativ om du använder en av dessa versioner:

    1. Du bör uppdatera till den senaste kumulativa uppdateringen för din filial:
      Branch Fast i CU Bygg Minsta version krävs
      för att tillämpa uppdatering

      KB-artikel
      (nedladdning)
      2008 Service Pack 3 CU #8 10.00.5828 10.00.5500 KB #2771833
      2008 R2 Service Pack 1 CU #10 10.50.2868 10.50.2500 KB #2783135
      2008 R2 Service Pack 2 CU #4 10.50.4270 10.00.4000 KB #2777358
      2012 RTM CU #5 11.00.2395 11.00.2100 KB #2777772
      2012 Service Pack 1 CU #2 11.00.3339 11.00.3000 KB #2790947

      Tabell 1 :Bygger som innehåller korrigeringen

    2. Om du inte tillämpar korrigeringen måste du testa alla referenser till dina vyer för att validera att de ger korrekta resultat i alla fall – inklusive efter att du har uppdaterat bastabellerna med MERGE . Om de inte gör det (eller om du misstänker att de senare kan påverkas), bör du bygga om det klustrade indexet på alla berörda vyer (eller reparera de indexerade vyerna med DBCC CHECKTABLE , som Paul har beskrivit i sitt inlägg), och sluta använda MERGE mot dessa tabeller tills du har tillämpat korrigeringen. Om du fortsätter att använda MERGE mot bastabellerna, förbered dig på att fortsätta reparera vyerna för att undvika problemet.
    3. En snabbare lösning skulle vara att förhindra att den skadade indexerade vyn överhuvudtaget används, genom att använda någon av följande metoder som krävs:
      • tillämpa frågetipset ALTERNATIV (EXPANDERA VISNINGAR) till alla relevanta frågor;
      • ta bort alla explicita referenser till indexet på vyn;
      • i standardutgåvor eller andra utgåvor där indexerade vyer inte matchas automatiskt, ta bort alla instanser av NOEXPAND .

      Men detta skulle naturligtvis till stor del motverka syftet med den indexerade vyn – kan lika gärna släppa indexet. Som sagt, det är oftast bättre att få rätt resultat långsamt, än att få fel resultat snabbt; så det kanske är okej.

    SQL Server 2008 RTM/SP1/SP2
    SQL Server 2008 R2 RTM

    Tyvärr är du på en version som inte längre finns i mainstream-stöd, och det är osannolikt att det här problemet kommer att lösas för dig (såvida du inte har utökat stöd och du gör mycket oväsen). Så dina alternativ är begränsade här – antingen flytta till en gren som stöds enligt tabellen ovan och tillämpa den kumulativa uppdateringen, eller välj ett av de andra alternativen som nämnts tidigare.

    SQL Server 2000
    SQL Server 2005

    Tja, de dåliga nyheterna är att du också har en version som inte längre stöds. Den goda nyheten är att i det här specifika fallet spelar det ingen roll – du kan inte använda MERGE hur som helst, så det här felet kan inte påverka dig.

Andra MERGE-problem

Tyvärr är detta långt ifrån den första buggen vi har sett med MERGE , och det kommer förmodligen inte att vara den sista. Här är ett snabbt urval av ett dussin SAMMANFATTNING buggar som fortfarande är markerade som aktiva på Connect:

  • #773895 :MERGE rapporterar felaktigt unika nyckelöverträdelser
  • #766165 :MERGE utvärderar filtrerat index per rad, inte efter operation, vilket orsakar filtrerat indexöverträdelse
  • #723696 :Grundläggande MERGE-uppslagning som orsakar låsningar
  • #713699 :En kontroll av systempåståenden har misslyckats ("cxrowset.cpp":1528)
  • #699055 :SAMMANFATTNING av frågeplaner tillåter överträdelser av FK- och CHECK-begränsningar
  • #685800 :Parametriserad DELETE och MERGE Tillåt överträdelser av främmande nyckelbegränsningar
  • #654746 :sammanslagning i SQL2008 SP2 lider fortfarande av "Försök att ställa in en icke-NULL-bar kolumns värde till NULL"
  • #635778 :NOT MATCHED och MATCHED delar av en SQL MERGE-sats är inte optimerade
  • #633132 :SLUT TILL MED FILTERAD KÄLLA fungerar inte korrekt
  • #596086:MERGE-satsfel när INSERT/DELETE används och filtrerat index
  • #583719 :MERGE-satsen behandlar icke-nullbara beräknade kolumner felaktigt i vissa scenarier
  • #539084 :MERGE Stmt :Sökvillkor i en icke-nyckelkolumn och en ORDER BY i källhärledd tabell bryter MERGE fullständigt

Nu kan det vara så att några av dessa buggar faktiskt har åtgärdats, men deras status är fel eftersom slingan tillbaka till Connect inte har stängts. Även om så är fallet kan det inte vara sant för dem alla (och eventuellt för andra som jag inte upptäckte).

Dessutom har det visat sig av Dan Guzman att SAMMANSLUTNING är inte immun mot rasförhållanden och andra samtidiga problem. Lösningen är att använda HOLDLOCK (eller en högre isoleringsnivå); det är dock en vanlig missuppfattning att SAMMANSLUTNING är helt atomär och inte alls utsatt för detta problem. Därför undrar jag högt:hur många MERGE uttalanden där ute inkluderar HOLDLOCK (eller körs under SERIALIZABLE )? Hur många har noggrant testats för frågor som rör samtidighet?

Slutsats

Personligen tycker jag att syntaxen är bra (även om det är skrämmande att lära sig), men varje gång ett problem dyker upp urholkar det mitt förtroende för det praktiska i att ersätta befintlig DML med den nya konstruktionen.

Med det i åtanke, att inte vara Chicken Little, men jag skulle inte känna mig bekväm med att rekommendera någon att använda MERGE såvida de inte implementerar extremt omfattande tester. Vissa av dessa problem finns också med standard UPSERT metoder, men problemen är mer uppenbara där. SAMMANFATTNING , bara genom sin natur med ett påstående, gör att du vill tro på magi. Kanske en dag kommer det att leverera, men just nu vet jag att det inte kommer att kunna såga en person på mitten utan någon seriös hjälp.


  1. Exportera frågeresultat till en XML-fil när du använder SQLcl (Oracle)

  2. En databasmodell för en taxitjänst

  3. Välj topp 10 poster för varje kategori i MySQL

  4. Hur man hittar en tabell med en specifik kolumn i postgresql