августа 13, 2007

Обзор версионных субд глазами воинствующего ораклойда

Давно хотел немного пошалить и собрать в одном документике архитектуру различных версионных субд, вокруг которых достаточно регулярно возникают самые интересные религиозные войны. Вот тут я и попробовал пройтись по архитектуре некоторых распространенных сегодня субд MVCC (multi-version concurency control).
За идеал версионной архитектуры конечно же возьму архитектуру Oracle, идеальность которой как известно сомнению не подлежит :)

Итак приступим: на низшей ступени стоят файл-серверные субд, такие как Foxpro и Accsess и прочая. Тут нет ничего: вместо ACID транзакций - "fake" [1], нет понятия уровня изолированности транзакций или консистентного набора (вместо этого некая буферизация), отсутствует стоимостный оптимизатор и самое прикольное - полная беззащитность БД. Любой кто имеет доступ к системе может записать все, что злобной душе угодно напрямую в файл БД минуя субд.
По транзакциям, как важнейшему компоненту субд, наверно стоит пройтись отдельно. Например в Foxpro это выглядит примерно так: средствами ОС на куски файла (к стате ну очень отдаленно напоминает как Oracle хранит блокировки в блоках данных) ставятся блокировки, после чего модифицируется некий кеш на клиенте и только после commit, содержимое кеша сбрасывается в файлик БД (dbf). В результате, если происходит сбой (файл-сервера или в сети) после фиксации транзакции, во время сбрасывания кеша, БД просто превращается в неконсистентную кашу, т.к. отвернуть неудачную транзакцию просто некому. При Insert ситуация не так страшна, т.к. судя по всему сначала данные записываются в конец файла и только потом модифицируется его заголовок, поэтому Foxpro может врубится, что данные заголовка не совпадают с реальным размером файла, а вот с Update все веселее - клиент просто молча может сбросить лишь часть данных кеша и молча погибнуть, при этом, о таком веселом происшествии прознать нет никакой возможности. Сложно сказать как это происходит в Access т.к. Майкрософт скрывает технические подробности, но судя по структуре файла Access тут таже беда, т.к. вернуть оригинальную версию строки при неудачной транзакции попросту неоткуда.
Немного снизить шансы такого сбоя можно попробовав перетащив систему на клиент-серверную архитектуру, например с помощью встроенных функций SOAP, но ACID транзакции и консистентный набор от этого к сожалению не появятся.

На заметно более высоком уровне развития находятся Interbase и его open source клон Firebird. Тут уже присутствуют зачатки почти всех признаков "взрослых" субд, единственно, напрочь отсутствует лог транзакций. Firebird существует в двух архитектурах: Classic и Superserver.
В Classic туча независимых сессий/процессов имеющих собственный отдельный кеш, зато процессы бывает раскидываются операционной системой по разным процессорам.
Superserver, появившийся позже, имеет один процесс и единый на все сессии кеш, что уже немного больше напоминает взрослые субд, облом состоит в том, что этот единственный процесс должен быть привязан к одному процессору, т.е. smp/многоядерные системы не супортится.
Концепция MVCC Firebird досталась еще от Rdb компании DEС и сильно отличается от нашего "идеала": При модифицируемой транзакции новые версии строк пишутся прямо в тот же блок или рядом с оригинальной версией, причем в большинстве случаев не вся строка, а только "дельта" между оригинальной и новой строкой (если дельта выходит больше, чем строка, пишется вся строка). По commit модифицируется Transaction Inventory Page (TIP) (заголовок дата-файла), где отмечается статус транзакции, по сути одним движением головки HDD, что и гарантирует ACID и невозможность беды подобной Foxpro. [2] Далее асинхронный процесс подчищает ненужные версии строк из файлов данных, что конечно же отлично сказывается на самочувствии остальных пользователей.
С уровнями изолированности транзакций тут так же не все гладко (в сравнении с остальными версионниками): READ COMMITED не обеспечивает консистентное чтение на уровне стэйтмента. [3]
[Добавление: в InterBase 7.x появился transaction log и smp support в superserver архитектуре]

Следующим идет Postgres, тут все уже гораздо лучше, есть WAL (write-ahead log) лог транзакций, сессии реализованы в виде процессов и имеют общий кеш, READ COMMITED обеспечивает консистентный набор стейтмента, все как у больших. Единственное большое разочарование - схожая с Firebird схема хранения версий строк или их дельты прямо в файлах данных, и соответственно необходимость в сборе мусора.

Microsoft SQL server 2005 практически полностью скопировал реализацию MVCC Oracle/Postgres, но как обычно MS немного не дотянул. Например, Oracle оперирует версиями блока данных, а сиквел строками. Оперирование блоками позволяет универсально накладывать версионность на любой объект, плюс позволяет делать оптимизацию: если блок уже стоит в очереди на сброс (на носитель), Oracle может создать копию блока и модифицировать именно копию, вместо того, чтоб дожидаться когда блок окажется на носителе.
Второе крупное различие - в mssql2k5 версии строк хранятся в tempdb, в то время как в Oracle в отдельной структуре сегментов отката (в оракле для отдельных транзакций можно создавать отдельные сегменты отката ). Tempdb часто становится головной болью администратора mssql и без версионности, проблеме i/o в tempdb на msdn посвящена не одна нота т.к. там помимо временных таблиц и табличных переменных хранятся сортировки и курсоры. Добавление в tempdb еще и версий строк делает и без того перегруженный tempdb узким местом в системе. Кроме этого MSSQL вынужден раз в минут (или при нехватке места) заниматся сбором мусора из tempdb, что также создает дополнительную нагрузку.
Следующее различие в том, что сегменты отката Oracle защищены от безразмерного роста и место пространства отката используется циклически (размер и их кол-во может задаваться админом). При неправильном размере сегментов очень длинная транзакция может получить ошибку ORA-01555 snapshot too old, в результате чего откатится лишь одна транзакция, в то время как в mssql2k5 ни что не ограничит рост tempdb, в результате одна «неудачная» транзакция может просто переполнить tempdb и остановить работу всех пользователей (есть job которым можно как-то попробовать среагировать).

Будете смеяться, но с точки зрения концепций MySQL/Innodb оказывается ближе всех - у него как и в Oracle выделены два лога UNDO и REDO, однако оперирует не блоками, а строками. [4] Поскольку UNDO отдельная структура, которую можно использовать циклически - нет необходимости в сборе мусора. Однако блокировки как и mssql хранятся в отдельной структуре в памяти, а не в блоках данных, кроме этого mysql исповедует multi-threading архитектуру, такую архитектуру Oracle использует только на Windows платформе.

To be continued ...

ЗЫ расстановка была только по степени похожести на архитектуру Oracle, совершенно не учитывая реализацию этой архитектуры ...

13 комментариев:

Анонимный комментирует...

А если не секрет, русскому языку где учились? :)

ivbeg комментирует...

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

Анонимный комментирует...

И про IB вы неточно написали. В версии 7 на суперсервере поддерживается многопроцессорность. А в IB 2007 есть лог транзакций.

Yo! комментирует...

>И про IB вы неточно написали.
в тексте речь идет именно о FireBird, так что все достаточно точно, но про IB 2007 наверно можно добавить.

Анонимный комментирует...

Лучше расскажи про "лёгность" управления индивидуальными сегментами отката в оракле для транзакций

Yo! комментирует...

да, ужос как сложно:
CREATE ROLLBACK SEGMENT rbs_one
TABLESPACE rbs_ts;

Rollback segment created.

SQL> SET TRANSACTION USE ROLLBACK SEGMENT rbs_one ;

Transaction set.

Дмитрий комментирует...

Прочитал.
Удивлен, что в коротком тексте автор попытался объять необъятное. Попытка зачтена, но не более.
Про FireBird (про другое судить сложно) Вы по верхушкам скользнули. Покопайте, и не забудте про возможности версии 2.1 (она уже хорошая альфа).
С удовольствием прочту продолжение.

Анонимный комментирует...

Сразу вспомнилась песня оракл-администратора про "Большой ролбэк сегмент для маленькой компании" :)
Ну и масса ляпов по смыслу. Большой совет - не ссылаться на форумы sql.ru в качестве источника информации - лучшесразу на udaff. Вроде люди взрослые, все повоинствовать хочется? Ну так был же день десантника, сходили бы в парк горького и крикнули "десант слабаки" :) Адреналина с перехлестом.
Хотя радует, что версионность идет в массы и теперь уже не осталось (?) оголтелых блокировочников.

Yo! комментирует...

>Большой совет - не ссылаться на форумы sql.ru в качестве источника информации

незнаю, незнаю - практика показывает, что sql.ru гораздо серьезней как источник, чем скажем Майкрософтский MSDN с его транзакциями в foxpro ...
если видишь ляпы - ты уж не замалчивай ;)

Анонимный комментирует...

> Microsoft SQL server 2005 практически полностью скопировал реализацию MVCC Oracle

учитывая, что версионность построчная и надо убирать мусор (пусть и в tempdb), я бы скорее назвал это копированием с PGSQL/IB/FB. Или аффтару пофиг, что страничные операции выполняются на несколько другом архитектурном уровне СУБД?

Yo! комментирует...

ну да, про сбор мусора в tempdb забыл упомянуть, а на счет копирования просто слышал байку о том, что по теории MVCC они из докладов оракла обучались. по уровням не вьехал.

Анонимный комментирует...

Забыли про Sybase ASA 10.
В одном из топиков на sql.ru я(ggg_old) приводил выдержку из документации про реализацию snapshot isolations в этом сервере.

Анонимный комментирует...

За идеал версионной архитектуры конечно же возьму архитектуру Oracle, идеальность которой как известно сомнению не подлежит :)Итак приступим: на низшей ступени стоят файл-серверные субд, такие как Foxpro и Accsess и прочая