Проблема параллелизма - PullRequest
1 голос
/ 21 января 2011

Мы получили старую систему в .NET 4.0 с использованием БД Oracle. В какой-то момент составляются некоторые исчисления, и система «блокирует», которые регистрируются в таблице, с помощью следующей команды: «SELECT [реестр, который будет обновляться исчислением] FOR UPDATE NOWAIT». Поэтому, если кто-то попытается вычислить или обновить реестр с этим идентификатором, он не будет работать. После расчета система снова подключается к БД, а затем «освобождает» реестр, просто выполнив команду отката.

Теоретически, это правильно для системы (хотя мне это не нравится).

В любом случае, вот в чем дело: если что-то вычисляется (а эти калькулятивные работы занимают около 5 минут), и в середине калькуляционного счета я закрываю браузер, реестр по-прежнему будет заблокирован, только разблокирован когда IIS перезапускается (на самом деле я не знаю, если он будет выпущен первым, я принудительно перезапускаю IIS, потому что это заняло слишком много времени).

Может ли кто-нибудь подсказать мне, как с этим бороться? Или, если вы, ребята, лучше подойдете к этому типу параллелизма, я буду вам благодарен.

Спасибо! Габриэль.

Добавление некоторого кода. Перед началом исчисления этот метод называется:

Public Shared Sub LockAndUnlock(ByVal pTable As String, ByVal pWhere As String, ByVal pConnectionString As String, ByVal pLock As Boolean)

    Dim vConnection As OleDbConnection = New OleDbConnection(pConnectionString)
    Dim vCommand As OleDbCommand = New OleDbCommand

    Try
        vCommand.Connection = vConnection
        If (pLock) Then
            vCommand.CommandText = "SELECT * " &
                                   "  FROM   " & pTable &
                                   " WHERE   " & pWhere &
                                   " FOR UPDATE NOWAIT"

            vConnection.Open()
            vCommand.ExecuteNonQuery()
        Else
            vCommand.CommandText = "ROLLBACK"

            If (vConnection.State = ConnectionState.Closed) Then
                vConnection.Open()
            End If

            vCommand.ExecuteNonQuery()
            vConnection.Close()
        End If

    Catch ex As Exception
        Throw ex
    End Try
End Sub

Если параметр pLock имеет значение True, метод блокируется. В противном случае он разблокируется.

Ответы [ 4 ]

0 голосов
/ 24 января 2011

Большинство современных БД разработали очень хороший способ обеспечения согласованности данных, который является частью того, за что вы платите, так что пользуйтесь. По этой причине я не уверен, зачем здесь необходим выбор для обновления.

Уровень изоляции по умолчанию для Oracle - фиксация на чтение, при которой грязное чтение невозможно. Вы будете гарантированно получать последовательные результаты без чтения, блокирующего записи и записи, блокирующего чтения (используя SCN и откат, а также более интересные вещи, вы можете получить больше информации об этом с помощью концепций Oracle pdf, найденных здесь ).

Во всяком случае, в большинстве случаев, если вы хотите сделать обновление, сделайте это (не беспокоясь о том, чтобы все вокруг наложить блокировки). Другие пользователи по-прежнему получат согласованное для чтения представление данных в том виде, в котором они существуют во время чтения (даже если продолжается незафиксированное обновление).

Одна вещь, которую нужно добавить: «для обновления» снимет внутренние блокировки при фиксации или откате. Определяемая пользователем / поддерживаемая логика "pLock" немного пугающая (может содержать ошибки).

0 голосов
/ 21 января 2011

Мне нужно посмотреть какой-нибудь код, но мне любопытно, что вы имеете в виду, когда говорите «система снова подключается к БД», а затем снимает блокировку.

Тот факт, что блокировка снята при перезапуске IIS, указывает на то, что соединение все еще активно. Вы используете поставщика оракула или поставщика MS Oracle?

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

0 голосов
/ 21 января 2011

Я бы использовал профиль Oracle с максимальным IDLE_TIME около 10 минут.

0 голосов
/ 21 января 2011

Это не зависит от браузера, потому что транзакция выполняет на сервере Oracle , к которому подключен клиент (ASP?). NET . Уничтожение IIS разблокирует его, поскольку оно разрывает соединение между сервером БД и клиентом БД, на котором выполняется транзакция.

Теперь в этом и заключается суть проблемы :-) Один может использовать опрос из веб-клиента и заставить сервер определять, когда было получено недостаточно опросов. Однако в этом заключается большая проблема, заключающаяся в том, что (как правило) нет способа убедиться, что работник веб-службы, запустивший транзакцию, возобновлен (я думаю, что это можно сделать с некоторыми настройками продолжения, но они не часто [пока].)

Итак, здесь я предлагаю два метода:

1) Иметь дополнительного брокера, такого как системный сервис, которому можно давать команды с веб-сервера, в дополнение к некоторому опросу веб-клиента. Это будет запускать любые транзакции, назначать идентификаторы, автоматически прерывать работу, если входящие запросы перестают поступать, и т. Д. Это позволит всегда «подключаться» обратно к правильной транзакции для отмены или получения результатов или чего-либо еще. Тьфу.

2) Поскольку работник веб-службы "занят" и не может использоваться другими соединениями, пока транзакция не завершится в любом случае ... просто сделайте, чтобы веб-сервер поддерживал соединение с веб-клиентом активен, пока транзакция БД не завершится (например, запрос будет открыт в новом окне браузера, в котором будет указано: «Закрытие этого запроса прервет выполнение »). Конечно, это зависит от 1) способности конкретного сервера выполнять потоковую передачу содержимого 2) способности (неявной / явной) проверки того, что транзакция закрыта, когда запрос завершается нормально или когда поток отключен - я никогда не пытался в (ASP?). NET. Все еще гадость.

Редактировать: второй пример может быть выполнен без потоковой передачи контента - например, скрыт за вызовом AJAX или IFRAME на «сообщить пользователю, что транзакция происходит на странице». Ключевым моментом является то, что он должен быть настроен так, чтобы , когда веб-транзакция заканчивалась, он почти сразу же завершал транзакцию базы данных . Это будет зависеть от веб-сервера.

Для ASP.NET см. Поток ответов как способ с поточной передачей для потоковой передачи и / или обнаружения разорванного соединения HTTP-ответа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...