Поделиться через


Решение проблем с параллелизмом обработки в базе данных в диаграммах обновления (SQLXML 4.0)

Как и другие механизмы обновления базы данных, диаграммы обновления должны иметь дело с одновременными обновлениями данных в многопользовательской среде. В диаграммах обновления используется оптимистическое управление параллелизмом, которое использует сравнение данных в выбранных полях как моментальных снимков, чтобы данные, которые нужно обновить, не были изменены другим пользовательским приложением после чтения из базы данных. Диаграммы обновления включают эти значения моментальных снимков в блок <before> диаграмм обновления. Перед обновлением базы данных диаграмма обновления сопоставляет значения, указанные в блоке <before>, с текущими значениями в базе данных, чтобы убедиться в допустимости обновления.

Управление оптимистичным параллелизмом обеспечивает три уровня защиты в диаграмме обновления: низкий (нет), промежуточный и высокий. Можно выбрать нужный уровень защиты, указав соответствующую диаграмму обновления.

Самый низкий уровень защиты

Этот уровень обеспечивает «слепое» обновление, при котором обновление обрабатывается без учета других обновлений, сделанных со времени последнего чтения базы данных. В этих случаях указываются только столбцы первичного ключа в блоке <before>, чтобы идентифицировать запись, и указываются обновленные сведения в блоке <after>.

Например, новый номер телефона для связи в следующей диаграмме обновления верен, независимо от предыдущего значения телефонного номера. Обратите внимание, как блок <before> указывает только столбец первичного ключа (BusinessEntityID).

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

Промежуточный уровень защиты

На этом уровне защиты диаграмма обновления сравнивает текущие значения обновляемых данных со значениями в столбцах базы данных, чтобы проверить, что значения не были изменены другой транзакцией после чтения записи данной транзакцией.

Этот уровень защиты можно обеспечить, указав столбцы первичного ключа и обновляемые столбцы в блоке <before>.

Например, данная диаграмма обновления изменяет значение в столбце Phone таблицы Person.Person для контактного лица со значением BusinessEntityID, равным 1. Блок <before> указывает атрибут Phone, чтобы обеспечить соответствие значения атрибута значению в соответствующем столбце в базе данных перед применением обновленного значения.

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

Высокий уровень защиты

Высокий уровень защиты гарантирует, что запись остается неизменной со времени последнего чтения записи приложением (то есть после чтения записи приложением она не была изменена никакой другой транзакцией).

Существует два способа получить высокий уровень защиты от одновременных обновлений.

  • Указать дополнительные столбцы в таблице в блоке <before>.

    Если указаны дополнительные столбцы в блоке <before> , диаграмма обновления сравнивает значения, указанные для этих столбцов, со значениями, которые были в базе данных перед применением обновления. Если какие-нибудь столбцы записи изменились после чтения записи транзакцией, диаграмма обновления не выполняет обновление.

    Например, следующая диаграмма обновления обновляет название рабочей смены, но указывает дополнительные столбцы (StartTime,EndTime) в блоке <before>, тем самым запрашивая более высокий уровень защиты от одновременных обновлений.

    <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> можно просто указать столбец отметки времени (если он есть в таблице) наряду со столбцами первичного ключа в блоке <before>. База данных обновляет столбец отметки времени уникальным значением после каждого обновления записи. В этом случае диаграмма обновления сравнивает значения отметок времени с соответствующим значением в базе данных. Значение отметки времени, сохраненное в базе данных, является двоичным значением. Поэтому столбец отметки времени в схеме должен быть указан как dt:type="bin.hex", dt:type="bin.base64" или sql:datatype="timestamp". Можно указать тип данных xml или Microsoft SQL Server.

Тестирование диаграммы обновления

  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. Скопируйте следующий код диаграммы обновления в приложении «Блокнот» и сохраните его в файле с именем 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>
    
  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>