アップデートグラムでのデータベース コンカレンシーに関する問題への対応 (SQLXML 4.0)
適用対象: SQL Server Azure SQL データベース
アップデートグラムは、他のデータベースの更新メカニズムと同様に、マルチサーバー環境での同時実行更新に対応しています。 アップデートグラムではオプティミスティック コンカレンシーが使用されます。この機能では、更新するデータがデータベースからの読み取り後に他のユーザー アプリケーションによって変更され邸内事を確認するために、選択フィールド データの比較がスナップショットとして使用されます。 アップデートグラムには、アップデートグラムの <before> ブロックにこれらのスナップショット値が含まれます。 データベースを更新する前に、アップデートグラムは、 <before> ブロックで指定されている値を、データベース内の現在の値と照合して、更新が有効であることを確認します。
アップデートグラムでは、オプティミスティック コンカレンシーによる保護を低 (なし)、中、高の 3 レベルで使用できます。 必要な保護レベルを適用するには、アップデートグラムで適切に指定する必要があります。
最低レベルの保護
このレベルでは、最後のデータベースの読み取り後に行われたその他の更新を無視して更新操作を実行します。 このような場合は、レコードを識別するために <before> ブロックに主キー列のみを指定し、更新された情報を <after> ブロックに指定します。
たとえば次のアップデートグラムでは、以前の電話番号に関係なく、新しい連絡先の電話番号として正しい番号を設定できます。 <前に>ブロックで主キー列 (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>
中レベルの保護
この保護レベルでは、トランザクションで読み取ったレコードが他のトランザクションによって変更されていないことを確認するため、アップデートグラムにおいて、更新するデータの現在の値とデータベース列の値が比較されます。
このレベルの保護を取得するには、 <fore> ブロックで更新する主キー列と列を指定します。
たとえば、このアップデートグラムでは、Person.Contact テーブルで、ContactID が 1 となっている連絡先の 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>
高レベルの保護
高レベルの保護では、アプリケーションで最後に読み取ったレコードが変化していない (他のトランザクションによって変更されていない) ことが確認されます。
同時実行更新に高レベルの保護を適用するには、次の 2 つの方法があります。
<before> ブロック内のテーブルに追加の列を指定します。
<before> ブロックに追加の列を指定した場合、アップデートグラムは、これらの列に指定されている値と、更新プログラムを適用する前のデータベース内の値を比較します。 トランザクションで読み取ったレコード列のいずれかが変更されている場合、アップデートグラムで更新は実行されません。
たとえば、次のアップデートグラムはシフト名を更新しますが、 <fore> ブロックに追加の列 (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>
この例では、 <fore> ブロック内のレコードのすべての列値を指定して、最高レベルの保護を指定します。
<before> ブロックでタイムスタンプ列 (使用可能な場合) を指定します。
<before> ブロック内のすべてのレコード列を指定する代わりに、タイムスタンプ列 (テーブルに列がある場合) と、<before> ブロックの主キー列のみを指定できます。 データベースでは、レコードが更新されるたびにタイムスタンプ列が一意な値に更新されます。 この場合、アップデートグラムではタイムスタンプの値とデータベースの対応する値を比較します。 データベースに格納されているタイムスタンプ値はバイナリ値です。 そのため、タイムスタンプ列はスキーマで dt:type="bin.hex"、 dt:type="bin.base64"、または sql:datatype="timestamp"として指定する必要があります。 ( xml データ型または Microsoft SQL Server データ型のいずれかを指定できます)。
アップデートグラムをテストするには
tempdb データベースに次のテーブルを作成します。
USE tempdb CREATE TABLE Customer ( CustomerID varchar(5), ContactName varchar(20), LastUpdated timestamp)
次のサンプル レコードを追加します。
INSERT INTO Customer (CustomerID, ContactName) VALUES ('C1', 'Andrew Fuller')
次の 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>
次のアップデートグラム コードをメモ帳にコピーして、前の手順で作成したスキーマと同じディレクトリに ConcurrencySampleTemplate.xml として保存します。 次の LastUpdated のタイムスタンプ値は例の Customer テーブルとは異なるため、LastUpdated の実際の値をテーブルからコピーし、アップデートグラムに貼り付けてください。
<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>
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>