Hantering av databasens samtidighetsproblem i Updategrams (SQLXML 4.0)

gäller för:SQL ServerAzure SQL Database

Liksom andra databasuppdateringsmekanismer måste updategrams hantera samtidiga uppdateringar av data i en multianvändarmiljö. Updategrams använder Optimistic Concurrency Control, som använder jämförelse av utvalda fältdata som snapshots för att säkerställa att den data som ska uppdateras inte har ändrats av en annan användarapplikation sedan den lästes från databasen. Updategrams inkluderar dessa snapshot-värden i <före-blocket> av updategram. Innan databasen uppdateras kontrollerar uppdateringsgrammet de värden som anges i före-blocket<> mot de värden som för närvarande finns i databasen för att säkerställa att uppdateringen är gäld.

Optimistic Concurrency Control erbjuder tre skyddsnivåer i ett uppdateringsgram: låg (ingen), mellannivå och hög. Du kan avgöra vilken skyddsnivå du behöver genom att specificera updategrammet därefter.

Lägsta skyddsnivå

Denna nivå är en blind uppdatering, där uppdateringen bearbetas utan hänvisning till andra uppdateringar som gjorts sedan databasen senast lästes. I ett sådant fall anger du endast primärnyckelkolumnen/kolumnerna i före-blocket<> för att identifiera posten, och du anger den uppdaterade informationen i <efter-blocket>.

Till exempel är det nya kontaktnumret i följande uppdateringsgram korrekt, oavsett vad telefonnumret tidigare var. Lägg märke till hur före-blocket<> endast anger primärnyckelkolumnen (ContactID).

<ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">  
<updg:sync >  
<updg:before>  
   <Person.Contact ContactID="1" />  
</updg:before>  
<updg:after>  
   <Person.Contact ContactID="1" Phone="111-111-1111" />  
</updg:after>  
</updg:sync>  
</ROOT>  

Mellanliggande skyddsnivå

På denna skyddsnivå jämför uppdateringsgrammet det aktuella värdet/värdena på den data som uppdateras med värdet/värdena i databaskolumnen/kolumnerna för att säkerställa att värdena inte har ändrats av någon annan transaktion sedan posten lästes av din transaktion.

Du kan få denna skyddsnivå genom att ange primärnyckelkolumnen/kolumnerna och kolumnen/kolumnerna du uppdaterar i före-blocket<>.

Till exempel ändrar detta uppdateringsgram värdet i kolumnen Phone i Person.Contact-tabellen för kontakten med ContactID 1. Före-blocket<> specificerar Phone-attributet för att säkerställa att detta attributvärde matchar värdet i motsvarande kolumn i databasen innan det uppdaterade värdet tillämpas.

<ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">  
<updg:sync >  
<updg:before>  
   <Person.Contact ContactID="1" Phone="398-555-0132" />  
</updg:before>  
<updg:after>  
   <Person.Contact ContactID="1" Phone="111-111-1111" />  
</updg:after>  
</updg:sync>  
</ROOT>  

Hög skyddsnivå

En hög skyddsnivå säkerställer att posten förblir densamma sedan din ansökan senast läste posten (det vill säga, eftersom din applikation har läst posten har den inte ändrats av någon annan transaktion).

Det finns två sätt att få denna höga skyddsnivå mot samtidiga uppdateringar:

  • Ange ytterligare kolumner i tabellen i <före-blocket> .

    Om du specificerar ytterligare kolumner i före-blocket<> jämför updategrammet de värden som anges för dessa kolumner med de värden som fanns i databasen innan uppdateringen applicerades. Om någon av postkolumnerna har ändrats sedan din transaktion läste posten, utför inte updategrammet uppdateringen.

    Till exempel uppdaterar följande uppdateringsgram skiftnamnet, men specificerar ytterligare kolumner (StartTime, EndTime) i <före-blocket> , vilket kräver en högre skyddsnivå mot samtidiga uppdateringar.

    <ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">  
    <updg:sync >  
    <updg:before>  
       <HumanResources.Shift ShiftID="1"   
                 Name="Day"   
                 StartTime="1900-01-01 07:00:00.000"   
                 EndTime="1900-01-01 15:00:00.000" />  
    </updg:before>  
    <updg:after>  
       <HumanResources.Shift Name="Morning" />  
    </updg:after>  
    </updg:sync>  
    </ROOT>  
    

    Detta exempel specificerar den högsta skyddsnivån genom att ange alla kolumnvärden för posten i <före-blocket> .

  • Ange tidsstämpelkolumnen (om tillgänglig) i före-blocket<>.

    Istället för att specificera alla postkolumner i före-blocket<> kan du bara ange tidsstämpelkolumnen (om tabellen har en) tillsammans med primärnyckelkolumnen/kolumnerna i <före-blocket>. Databasen uppdaterar tidsstämpelkolumnen till ett unikt värde efter varje uppdatering av posten. I detta fall jämför updategrammet tidsstämpelns värde med motsvarande värde i databasen. Tidsstämpelvärdet som lagras i databasen är ett binärt värde. Därför måste tidsstämpelkolumnen anges i schemat som dt:type="bin.hex",dt:type="bin.base64" eller sql:datatype="timestamp". (Du kan ange antingen xml-datatypen eller Microsoft SQL Server-datatypen.)

För att testa updategrammet

  1. Skapa denna tabell i tempdb-databasen :

    USE tempdb  
    CREATE TABLE Customer (  
                 CustomerID  varchar(5),  
                 ContactName varchar(20),  
                 LastUpdated timestamp)  
    
  2. Lägg till detta exempelalbum:

    INSERT INTO Customer (CustomerID, ContactName) VALUES   
                         ('C1', 'Andrew Fuller')  
    
  3. Kopiera följande XSD-schema och klistra in det i Notepad. Spara den som ConcurrencySampleSchema.xml:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
                xmlns:sql="urn:schemas-microsoft-com:mapping-schema">  
      <xsd:element name="Customer" sql:relation="Customer" >  
       <xsd:complexType>  
            <xsd:attribute name="CustomerID"    
                           sql:field="CustomerID"   
                           type="xsd:string" />   
    
            <xsd:attribute name="ContactName"    
                           sql:field="ContactName"   
                           type="xsd:string" />  
    
            <xsd:attribute name="LastUpdated"   
                           sql:field="LastUpdated"   
                           type="xsd:hexBinary"   
                 sql:datatype="timestamp" />  
    
        </xsd:complexType>  
      </xsd:element>  
    </xsd:schema>  
    
  4. Kopiera följande uppdateringsgramkod till Notepad och spara den som ConcurrencySampleTemplate.xml i samma katalog där du sparade schemat som skapades i föregående steg. (Observera att tidsstämpelvärdet nedan för LastUpdated kommer att skilja sig i din exempelkundtabell, så kopiera det faktiska värdet för LastUpdated från tabellen och klistra in det i updategramet.)

    <ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">  
    <updg:sync mapping-schema="SampleSchema.xml" >  
    <updg:before>  
       <Customer CustomerID="C1"   
                 LastUpdated = "0x00000000000007D1" />  
    </updg:before>  
    <updg:after>  
       <Customer ContactName="Robert King" />  
    </updg:after>  
    </updg:sync>  
    </ROOT>  
    
  5. Skapa och använd SQLXML 4.0 Test Script (Sqlxml4test.vbs) för att köra mallen.

    Mer information finns i Använda ADO för att köra SQLXML 4.0-frågor.

Det här är motsvarande XDR-schema:

<?xml version="1.0" ?>  
<Schema xmlns="urn:schemas-microsoft-com:xml-data"  
        xmlns:dt="urn:schemas-microsoft-com:datatypes"  
        xmlns:sql="urn:schemas-microsoft-com:xml-sql">  
<ElementType name="Customer" sql:relation="Customer" >  
    <AttributeType name="CustomerID" />  
    <AttributeType name="ContactName" />  
    <AttributeType name="LastUpdated"  dt:type="bin.hex"   
                                       sql:datatype="timestamp" />  
    <attribute type="CustomerID" />  
    <attribute type="ContactName" />  
    <attribute type="LastUpdated" />  
</ElementType>  
</Schema>  

Se även

Säkerhetsöverväganden för Updategram (SQLXML 4.0)