Управление параллельным доступом
Управление параллельным доступом - это метод, используемый для поддержания свойств согласованности и изолированности транзакций. Это метод применяется, когда две параллельно выполняемые транзакции пытаются одновременно выполнить операции чтения или записи над одними и теми же объектами. Согласованность по чтению определяется как требование того, что все операции чтения в транзакции выполняются над одним и тем же состоянием базы данных, а согласованность по записи (обновлению) гарантирует, что порядок операций над объектами базы данных не влияет на окончательный результат.
В базах данных могут реализовываться различные виды поддержки согласованности и управления параллельным доступом. Для обеспечения согласованности по чтению обычно используются два базовых механизма:
- Гарантированное представление (Guaranteed view) - для всех транзакций гарантируется согласованное представление репозитория объектов, основанное на состоянии базы данных в момент времени начала транзакций. Это характерная особенность базы данных, и ей обладают не все базы данных.
- Блокировки по чтению (Read locks) - программист должен запрашивать блокировки объектов, когда они читаются, чтобы другие пользователи не могли изменять их.
Если для приложения требуется согласованное представление для некоторых только читающих транзакций, например, генерирующих отчеты или собирающих данные для их представления на дисплее клиента, то обычно лучше подходит база данных, поддерживающая гарантированное представление, потому что:
- Приложение проще разрабатывается и поддерживается, поскольку от программиста не требуется заботиться о блокировках по чтению и возможных синхронизационных тупиках, которые могут возникнуть при взаимодействии с транзакциями, использующими блокировки по записи.
- Приложения выполняются более эффективно, потому что базы данных, в которых реализовано гарантированное представление, обычно обеспечивают очень эффективный доступ к данным по чтению. Это становится возможным, поскольку в них не требуется обращения к менеджеру блокировок, и доступ к данным производится по указателю на конкретное представление.
- Может быть достигнут более высокий уровень параллелизма (и более высокая общая пропускная способность), поскольку отсутствует конфликт между одновременно выполняющимися читающими и пишущими транзакциями.
Если приложение пишется таким образом, что все операции обновления или записи в одновременно выполняющихся транзакциях производятся над разъединенными множествами объектов, то конфликты не существуют, и транзакции могут быть успешно зафиксированы без какого-либо дополнительного управления параллельным доступов, снижающего производительность. Однако так бывает редко, и в большинстве приложений должна использоваться какая-либо форма управления параллельным доступом, обеспечивающая успешную фиксацию транзакций.
Для управления согласованность по обновлению в базе данных имеются три основных метода:
- Выигрывает последний (Last in Wins) - "Выигрывает" последняя из одновременно выполняемых транзакций, пишущая данные, в том смысле, что именно ее изменения сохраняются в базе данных, но это может привести к непредвиденным результатам. Например, пусть пользователь A читает значение объекта O и видит значение 3. Затем одновременно работающий пользователь B изменяет значение объекта O на 7 и фиксирует транзакцию. Тем временем, пользователь A добавляет 1 к значению O (которое он ранее прочитал) и сохраняет результирующее значение 4 в объекте O. В результате обновления пользователя B оказываются потерянными. В большинстве приложений этот метод использовать нельзя.
- Оптимистический метод - Доступ к объектам и их обновление производится в частной области, образуемой в ходе выполнения транзакции. До фиксации транзакции требуется выполнить проверку того, что операции этой транзакции согласуются с операциями других транзакций, зафиксированных после ее начала. Если проверка согласованности не удается, фиксация не производится, и все изменения, совершенные при выполнении транзакции, должны быть аннулированы. Обновляющие транзакции являются "оптимистическими" в том смысле, что они не ожидают частого возникновения конфликтов, и в случае неудачи они готовы снова произвести обновления. Этот метод также называют "Выигрывает первый" ("First in Wins"), поскольку вторая попытка зафиксировать объект может не удаться по причине наличия конфликта с уже зафиксированной транзакцией.
- Пессимистический метод - Для предотвращения выполнения операций чтения или обновления другими транзакциями в период выполнения данной транзакции используются блокировки или упорядочивание по временным меткам.
Часто применяется двухфазное блокирование, поскольку это подход является простым и позволяет избежать возникновения проблемы каскадных откатов транзакций.
Во многих объектно-ориентированных приложениях оказывается сложно предсказать, какие объекты будут читаться или изменяться, поскольку поведение метода может зависеть от найденного значения. Например, метод может обнаружить, что на складе осталось мало единиц некоторого товара и вызвать метод reorder для его дополнительного заказа. Метод reorder может быть очень простым, но для его выполнения может потребоваться доступ к ряду объектов поставщиков и определение того, кто из них является наилучшим в данной ситуации. Эта непредсказуемость поведения обычно затрудняет разработку приложений с использованием только пессимистических механизмов управления параллельным доступом, поскольку усложняется управление блокировками и возрастает вероятность синхронизационных тупиков. Поэтому в объектно-ориентированных системах более часто используются оптимистические методы управления параллелизмом.
Одним из ключевых аспектов оптимистического подхода является обнаружение конфликтов. Нарушения согласованности обычно подразделяются на нарушения по чтению и нарушения по записи. Согласованность по чтению гарантирует, что данные, читаемые при выполнении данной, не изменяются другой транзакцией, пока данная транзакция является активной (в промежутке времени от начала транзакции до ее фиксации). Это называется конфликтами Read/Write, поскольку чтения текущей транзакции конфликтуют с записями других транзакций. Согласованность по записи гарантирует, что объект, измененный при выполнении данной транзакции, не изменяется другой транзакцией, пока данная транзакция является активной. Эти конфликты называются конфликтами Write/Write, поскольку записи текущей транзакции конфликтуют с записями других транзакций.
В некоторых базах данных может обеспечиваться несколько уровней требований согласованности:
- При полной согласованности требуется, чтобы для всех объектов, прочитанных или измененных транзакцией, не допускалось их обновление параллельно выполняемой транзакцией, которая фиксируется, когда данная транзакция является активной.
- Уровень параллельности может быть повышен (за счет уменьшения числа неудачных фиксаций) путем выполнения проверок только согласованности по записи, но это следует применять только в тех случаях, когда приложение допускает, что производимое им обновление объекта может основываться на данных, которые могут измениться после их прочтения.Такая возможность используется в приложениях потоков работ, подобных тому, которое описано в [].
Также важно учитывать гранулярность механизма управления параллельным доступом. Некоторые системы стремятся оптимизировать проверки путем выполнения их на элементах, гранулированных должным образом, например, на страницах, в которых располагаются объекты. Это может повысить производительность в случаях, когда объекты кластеризуются таким образом, что объекты, которые могли бы привести к конфликту, находятся в разных страницах. Хотя этот подход и возможен, часто он оказывается очень неуклюжим, и в общем случае "мелкозернистая" проверка согласованности на индивидуальных объектах позволяет поддерживать более высокий уровень параллельности выполнения операций обновления.