在 Updategram 中处理数据库并发问题 (SQLXML 4.0)

适用于: SQL Server Azure SQL 数据库

与其他数据库更新机制一样,updategram 必须处理多用户环境下对数据的并发更新。 Updategram 使用乐观并发控制,该模式将选择字段数据与快照进行比较,以确保要更新的数据自从在数据库中读取后,其他用户应用程序未更改过该数据。 Updategram 在 updategram 块之前>包含这些快照值<。 在更新数据库之前,updategram 会根据数据库中当前的值检查在之前>块中指定的<值,以确保更新有效。

乐观并发控制在 updategram 中提供三种保护级别:低(无)、中间和高。 通过相应指定 updategram,可以确定需要的保护级别。

最低保护级别

此级别为盲目更新,它不参照自上次读取数据库后已进行的其他更新来处理更新。 在这种情况下,只需在块前><指定主键列来标识记录,并在后>块中<指定更新的信息。

例如,无论以前的电话号码是什么,以下 updategram 中的新联系人电话号码都是正确的。 请注意之前>块如何<仅指定主键列 (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>  

中间保护级别

在此保护级别中,updategram 将要更新的数据的当前值与数据库列中的值进行比较,以确保自您的事务读取记录后,这(个)些值未被任何其他事务更改过。

可以通过指定在块中<>更新的主键列和列(s)来获取此级别的保护。

例如,此 updategram 为 ContactID 是 1 的联系人更新 Person.Contact 表的 Phone 列中的值。 <before> 块指定 Phone 属性,以确保在应用更新的值之前,此属性值与数据库中相应列中的值匹配。

<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>  

高保护级别

高保护级别确保自您的应用程序上次读取该记录后该记录没有变化(即自您的应用程序读取记录后,该记录未被任何其他事务更改过)。

可以通过两种方法实现针对并发更新的此类高保护级别:

  • 在块前<>的表中指定其他列。

    如果在前>块中<指定其他列,updategram 会将为这些列指定的值与应用更新之前数据库中的值进行比较。 如果自您的事务读取记录后有记录列被更改过,updategram 将不执行更新。

    例如,以下 updategram 更新班次名称,但在块前>指定其他列(StartTime,EndTime),<从而请求对并发更新的更高级别的保护。

    <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>  
    

    此示例通过指定前>块中<记录的所有列值来指定最高级别的保护。

  • 在块前<>指定时间戳列(如果可用)。

    可以指定时间戳列(如果表有一个),而不是指定前>块中的所有记录列<以及前>一个块中的<主键列。 在每次更新记录后,数据库将时间戳列更新为唯一值。 在这种情况下,updategram 将时间戳的值与数据库中的相应值进行比较。 在数据库中存储的时间戳值为二进制值。 因此,时间戳列必须在架构中指定为 dt:type=“bin.hex”dt:type=“bin.base64”sql:datatype=“timestamp”。 (可以指定 xml 数据类型或Microsoft SQL Server 数据类型。

测试 updategram

  1. tempdb 数据库中创建此表:

    USE tempdb  
    CREATE TABLE Customer (  
                 CustomerID  varchar(5),  
                 ContactName varchar(20),  
                 LastUpdated timestamp)  
    
  2. 添加此示例记录:

    INSERT INTO Customer (CustomerID, ContactName) VALUES   
                         ('C1', 'Andrew Fuller')  
    
  3. 复制以下 XSD 架构并将其粘贴到记事本中。 将其另存为 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. 将以下 updategram 代码复制到记事本中,然后在保存上一步中创建的架构的相同目录中将其保存为 ConcurrencySampleTemplate.xml。 (请注意下面 LastUpdated 的时间戳值将不同于示例 Customer 表中的值,因此从表中复制 LastUpdated 的实际值并将其粘贴到 updategram。)

    <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. 创建并使用 SQLXML 4.0 测试脚本 (Sqlxml4test.vbs) 执行该模板。

    有关详细信息,请参阅使用 ADO 执行 SQLXML 4.0 查询

这是等效的 XDR 架构:

<?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>  

另请参阅

updategram 安全注意事项 (SQLXML 4.0)