Поддержка целостности в классических СУБД
Вопросам поддержки целостности в СУБД было посвящено огромное количество работ в течение последних 25 лет и эта область лежит вне рамок этой темы. Однако мы в общих чертах опишем основные концепции и наиболее распространенные алгоритмы, применяемые в классических СУБД для того, чтобы лучше продемонстрировать особенности методов, применяемых в системах реального времени.
Для обеспечения целостности базы данных в классических СУБД используется механизм транзакций. Все операции с базой данных осуществляются только от лица транзакций, чье выполнение контролируется специальным алгоритмом, гарантирующим сохранение целостности базы.
Алгоритмы управления транзакциями регулируют порядок совместной работы нескольких транзакций и поэтому обычно называются протоколами управления транзакциями. Такие протоколы основываются на предположении, что каждая из управляемых им транзакций обладает некоторым заданным набором свойств. Разные протоколы могут опираться на разные наборы свойств транзакций, но наиболее стандартным является так называемый набор ACID-свойств. Этот набор включает: атомарность, целостность, изолированность, постоянство.
Обязательным требованием, предъявляемым к любому протоколу управления транзакциями, является условие сохранения целостного состояния базы данных при совместном выполнении транзакций. Основным критерием определения сохранения целостности базы и, следовательно, корректности работы протокола является критерий сериализуемости получающихся расписаний [79].
Эффективность алгоритмов управления транзакциями сильно влияет на производительность всей СУБД, и, следовательно, производительность алгоритмов является ключевым фактором их сравнения.
Все протоколы управления транзакциями подразделяются на два класса: пессимистические и оптимистические.
Пессимистический подход
Отличительной особенностью протоколов этого класса является предотвращение возможности возникновения конфликтов. Основным методом для достижения этого является механизм блокировок. Этот метод предполагает, что для использования какого-либо ресурса транзакции необходимо сначала получить блокировку на этот ресурс. Обладание блокировкой на данный ресурс гарантирует невозможность конфликта с другими транзакциями, которые хотят использовать тот же ресурс. Транзакциям, которые потенциально могут вызвать появление конфликта с держателем блокировки на ресурс, блокировка просто не выдается. В таком случае эта транзакция встает в очередь на получение блокировки на этот ресурс и продолжает работу после получения этой блокировки.
Одним из наиболее широко распространенных пессимистических протоколов является двухфазный протокол (2PL) [79], согласно которому все операции блокирования ресурсов должны предшествовать всем операциям разблокирования. В классическом варианте этого протокола рассматриваются блокировки двух видов - на чтение и на изменение.
Серьезная проблема, которая может возникнуть при применении пессимистического протокола, − это так называемая проблема возникновения «тупиков» (deadlock). Тупик − это такая ситуация, при которой каждая транзакция из некоторого множества транзакций Т ожидает получения блокировки на элемент, который в данный момент времени заблокирован другой транзакцией из Т [79]. Попавшие в ситуацию тупика транзакции самостоятельно покинуть его не в силах и могут ждать вечно. Для борьбы с тупиками используются специальные методы их обнаружения и разрешения.
Оптимистический подход
Основная идея оптимистических протоколов − максимизировать объем выполняемой работы. Эти протоколы дают шанс работать всем транзакциям, но разрешают благополучно завершиться только тем из них, чье завершение не влечет нарушения целостности базы.
С точки зрения менеджера управления транзакций при использовании оптимистического протокола выполнение транзакции делится на три концептуальные фазы: чтение, проверка, запись. В течение фазы чтения транзакция работает параллельно с другими транзакциями без каких-либо ограничений, но все измененные данные записываются в личную рабочую память транзакции, а не в базу. Когда транзакция завершает свою работу, менеджер инициирует фазу проверки транзакции на наличие конфликтов с другими транзакциями. Если проверка окончилась удачно (т.е. конфликтов не обнаружено), то сделанные транзакцией изменения переносятся в базу и становятся видимыми другим транзакциям. В противном случае, сама транзакция или конфликтующие с ней транзакции завершаются анормально (т.е. сделанные изменения забываются).
По типу проверки оптимистические протоколы делятся на «вперед смотрящие» (forward validation) [79] и «назад смотрящие» (backward validation) [79]. Различие состоит в выборе множества транзакций для проверки на наличие конфликтов при завершении транзакции Т0. Протоколы из первой группы используют в качестве такого множества − все еще не завершенные транзакции (и соответственно анормально завершают все те из них, которые конфликтуют с Т0 либо саму Т0). А «назад смотрящие» проводят проверку по отношению ко всем нормально завершившимся транзакциям и в случае конфликта анормально завершают только Т0.
Сравнение подходов
Основным недостатком пессимистического подхода являются простои во время тупиков и растрата машинных ресурсов на их обнаружение и разрешение.
Оптимистический подход бесполезно тратит машинные ресурсы на работу транзакций, которые позже будут анормально завершены из-за возникновения конфликтов, а также на работу на стадии проверки при завершении каждой транзакции.
Экспериментальные результаты показывают, что в случае классических СУБД пессимистический подход обычно показывает лучшие результаты [79]. Поэтому в большинстве современных промышленных СУБД используются разновидности пессимистических протоколов.