RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

Глава 6. Версии объекта схемы NDB

NDB поддерживает изменения схемы онлайн. Объект схемы, такой как Table или Index, имеет 4-байтовый идентификатор версии объекта схемы, который может наблюдаться в выводе утилиты ndb_desc (см. ndb_desc Describe NDB Tables), как показано здесь (подчеркнутый текст):

shell> ndb_desc -c 127.0.0.1 -d test t1
-- t1 --
Version: 33554434
Fragment type: HashMapPartition
K Value: 6
Min load factor: 78
Max load factor: 80
Temporary table: no
Number of attributes: 3
Number of primary keys: 1
Length of frm data: 269
Row Checksum: 1
Row GCI: 1
SingleUserMode: 0
ForceVarPart: 1
FragmentCount: 4
ExtraRowGciBits: 0
ExtraRowAuthorBits: 0
TableStatus: Retrieved
HashMap: DEFAULT-HASHMAP-240-4
-- Attributes --
c1 Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
c2 Int NULL AT=FIXED ST=MEMORY
c4 Varchar(50;latin1_swedish_ci) NOT NULL AT=SHORT_VAR ST=MEMORY
-- Indexes --
PRIMARY KEY(c1) - UniqueHashIndex
PRIMARY(c1) - OrderedIndex
NDBT_ProgramExit: 0 - OK

Идентификатор версии объекта схемы (или просто версия схемы) составлен из основной и вспомогательной версии, основная версия занимает наименьший значимый байт версии схемы, вспомогательная версия занимает остающиеся 3 старших значащих байта. Вы видите эти два компонента, рассматривая версию схемы в шестнадцатеричной нотации. В выводе в качестве примера версию схемы показывают как 33554434, который в шестнадцатеричном виде является 0x02000002, это эквивалентно основной версии 2 и вспомогательной версии 2. Добавление индекса в таблицу t1 заставляет версию схемы, как сообщается ndb_desc, продвигаться к 50331650 или шестнадцатерично 0x03000002, что эквивалентно основной версии 2 (3 младших значащих байта 00 00 02) и вспомогательной версии 3 (старший значащий байт 03). Незначительные версии схемы начинаются с 0 для недавно составленной таблицы.

Кроме того, у каждого класса объекта базы данных API NDB есть свой собственный метод getObjectVersion(), который возвращает версию объекта схемы объекта аналогично Object::getObjectVersion(). Это включает экземпляры не только Object, но и Table, Index, Column, LogfileGroup, Tablespace, Datafile и Undofile, а также Event. Однако, NdbBlob::getVersion() имеет цель и функцию, которая абсолютно не связана с перечисленными методами.

Изменения схемы, которые считают обратно совместимыми, такие как добавление столбца DEFAULT или NULL, в конце таблицы заставляет вспомогательную версию объекта таблицы быть увеличенной. Изменения схемы, которые не считают обратно совместимыми, такие как удаление колонки, заставляют основную версию быть увеличенной.

В то время как внедрение операции, вызывающей существенное изменение версии схемы, может на самом деле включить 2 копии затронутой таблицы (удаление и воссоздание таблицы), конечный результат может наблюдаться как увеличение основной версии.

У запросов и операций DML, которые прибывают от клиентов NDB, также есть связанная версия схемы, которая проверяется в начале обработки в узлах данных. Если версия схемы запроса отличается от последней версии схемы затронутого объекта базы данных только в ее компоненте вспомогательной версии, операция считается совместимой и позволена. Если версия схемы будет отличаться по главной версии схемы, это будет отклонено.

Этот механизм позволяет схеме быть измененной в узлах данных различными способами, не требуя синхронизированного изменения схемы в клиентах. Клиенты не должны идти дальше к новой версии схемы, пока они не готовы это сделать. Запросы и операции DML могут продолжаться непрерывно.

API NDB и версии объекта схемы. Применение API NDB обычно использует объект NdbDictionary, связанный с объектом Ndb, чтобы получить объекты схемы. Объекты схемы восстанавливаются по требованию от узлов данных, передача сигналов используется, чтобы получить определение индекса или таблицы, тогда построен объект локальной памяти, который может использовать приложение. NDB внутренне кэширует объекты схемы так, чтобы каждый последовательный запрос о той же самой таблице или индексе по имени не требовал передачи сигналов.

Глобальный кэш схемы. Чтобы избежать потребности сигнализировать к узлам данных для каждого поиска объекта схемы, кэш схемы используется для каждого Ndb_cluster_connection. Это упоминается как глобальный кэш схемы. Это глобально с точки зрения охвата многократных объектов Ndb. Порожденные объекты таблицы и индекса автоматически помещаются в этот кэш, чтобы экономить на будущей передаче сигналов и затратах экземпляра. Кэш поддерживает подсчет ссылок для каждого объекта, это количество используется, чтобы определить, когда данный объект схемы может быть удален. Объектам схемы можно изменить их подсчеты ссылок явно, вызовом метода API или местными операциями по кэшу схемы.

Местный кэш схемы. В дополнение к глобальному кэшу схемы для каждого подключения, каждый объект NdbDictionary имеет местный кэш схемы. Этот кэш содержит указатели на объекты в глобальном кэше схемы. Каждый местный кэш схемы, содержащий ссылку на объект схемы в глобальном кэше схемы, увеличивает глобальный подсчет ссылок кэша схемы на 1. Наличие кэша схемы, который является местным каждому объекту Ndb позволяет искать объекты схемы, не налагая блокировок. Местный кэш схемы обычно освобождается (уменьшая подсчеты ссылок глобального кэша в процессе), когда его связанный объект Ndb удален.

Операция без изменений схемы. Обычные операции выполняются так:

  1. Таблицу требует некоторый клиент (объект Ndb) впервые. Местный кэш проверяется, попытка ни к чему не приводит. Глобальный кэш тогда также проверяется (с использованием блокировки), попытка ни к чему не приводит.

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

  2. Второй клиент (другой объект Ndb) запрашивает доступ к той же самой таблице также по имени. Проверка местных результатов кэша ни к чему не приводит, но проверка глобального кэша приводит к хиту.

    В результате указатель объекта добавляется к местному кэшу, глобальный подсчет ссылок увеличен так, чтобы его значение равнялось теперь 2 и указатель объекта возвращен клиенту. Никакой новый указатель не добавляется к глобальному кэшу.

  3. Во второй раз второй клиент запрашивает доступ к той же самой таблице по имени. Местный кэш проверяется, производя хит. Указатель объекта немедленно возвращен клиенту. Никакие указатели не добавляются к местным или глобальным кэшам, подсчет ссылок объекта не увеличен (и таким образом подсчет ссылок остается постоянным и равен 2).

  4. Второй клиент удаляет объект Ndb. Объектам в местном кэше схемы этого клиента уменьшили их подсчеты ссылок в глобальном кэше.

    Это устанавливает подсчет ссылок глобального кэша в 1. Так как это еще не 0, никакие меры еще не приняты, чтобы удалить исходный объект Ndb.

Изменения схемы. Предполагая, что схема объекта никогда не изменяется, версия схемы, полученная сначала, используется для целой жизни прикладного процесса, а объект в памяти удален только когда все местные ссылки кэша (то есть, все ссылки на объекты Ndb) были удалены. Это вряд ли произойдет кроме как во время закрытия или сброса связи с кластером.

Если схема объекта изменяется обратно совместимым способом в то время, как приложение работает, у этого есть следующее действие:

  • Вспомогательная версия в узлах данных увеличена. Продолжающиеся операции DML, используя старую версию схемы все еще имеют успех.

  • Клиенты NDB API впоследствии получающие последнюю версию объекта схемы, получают новую версию схемы.

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

  • Клиенты NDB API, подписывающиеся на события, могут наблюдать событие TE_ALTER для рассматриваемой таблицы и могут использовать это, чтобы вызвать аннулирования кэша объекта схемы.

  • Каждая местная запись кэша может быть удалена, вызывая removeCachedTable() или removeCachedIndex(). Это удаляет запись из местного кэша и уменьшает подсчет ссылок в глобальном кэше. Когда (и если) подсчет ссылок глобального кэша достигает ноля, старый кэшированный объект может быть удален.

  • Альтернативно, местные записи кэша могут быть удалены, как и лишенная законной силы запись глобального кэша вызовом invalidateTable() или invalidateIndex(). Последующие вызовы getTable() или getIndex() и другие клиенты возвращают новую версию объекта схемы, экземплируя новый объект.

  • Новые объекты Ndb заполняют свои местные кэши таблиц по требованию от глобального кэша. Это означает, что как только старый объект схемы был лишен законной силы в глобальном кэше, такие объекты восстанавливают последние объекты таблицы, известные в то время, когда объекты таблицы сначала кэшировались.

Когда несовместимое изменение схемы внесено (то есть, было существенное изменение версии схемы), запросы API NDB, используя старую версию терпят неудачу, как только новая версия передается. Это может также использоваться в качестве триггера, чтобы получить новую версию объекта схемы.

Правила, управляющие обработкой изменений версии схемы, показаны в следующем списке:

  • Изменение схемы онлайн (незначительное изменение версии) не затрагивает существующих клиентов (объекты Ndb), клиенты могут продолжить использовать старую версию объекта схемы.

  • Если и только если клиент добровольно удаляет кэшированные объекты, делая вызовы API, он затем может наблюдать новую версию объекта схемы.

  • Когда объекты Ndb удаляют кэшированные объекты, подсчет ссылок на старых объектах схемы уменьшается.

  • Когда этот подсчет ссылок достигает 0, объект может быть удален.

Последствия жизненного цикла объекта схемы. Продолжительность жизни объекта схемы (такого как Table или Index) ограничивается жизнью объекта Ndb, из которого это получено. Когда родительский объект Ndb объекта схемы удален, подсчет ссылок, который содержит живой объект Ndb, уменьшен. Если этот объект Ndb содержит последнюю остающуюся ссылку на данную версию объекта схемы, удаление объекта Ndb может также привести к удалению объекта схемы. Поэтому никакие другие потоки не могут использовать объект в это время.

Внимание должно быть проявлено, когда указатели на объекты схемы хранятся в приложении и совместно используются кратным числом объектов Ndb. Объект схемы не должен использоваться вне продолжительности жизни объекта Ndb, который создал его.

Запросы могут ответить асинхронно и независимо друг от друга, работая с обратно совместимыми изменениями схемы, перейдя в новую схему только при необходимости. Различные потоки могут воздействовать на различные версии объекта схемы одновременно.

Таким образом очень важно гарантировать, чтобы объекты схемы не переживали объекты Ndb, которые раньше создавали их. Чтобы помочь предотвратить это, можно принять любые из следующих мер, чтобы лишить законной силы старые объекты схемы:

  • Чтобы вызвать аннулирование по мере необходимости, используйте события API NDB TE_ALTER (см. Event::TableEvent).

  • Используйте внешний триггер, чтобы начать аннулирование.

  • Выполните периодическое аннулирование явно.

Лишение законной силы кэшей любым из этих способов позволяет запросам получить новые версии объектов схемы как требуется.

Также стоит отметить что не все методы получателя NDB API Table возвращают указатели: многие из них (в дополнение к Table::getName()) возвратят имена таблиц. Такие методы включают Index::getTable(), NdbOperation::getTableName(), Event::getTableName() и NdbDictionary::getRecordTableName().

Поиск

 

Найди своих коллег!

Вы можете направить письмо администратору этой странички, Алексею Паутову. mailto:alexey.v.pautov@mail.ru