アップデートグラムでのデータベースの同時実行に関する問題への対応 (SQLXML 4.0)
アップデートグラムは、他のデータベースの更新メカニズムと同様に、マルチサーバー環境での同時実行更新に対応しています。 アップデートグラムではオプティミスティック同時実行制御が使用されます。この機能では、更新するデータがデータベースからの読み取り後に他のユーザー アプリケーションによって変更され邸内事を確認するために、選択フィールド データの比較がスナップショットとして使用されます。 これらのスナップショット値は、アップデートグラムの <before> ブロックに指定されます。 アップデートグラムではデータベースの更新前に、更新が有効であることを確認するため、<before> ブロックで指定された値とデータベースにある現在の値が照合されます。
アップデートグラムでは、オプティミスティック同時実行制御による保護を低 (なし)、中、高の 3 レベルで使用できます。 必要な保護レベルを適用するには、アップデートグラムで適切に指定する必要があります。
最低レベルの保護
このレベルでは、最後のデータベースの読み取り後に行われたその他の更新を無視して更新操作を実行します。 この場合、<before> ブロックに主キー列のみを指定してレコードを識別し、<after> ブロックに更新後の情報を指定します。
たとえば次のアップデートグラムでは、以前の電話番号に関係なく、新しい連絡先の電話番号として正しい番号を設定できます。 <before> ブロックに、主キー列 (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>
中レベルの保護
この保護レベルでは、トランザクションで読み取ったレコードが他のトランザクションによって変更されていないことを確認するため、アップデートグラムにおいて、更新するデータの現在の値とデータベース列の値が比較されます。
このレベルの保護を適用するには、<before> ブロックに主キー列と更新する列を指定します。
たとえば、このアップデートグラムでは、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> ブロックで追加の列を指定した場合、アップデートグラムでは、更新の適用前に、その列に指定されている値とデータベースにあった値が比較されます。 トランザクションで読み取ったレコード列のいずれかが変更されている場合、アップデートグラムで更新は実行されません。
たとえば勤務時間名を更新する次のアップデートグラムでは、<before> ブロックに追加の列 (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>
この例では、<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>