Обработка параллелизма Sql transactrion

Предположим, я собираюсь запустить проект с помощью ASP.NET и SQL Server 2005. Я должен разработать требование параллелизма для этого приложения. Я планирую добавить столбец TimeStamp в каждой таблице. При обновлении таблиц я проверю, что столбец TimeStamp - то же, поскольку он был выбран.

Это приблизится быть, достаточны? Или есть ли какие-либо недостатки для этого подхода при каких-либо обстоятельствах?

Совет.

Спасибо

Lijo

5
задан Community 30 April 2015 в 08:59
поделиться

4 ответа

Прежде всего, способ, который вы описали в своем вопросе, на мой взгляд, является лучшим способом для приложения ASP.NET с MS SQL в качестве базы данных. В базе данных нет блокировки. Он идеально подходит для постоянно отключенных клиентов, таких как веб-клиенты.

Как можно понять из некоторых ответов, существует недопонимание в терминологии. Мы все имеем в виду использование Microsoft SQL Server 2008 или выше для хранения базы данных. Если вы откроете в документации по MS SQL Server 2008 тему "rowversion (Transact-SQL)", то найдете следующее:

"timestamp является синонимом для... rowversion типа данных и подчиняется поведению синонима типа данных". ... "Синтаксис timestamp является устаревшим. Эта функция будет удалена в будущей версии Microsoft SQL Server. Избегайте использования этой функции в новых разработках, и планируйте модифицировать приложения, которые в настоящее время используют эту функцию."

Итак, тип данных timestamp является синонимом типа данных rowversion для MS SQL. Он содержит 64-битный счетчик, который существует внутри каждой базы данных и может быть представлен как @@DBTS. После модификации одной строки в одной таблице базы данных, счетчик будет увеличен.

Читая ваш вопрос, я прочитал "TimeStamp" как имя столбца типа rowversion данных. Мне лично больше нравится имя RowUpdateTimeStamp. В AzManDB (см. Microsoft Authorization Manager с Store as DB) я встречал такое название. Иногда использовались также ChildUpdateTimeStamp для отслеживания иерархических RowUpdateTimeStamp структур (в отношении триггеров).

Я реализовал этот подход в своем последнем проекте и был очень доволен. В общем, вы делаете следующее:

  1. Добавляете RowUpdateTimeStamp столбец в каждую таблицу вашей базы данных с типом rowversion (в Microsoft SQL Management Studio он будет виден как timestamp, что одно и то же).
  2. Все SQL SELECT-запросы для отправки результатов клиенту следует строить таким образом, чтобы вместе с основными данными отправлять дополнительное значение RowVersion. Если у вас есть SELECT с JOINTами, вы должны отправить RowVersion максимального RowUpdateTimeStamp значения из обеих таблиц, как
SELECT s.Id AS Id
    ,s.Name AS SoftwareName
    ,m.Name AS ManufacturerName
    ,CASE WHEN s.RowUpdateTimeStamp > m.RowUpdateTimeStamp
          THEN s.RowUpdateTimeStamp 
          ELSE m.RowUpdateTimeStamp 
     END AS RowUpdateTimeStamp 
FROM dbo.Software AS s
    INNER JOIN dbo.Manufacturer AS m ON s.Manufacturer_Id=m.Id

Или сделать приведение данных, как показано ниже

SELECT s.Id AS Id
    ,s.Name AS SoftwareName
    ,m.Name AS ManufacturerName
    ,CASE WHEN s.RowUpdateTimeStamp > m.RowUpdateTimeStamp
          THEN CAST(s.RowUpdateTimeStamp AS bigint)
          ELSE CAST(m.RowUpdateTimeStamp AS bigint)
     END AS RowUpdateTimeStamp 
FROM dbo.Software AS s
    INNER JOIN dbo.Manufacturer AS m ON s.Manufacturer_Id=m.Id

для хранения RowUpdateTimeStamp как bigint, что соответствует ulong типу данных C#. Если вы делаете OUTER JOINTs или JOINTs из многих таблиц, то конструкция MAX(RowUpdateTimeStamp) из всех таблиц будет выглядеть немного сложнее. Поскольку MS SQL не поддерживает функции типа MAX(a,b,c,d,e), соответствующая конструкция может выглядеть следующим образом:

(SELECT MAX(rv)
 FROM (SELECT table1.RowUpdateTimeStamp AS rv
      UNION ALL SELECT table2.RowUpdateTimeStamp
      UNION ALL SELECT table3.RowUpdateTimeStamp
      UNION ALL SELECT table4.RowUpdateTimeStamp
      UNION ALL SELECT table5.RowUpdateTimeStamp) AS maxrv) AS RowUpdateTimeStamp
  1. Все отключенные клиенты (веб-клиенты) получают и хранят не только некоторые строки данных, но и RowVersion (тип ulong) строки данных.
  2. При одной попытке модифицировать данные от отключенного клиента, клиент должен отправить на сервер RowVersion, соответствующий исходным данным. Хранимая процедура spSoftwareUpdate может выглядеть так
CREATE PROCEDURE dbo.spSoftwareUpdate
    @Id int,
    @SoftwareName varchar(100),
    @originalRowUpdateTimeStamp bigint, -- used for optimistic concurrency mechanism
    @NewRowUpdateTimeStamp bigint OUTPUT
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    -- ExecuteNonQuery() returns -1, but it is not an error
    -- one should test @NewRowUpdateTimeStamp for DBNull
    SET NOCOUNT ON;

    UPDATE dbo.Software
    SET Name = @SoftwareName
    WHERE Id = @Id AND RowUpdateTimeStamp <= @originalRowUpdateTimeStamp

    SET @NewRowUpdateTimeStamp = (SELECT RowUpdateTimeStamp
                                  FROM dbo.Software
                                  WHERE (@@ROWCOUNT > 0) AND (Id = @Id));
END

Код хранимой процедуры dbo.spSoftwareDelete выглядит так же. Если не включить NOCOUNT, то во многих сценариях можно получить DBConcurrencyException, сгенерированный автоматически. Visual Studio предоставляет вам возможности для использования оптимистичного параллелизма, например, флажок "Use optimistic concurrency" в Advanced Options TableAdapter или DataAdapter.

Если вы посмотрите на dbo.spSoftwareUpdate хранимую процедуру, то увидите, что я использую RowUpdateTimeStamp <= @originalRowUpdateTimeStamp в WHERE вместо RowUpdateTimeStamp = @originalRowUpdateTimeStamp. Я делаю это потому, что, значение @originalRowUpdateTimeStamp, которое имеет клиент, обычно строится как MAX(RowUpdateTimeStamp) из нескольких таблиц. Поэтому может оказаться, что RowUpdateTimeStamp < @originalRowUpdateTimeStamp. Либо вы должны использовать строгое равенство = и воспроизвести здесь такой же сложный оператор JOIN, какой вы использовали в операторе SELECT, либо использовать конструкцию <=, как я, и остаться в точности таким же безопасным, как и раньше.

Кстати, можно построить очень хорошее значение для ETag на основе RowUpdateTimeStamp, которое можно отправить в HTTP заголовке клиенту вместе с данными. С помощью ETag можно реализовать интеллектуальное кэширование данных на стороне клиента.

Я не могу написать здесь весь код, но вы можете найти много примеров в Интернете. Хочу лишь еще раз повторить, что, на мой взгляд, использование оптимистичного параллелизма на основе rowversion является лучшим способом для большинства сценариев ASP.NET.

5
ответ дан 14 December 2019 в 04:33
поделиться

Предложение версии строки верное, я бы сказал, но его разочаровывает то, что временная метка скоро станет устаревшей. Некоторые из моих СТАРЫХ приложений используют это по разным причинам, а не для проверки параллелизма.

0
ответ дан 14 December 2019 в 04:33
поделиться

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

1
ответ дан 14 December 2019 в 04:33
поделиться

В SQL Server в зависимости от типа ситуации рекомендуется создать столбец типа 'rowversion' и использовать его, чтобы проверить, любое из полей в этой строке изменилось.

SQL Server гарантирует, что если какое-либо значение в строке изменится (или будет вставлена ​​новая строка), его столбец rowversion будет автоматически обновлен до другого значения. Позволить базе данных сделать это за вас гораздо надежнее, чем пытаться сделать это самостоятельно.

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

Кроме того, с этой страницы:

Синтаксис метки времени устарел. Эта функция будет удалена в будущая версия Microsoft SQL Server. Избегайте использования этой функции в новых разработках и запланируйте изменение приложений, которые в настоящее время используют эту функцию.

2
ответ дан 14 December 2019 в 04:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: