• незавершенные (uncommited) — версии, созданные транзакциями, которые еще находятся в работе. В MV2PL планировщик следит за тем, чтобы в каждый момент времени существовало не более одной незавершенной версии. В зависимости от того, позволяется ли транзакциям читать незавершенные версии данных, различаются два варианта алгоритма: с чтением незавершенных данных и без. Сначала рассмотрим схему работы MV2PL в предположении, что все версии элементов данных сохраняются в базе. Затем обсудим вариант этого алгоритма, в котором допускается одновременное существование не более двух версий одного и того же элемента данных. Все операции, которые обрабатывает планировщик, разделяются на два класса: обычные и финальные операции. Под финальной операцией понимается последняя операция транзакции перед ее завершением или же сама операция завершения. Обе интерпретации допустимы. При этом каждая отдельная операция транзакции обрабатывается следующим образом: 1. если операция не является финальной, то: а) операция Ф) выполняется незамедлительно; ей сопоставляется последняя из завершенных к данному моменту версий х (или последняя из незавершенных версий х во втором варианте алгоритма); Ь) операция w(x) выполняется только после завершения транзакции, записавшей последнюю версию х. 2. если операция является финальной для транзакции ti, то она откладывается до тех пор, пока не завершатся: а) все транзакции //, прочитавшие текущую версию данных, которую должна заменить версия, записанная ti (тем самым устраняется возможность неповторяющегося чтения); Ь) все транзакции tj, которые записали версии, прочитанные ti (это требуется только во втором варианте алгоритма). Как видно, этот алгоритм ничего не говорит о количестве версий одного и того же элемента, которые могут одновременно существовать в базе данных, что вызывает проблемы с хранением версий. Во-первых, они могут занимать слишком много места. Во-вторых, возникают трудности с 65 |
* • завершенные (commited) — версии, созданные транзакциями, которые уже успешно закончили свою работу; • текущая версия (current) — последняя из завершенных версий; • }^завершенные (uncommited) — версии, созданные транзакциями, которые еще находятся в работе. В MV2PL планировщик следит за тем, чтобы в каждый момент времени существовало не более одной незавершенной версии. В зависимости от того, позволяется ли транзакциям читать незавершенные версии данных, различаются два варианта алгоритма: с чтением незавершенных данных и без. Сначала рассмотрим схему работы MV2PL в предположении, что все версии элементов данных сохраняются в базе. Затем обсудим вариант этого алгоритма, в котором допускается одновременное существование не более двух версий одного и того же элемента данных. Все операции, которые обрабатывает планировщик, разделяются на два класса: обычные и финальные операции. Под финальной операцией понимается последняя операция транзакции перед ее завершением или же сама операция завершения. Обе интерпретации допустимы. При этом каждая отдельная операция транзакции обрабатывается следующим образом: 1. если операция не является финальной, то: а) операция ф ) выполняется незамедлительно; ей сопоставляется последняя из завершенных к данному моменту версий х (или последняя из незавершенных версий х во втором варианте алгоритма); Ь) операция w(x) выполняется только после завершения транзакции, записавшей последнюю версию х. 2. если операция является финальной для транзакции ti, то она откладывается до тех пор, пока не завершатся: а) все транзакции /у, прочитавшие текущую версию данных, которую должна заменить версия, записанная ti (тем самым устраняется возможность неповторяющегося чтения); Ь) все транзакции tj, которые записали версии, прочитанные ti (это требуется только во втором варианте алгоритма). 135 Как видно, этот алгоритм ничего не говорит о количестве версий одного и того же элемента, которые могут одновременно существовать в базе данных, что вызывает проблемы с хранением версий. Во-первых, они могут занимать слишком много места. Во-вторых, возникают трудности с размещением этих «старых» данных. Учитывая, что количество версий заранее не известно, сложно придумать эффективную структуру их хранения, которая бы не вызывала заметных накладных расходов. И, наконец, такая система слишком сложна в реализации. Именно из-за этих проблем предлагается использовать протокол 2V2PL. В этом протоколе возможно одновременное существование двух версий элемента данных: одной текущей версии данных и не более одной незавершенной. Такая организация версий выгодна прежде всего для транзакций, выполняющих операцию чтения. В 2V2PL используются три типа блокировок; каждая блокировка удерживается до конца транзакции. • Блокировка г/ (read lock) устанавливается на текущую версию элемента данных х непосредственно перед ее прочтением. • Блокировка wl (write lock) устанавливается перед тем, как создать новую (незавершенную) версию элемента х. • Блокировка с/ (commit lock) устанавливается перед выполнением последней операции транзакции (обычно перед операцией завершения) по отношению к каждому элементу данных, который она записала. Эта блокировка играет роль монопольной блокировки для обычного протокола 2PL. Она необходима для корректной смены версий. Блокировки rl совместимы между собой, а также с блокировками wl. Поэтому использование блокировок rl и wl обеспечивает выполнение правил (1а) и (lb) алгоритма MV2PL (с учетом того, что одновременно позволяется поддерживать не более одной незавершенной версии). Блокировка с/, в свою очередь, обеспечивает выполнение правил (2а) и (2Ь). |