faqs.org.ru

 Главная > Программирование > Работа с базами данных >

Borland Interbase 5 FAQ

Секция 3 из 3 - Предыдущая - Следующая
Все секции - 1 - 2 - 3

1.63 Многоверсионность метаданных, или как поддерживается модификация структур таблиц.

см. материал по версиям метаданных.

1.64 Почему рекомендуется периодически делать backup/restore ?

Вообще, backup предназначен для резервирования данных на случай сбоя системы. Кроме того, backup/restore делает несколько полезных вещей:

  • сбрасывает счетчики версий метаданных
  • перепаковывает записи на страницах данных
  • убирает старые версии записей (как sweep)
  • перестраивает индексы
  • возвращает дисковое пространство операционной системе
  • очищает "дыры" в многофайловой БД
  • при восстановлении можно изменить размер страницы.
  • 1.65 Как работает многоверсионность записей ?

    Многоверсионность записей работает следующим образом:

  • при удалении запись помечается на удаление, и может быть удалена только после commit этой транзакции. Если транзакции repeatableread, видящие такую запись, все еще активны, то запись остается "неудаленной" до тех пор пока они не завершатся. Когда в записи никто не заинтересован, она помечается на окончательное удаление и будет физически удалена либо при database sweep, либо при старте другой транзакции (и запроса) которая могла-бы прочитать эту запись.
  • при вставке записи, запись не видна до тех пор пока вставившая ее транзакция не будет завершена. Если в данный момент активны транзакции repeatableread, то они не увидят такую запись даже если был сделан commit для вставляемой записи, поскольку их transaction id меньше чем у транзакции, вставившей запись.
  • при изменении записи, пока транзакция не закончена, на свободное место страницы данных записываются только измененные поля (delta). Транзакция, изменившая запись, вынуждена производить "сборку" записи из старых и новых значений чтобы увидеть актуальные данные. Другие транзакции будут видеть старые версии записей, поэтому блокировок по чтению не возникает. Delta не может превышать 256 байт,  кроме этого изменения полей blob не сохраняются как delta, т.к. в записи хранится не содержимое blob а его идентификатор (изменения blob сохраняются на отдельных страницах, но не на целой странице на 1 blob, а сегментами). Если изменений много, то IB выделяет для их хранения  дополнительные страницы данных. При большом количестве изменений "сборка" записей может вызвать более интенсивный обмен с диском и общее ухудшение производительности.
  • Возможна ситуация, при которой существует несколько версий одной записи, а не две как это кажется (старая и новая). Например транзакция 1 видит версию 1, транзакция 2 обновляет ее до версии 2, транзакция 3 видит версию 2, транзакция 2 подтверждает изменения но версия 2 остается видимой для транзакции 3, транзакция 4 обновляет запись до версии 3 и т.д.

    1.66 Какие блокировки обеспечивает IB ?

    SQL-сервер IB использует "оптимистические блокировки" на уровне записей. Это означает, что чтение данных никогда не блокирует их от изменений. И наоборот, изменение данных не приводит к их блокировке по чтению (хотя возможен режим, когда транзакция будет при чтении ждать завершения транзакции, изменившей записи).

    Суть блокировок обеспечивается механизмом многоверсионности записей - запись блокируется от изменений транзакцией только если эта запись была изменена или удалена другой транзакцией.

    Вообще в IB блокировки в общепринятом смысле отсутствуют. При изменении записи проверяется, есть-ли у этой записи указатель на старую версию записи, и совпадает-ли идентификатор текущей транзакции с идентификатором транзакции, изменившей запись. Если такой указатель есть - считается что в этот момент кто-то другой уже изменил запись, но не подтвердил ее изменения, и только в этом случае запись считается "заблокированной" от изменений.

    1.67 Существуют-ли в IB блокировки по чтению ?

    Нет. Невозможно заблокировать запись чтением, и невозможно заблокировать запись от чтения. Запись можно блокировать от изменения или удаления только заблаговременным обновлением. Т.е. чтобы никто другой не мог сделать UPDATE записи, вы должны тоже выдать UPDATE этой-же записи ("холостой" UPDATE).

    Есть только один случай, когда при чтении обновленной записи IB выдает deadlock - если ваша транзакция стартовала с параметрами

    SET TRANSACTION READ WRITE NO WAIT READ COMMITTED NO RECORD_VERSION.

    Такая транзакция не будет иметь возможности читать старые версии записей, если есть новые версии этих записей (режим NO RECORD_VERSION).
    Этот уровень изоляции ошибочно использовался в BDE вплоть до версии 4.01. В 4.01 и выше транзакция ReadCommitted имеет параметр RECORD_VERSION. Подробнее об этом см. статью.

    1.68 Какие уровни изоляции поддерживает IB ?

    Для начала заметим, что режим Dirty Read (чтение неподтвержденных записей) IB не поддерживает. Т.е. такая ситуация в механизме многоверсионности  записей просто невозможна.

    Поддерживаемые уровни:

  • Read Committed - чтение подтвержденных записей, то-же самое что и "невоспроизводимое чтение".
  • Repeatable Read- воспроизводимое чтение (snapshot). Видны только те версии записей, которые существовали на момент начала такой транзакции. Внутри такой транзакции разрешено не только чтение, но и вставка/удаление/модификация записей.
  • SNAPSHOT TABLE STABILITY - snapshot с резервированием таблиц. Таблицы могут быть заблокированы от изменения, но никогда - от чтения. (В Delphi этот режим включить невозможно, т.к. BDE не может управлять параметрами транзакций любого SQL-сервера. Через IB API - возможно)
  • примечание: у транзакций IB есть большое количество дополнительных параметров, которые можно изменять только через IB API. При работе из BDE используются умолчательные значения этих параметров. Более подробно см. IB API Guide.
    примечание: в BDE 5.01 (www.borland.com/devsupport/bde) для IB появилась поддержка режима WAIT/NO WAIT и COMMIT/COMMIT RETAIN через параметры алиаса.

    1.69 С какими транзакциями работают BDE, WISQL ... ?

    BDE как универсальный интерфейс доступа к данным работает с тремя типами транзакций - DirtyRead, ReadCommitted, RepeatableRead. Вместо DirtyRead для IB используется ReadCommitted.

    Вы можете стартовать любую из этих транзакций из Delphi, установив нужный уровень изоляции в свойстве TDatabase.Transisolation и вызвав метод TDatabase.StartTransaction.

    Если вы не управляете началом транзакции самостоятельно, то независимо от установленного уровня изоляции в TDatabase.TransIsolation BDE автоматически подтверждает любые изменения данных следующими транзакциями:

    Delphi 1.0, версия BDE <= 2.5 RepeatableRead

    Delphi 2.0, версия BDE = 3.x ReadCommitted

    Delphi 3.0, версия BDE >= 4.0 RepeatableRead

    Для того чтобы изменить транзакцию по умолчанию (ReadCommitted) для BDE =3.x на RepeatableRead, вы должны изменить при помощи BDECFG значение параметра DRIVER FLAGS с пустого на 512 (см. справку BDECFG либо READLINK.TXT).
    В BDE версии 4.0 и выше для IB можно при помощи флагов управлять не только типом транзакции, но и способом ее завершения по умолчанию (COMMIT или COMMIT RETAIN), что позволяет избежать автоматического перечитывания записей при COMMIT в режиме BDE SHARED AUTOCOMMIT. Более подробно см. READLINK.TXT из поставки Delphi 3.0 C/S, или BDEREADME.TXT из BDE 5.01 update.

    WISQL по умолчанию стартует транзакцию SET TRANSACTION SNAPSHOT, т.е. RepeatableRead. В WISQL вы можете стартовать любую транзакцию IB (см. SET TRANSACTION в HELP или документации).

    1.70 Можно-ли управлять параметрами транзакций IB из BDE ?

    К сожалению, нет. Нет способа получить из BDE native transaction handle для IB, поэтому изменить характеристики транзакции IB или стартовать свою транзакцию через BDE невозможно.

    Компоненты прямого доступа FIBC, IBX, IBObjects могут устанавливать любые параметры транзакций, осуществлять двухфазный коммит и открывать любое количество транзакций в одном соединении.

    1.71 Что такое BLR ?

    Binary Language Representation. В таком виде хранятся и исполняются в IB триггеры, хранимые процедуры, контроль полей и prepared queries.

    Может-быть кому-то покажется странным, но язык SQL не является интерпретируемым. Например, имена полей в операторе SELECT могут быть обработаны только после разбора имен таблиц, участвующих в этом SELECT.

    1.72 Что такое UDF ?

    User Defined Functions - функции, определяемые пользователем. Вы можете на C или C++ (для любой платформы) или на Delphi 2.0 (для Windows NT) написать собственные функции и расширить таким образом функциональность IB.

    (исключением является IB for NetWare, т.к. для написания UDF пользователю пришлось-бы писать NLM. Кроме того, некорректная работа такого NLM могла-бы повлечь за собой "падение" сервера NetWare.)

    Существуют как свободно распространяемые библиотеки UDF, так и коммерческие (от MER Systems, более 100 функций).

    ДемоЦентр предлагает вам собственный бесплатный набор UDF, который больше представляет собой подробнейший "учебник" для написания собственных UDF на Delphi 2.0. Безусловно в этом наборе вы найдете множество полезных функций, таких как работа с датами, строками, varchar, поиск подстроки в BLOB и т.п.

    Также весьма популярна бесплатная библиотека FreeUDFLib, содержащая большое количество функций в исходных текстах (Delphi).
    см. раздел UDF в "Файлах и утилитах".

    1.73 Не восстанавливаются (restore) процедуры (sp) с QUERY PLAN. Что делать ?

    Это действительно ошибка в GBAK. Исправлено в IB 5.0.

    Тем кто продолжает работать на версиях 4.x, можно предложить следующее решение:
    перед backup выполнить скрипт, который заменит проблемные процедуры на пустые
    alter procedure xxx as begin suspend; end^
    ...
    А после restore выполнить скрипт, восстанавливающий текст процедур.

    1.74 Почему Server Manager не показывает Database Connections на WinNT ?

    Этот пункт меню "платформо-зависимый". Для NetWare и Local IB он разрешен, а для IB 4.0, 4.1 for NT - запрещен.

    Для IB 4.2 и 5.0 for NT этот пункт разрешен, поскольку с версии 4.2 IB имеет архитектуру SuperServer.

    примечание: версия IB 5.1 for RH Linux 5.2 имеет архитектуру Classic, и не позволяет просматривать количество активных соединений.

    1.75 Что такое архитектура SuperServer ?

    Исторически сложилось так, что первоначально SQL-серверы работали в архитектуре, когда подсоединение нового пользователя вызывало создание нового процесса SQL-сервера, работающего в отдельном адресном пространстве. Такие процессы могли общаться друг с другом только через Shared Memory или похожие механизмы.

    Постепенно большинство производителей SQL-серверов пришли к выводу, что такая архитектура устарела, и перешли на новую - SuperServer. Это громкое слово всего-лишь означает, что на каждого пользователя создается новый поток (thread) вместо процесса. Таким образом потоками можно управлять в одном адресном пространстве, можно оптимизировать кэширование считываемых разными потоками данных, и т.д. Однако понятно, что такая архитектура менее устойчива к сбоям отдельных потоков (это относится ко всем реализациям данной архитектуры).

    IB соответствует архитектуре SuperServer с версии 4.2, 5.x для Windows95/NT, 5.x для Solaris и HP-UX, 5.6 для SCO.

    На NetWare архитектура SuperServer была всегда.

    1.76 Соответствует-ли реализация SQL в IB стандарту ANSI и какому ?

    Реализация SQL в IB соответствует entry level ANSI SQL-92. Это означает, что все возможности, заявленные в entry level, реализованы в IB. Также в IB реализованы некоторые возможности более высокого уровня (например домены), но для соответствия intermediate или full level требуется полная реализация соответствующего уровня, чего пока нет не только в IB, но и практически в любых других SQL-серверах.

    1.77 Можно-ли поместить GDB-файл на другой компьютер ?

    Это возможно только для 16-разрядного Local IB. Для 32-разрядных версий IB это невозможно. Даже если-бы это и было возможно, то надежность такой системы была-бы весьма низка. Вообще возможность помещать GDB на файл-сервер была специально отключена для того, чтобы исключить возможность доступа к одному-и тому-же GDB с разных станций, использующих Local IB или с других операционных систем. IB, как и любой другой SQL-сервер, может обеспечивать корректную работу с БД только как сервер (т.е. самостоятельно предоставляя конкурентный доступ к БД нескольким пользователям одновременно), а не в режиме разделения файла в сети.

    1.78 В чем разница между OAT и OIT ? (старейшей активной и старейшей заинтересованной транзакцией).

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

    Базовая идея состоит в том, что ядро IB старается обеспечить каждой транзакции "вид" целостной БД начиная от момента старта этой транзакции. Для этого, ядро определяет состояние версии записи для транзакции, выбирающей записи. Если запись была создана транзакцией, завершенной перед стартовавшей транзакцией, то такая транзакция увидит эту запись. Если запись была создана отмененной транзакцией (rolled back), то запись будет "очищена" (перезаписана другой версией или удалена со страницы данных). Если запись была создана транзакцией, которая все еще активна на момент старта выбирающей записи транзакции, то ядро IB использует указатель на "старую" запись, либо игнорирует запись полностью (при отсутствии "старой" версии).

    В файле БД существует набор страниц, называемых Transaction Inventory Pages (TIP), в которых хранится информация о всех стартовавших транзакциях. Каждая транзакция может находиться в четырех состояниях: activ (активная, committed (подтвержденная), rolled back (отмененная), in limbo ("зависшая" между фазами при двухфазном подтверждении транзакций - two phase commit).

    Состояние транзакций может быть изменено автоматически записью в соответствующую страницу TIP.

    Для отслеживания состояний взаимосвязанных транзакций, каждая транзакция должна знать состояние других транзакций на момент своего старта. Эта информация может быть получена копированием страниц TIP во внутренний блок транзакции. Поскольку номер транзакции постоянно увеличивается, увеличивается и размер внутреннего блока транзакции и количество прочитываемых страниц TIP, что приводит к увеличению "стоимости" старта транзакции.

    Для контроля "стоимости" старта транзакции, IB имеет концепцию "заинтересованной" (interesting) и "скучающей" (boring) транзакций. Boring транзакция - это либо подтвержденная либо полностью завершенная транзакция. Заинтересованная транзакция - либо активная либо "зависшая". Поэтому для стартовавшей транзакции нет необходимости знать состояние всех транзакций в БД, а только те, которые были (или еще есть) после "старейшей заинтересованной" транзакции.

    Sweeping - это "домашняя уборка", которая трансформирует "погибшую" но заинтересованную транзакцию в "скучающую" транзакцию.

    Вообще процесс sweep - ничего более последовательного сканирования всех таблиц БД. Поскольку обнаружение "мертвой" версии записи приведет к "сбору мусора", sweep превращает все "старейшие заинтересованные транзакции в "скучающие" транзакции, снижая стоимость старта новой транзакции. Sweep никого не блокирует и требует очень мало ресурсов.

    Итак sweep - не такое уж большое дело. В большинстве СУБД процесс sweep делает очень малую "сборку мусора", т.к. в них отсутствует подобная IB многоверсионность записей. В нашем случае sweep подтверждает что весь мусор собран и транзакции переведены в состояние "скучающих". Кроме того, для хранения состояния транзакции используется два бита (четыре состояния), поэтому затягивание со sweep не очень сильно влияет на производительность.

    Проблемы со sweep в общем относятся к не процессу sweep, а к тому что кто-то стартовал 20000 транзакций. Старт одной транзакции имеет среднюю стоимость (запись на диск, сканирование TIP, создание собственного блока и блокирование его lock manager-ом), но старт и подтверждение 20000 транзакций - очень высокую стоимость.

    Если вы собираетесь добавить в таблицу 20000 записей, лучше это делать в одной транзакции нежели в 20000 отдельных.

    примечание: максимально подробное описание этого вопроса вы найдете в статье.

    1.79 В чем разница между CHAR и VARCHAR ? Что лучше использовать ?

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

    Если вы собираетесь хранить строки длиной не более 40-50 символов, то лучше использовать CHAR. Более подробно см. статью.

    При передаче по сети в текущих версиях IB VARCHAR передается так-же как и CHAR (т.е. неэффективно). Исправлено в IB 5.0.

    1.80 Можно-ли поместить БД IB на CD-ROM ?

    В IB 4.x и 5.x база данных должна быть всегда доступна на запись, т.к. даже простая выборка (чтение) из БД стартует транзакцию, а информация о транзакции должна быть записана в БД.

    Возможность работать с read-only базами данных, а следовательно и помещать их на CD-ROM, появится только в IB 6.0.

    1.81 Как выполнить create procedure/trigger при помощи TQuery?

    Для этого у TQuery нужно установить property ParamCheck:=False. При этом текст запроса не будет проверяться на наличие параметров, которые предваряются двоеточием (:). Никаких других изменений не требуется.

    1.82 Как установить генератор в нужное значение в процедуре или триггере?

    Действительно, оператор SET GENERATOR... является оператором DDL, а операторы DDL не допускаются в триггерах или процедурах. Установить значение генератора в нужное можно очень простым способом (например в 0):
    ...
    TMP=GEN_ID(MYGEN, -GEN_ID(MY_GEN, 0));
    ...

    Т.е. увеличить значение генератора на его текущее отрицательное значение.

    1.83 Не могу подсоединиться к IB из под web-сервера IIS, Netscape, Baikonur и др.

    Если вы обращаетесь к IB из IIS, Baikonur и т.п. Web-серверов, то нужно использовать строку коннекта как для удаленного сервера, т.к. локальное подсоединение работать не будет. Например, 'server:c:\dir\data.gdb' или '\\server\c:\data.gdb'.

    1.84 Ошибка при установке "Internal error near IBcheck"

    Эта ошибка вызвана порчей ключа registry инсталлятором Delphi 4. Исправить ее можно, запустив RegEdit и проверив ключ HK_CURRENT_USER/Environment. Значение PATH должно быть строкового типа. Если это не так, то PATH надо поменять (или пересоздать) на строковое значение.


    (с) 1997 Epsylon Technologies

    Секция 3 из 3 - Предыдущая - Следующая

    Вернуться в раздел "Работа с базами данных" - Обсудить эту статью на Форуме
    Главная - Поиск по сайту - О проекте - Форум - Обратная связь

    © faqs.org.ru