Размещение областей базы данных

Местонахождение каждого экстента базы данных можно узнать из значения столбца vstart. Именно здесь в игру вступают виртуальные номера серверных устройств (vdevno), задаваемые при инициализации серверных устройств командой disk init. Каждая 2-килобайтная дисковая страница сервера имеет свой уникальный виртуальный номер страницы, однозначно определяющий ее в рамках всего сервера.

Кроме того, каждая страница данных также имеет уникальный в пределах этой базы данных логический номер. Поэтому каждая строка таблицы sysusages содержит поле Istart — логический номер первой страницы дискового фрагмента в базе данных, использующий этот экстент.

Для каждой базы данных значение параметра Istart последовательно увеличивается от одной записи sysusages к следующей на количество страниц очередного экстента. В нашем примере, первый экстент базы данных dbl начинается с Istart = 0 и имеет размер в 5120 страниц данных, пронумерованных от 0 (номер первой страницы является значением Istart) до 5119.

Соответственно, следующий экстент базы данных начинается с Istart = 5120 и имеет длину в 2560 страниц (их номера находятся в диапазоне от 5120 до 7679) и т.д. Логические номера страниц последовательно возрастают от сегмента к сегменту. Однако этого нельзя сказать о виртуальных номерах страниц (столбец vstart).

Значение vstart каждой записи таблицы sysusages — это виртуальный номер первой страницы соответствующего экстента. Виртуальные номера страниц зависят не только от логического номера Istart, но и от виртуального номера серверного устройства vdevno, на котором находится фрагмент дискового пространства, а также от положения этого фрагмента на устройстве. Именно по этой причине два серверных устройства не могут иметь одинаковые виртуальные номера устройств. Ведь виртуальный номер страницы vstart зависит от vdevno и должен быть уникальным в рамках всего сервера.

Теперь выясним расположение каждого фрагмента дискового пространства на серверных устройствах. Сделать это можно с помощью системной таблицы sysdevices.

В ней для каждого серверного устройства (поддерживаемого разделом физического диска или файлом операционной системы) указаны значения виртуального номера первой (low) и последней (high) страниц данных этого устройства.

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

Это объясняется тем, что при выполнении команд create database или alter database, вносящих новые записи в таблицу sysusages, сервер обнаружит переполнение соответствующего устройства и будет вынужден сократить размер распределяемой области дискового пространства.

Поэтому не нужно проверять, помещается ли последняя страница каждого фрагмента дискового пространства, фигурирующего в таблице sysusages, в серверное устройство, содержащее начало этого экстента. (Оно было найдено путем сравнения виртуального номера первой страницы экстента vstart с указанным в таблице sysusages диапазоном виртуальных номеров страниц (low — high) всех устройств сервера.)

В нашем примере первый экстент базы данных db1 имеет vstart = 201326592, что свидетельствует о его размещении в самом начале серверного устройства sd4f (low = 201326592, high = 201510661.

Назначение сегментов экстентам баз данных

Отметим лишь, что каждый фрагмент дискового пространства, соответствующий одной записи таблицы sysusages, может быть назначен нескольким сегментам базы данных одновременно. Состав сегментов, объекты которых могут находится в данном экстенте, определяется значением столбца segmap.

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

Его битовое представление имеет единицу в поле данного типа сегмента и ноль во всех остальных полях массива. Итоговый вид двоичного массива можно получить, вычислив логическое “ИЛИ” двоичных кодов всех имеющихся сегментов, т.е. установив единицы в поля, указывающие на наличие реально имеющихся сегментов, и нули во все остальные поля двоичного массива. Значение segmap является представлением полученного двоичного массива в десятичной системе счисления. Это значение равно сумме кодов всех имеющихся сегментов.

Обратите внимание на то, что коды сегментов являются последовательными степенями двойки. Значение поля segmap является суммой кодов всех сегментов, присутствующих в экстенте базы данных. Поэтому при совместном размещении сегментов system, default и logsegment (неизбежном в случае базы данных master) соответствующий дисковый фрагмент получает значение segmap = 7. Фрагменты базы данных, содержащие только сегмент журнала транзакций logsegment, имеют значение segmap = 4.

Важно отметить, что код сегмента удваивается с каждым очередным номером пользовательского сегмента базы данных, увеличиваясь от 8 до 16, 32, 64, 128 и т.д. Поэтому значение segmap = 128 отнюдь не свидетельствует о наличии в экстенте 128 различных сегментов базы данных. На практике, segmap никогда не принимает всех возможных значений (например, от 1 до 128). Как правило его величина составляет 3 (1+2), 4 или 8.

Записи об экстентах баз данных нельзя удалять вручную (кроме базы данных tempdb)

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

Единственным исключением из этого правила служит база данных tempdb. Для ее уменьшения из таблицы sysusages можно удалить записи о любых экстентах tempdb, за исключением расположенной на серверном устройстве master первой 2-мегабайтной области tempdb (которую нельзя удалять ни при каких обстоятельствах).

Чтобы сократить базу данных tempdb, после удаления всех необходимых записей таблицы sysusages следует перезапустить сервер. Более подробно этот процесс описан в руководстве по устранению неполадок SQL Server (SQL Server Troubleshooting Guide).

Модификация таблицы sysusages вручную

При каждом внесении изменений в системные таблицы сервера вручную следует соблюдать перечисленные ниже основные меры предосторожности

Внимание!
1. Модификация содержания системных таблиц не поддерживается компанией Sybase. Компания не гарантирует, что различные версии сервера будут иметь одинаковую конфигурацию системных таблиц. Поэтому эта операция, выполненная в одной версии SQL Server, может оказаться неприменимой к другой версии сервера.
2. Перед изменением содержания системных таблиц обязательно проконсультируйтесь со службой технической поддержки Sybase.
3. Перед внесением изменений проверьте, имеется ли у вас полный набор дампов, необходимый для восстановления сервера в случае, если вносимые изменения приведут к нарушению его работоспособности.
4. После модификации системных таблиц для активизации внесенных изменений необходимо произвести перезапуск сервера.

Системные хранимые процедуры sp_addsegment, sp_extendsegment и sp_dropsegment автоматически проверяют все записи таблицы sysusages, относящиеся к базе данных и серверному устройству, указанным при вызове процедуры. Затем они вносят необходимые изменения в поле segmap каждого дискового фрагмента. Именно этот механизм предотвращает назначение других сегментов базы данных серверному устройству, поддерживающему сегмент журнала транзакций.
(Напомним, что logsegment имеет значение segmap = 4.) Он также не позволяет назначить logsegment серверному устройству, уже содержащему сегменты этой же базы данных.

При распространении базы данных на серверное устройство командами create database или alter database (т.е. когда в таблице sysusages создается запись о первом экстенте распространяемой базы данных, расположенном на этом устройстве) поле segmap получает значение 7 или 3 (т.е. новому экстенту назначаются сегменты system, default и logsegment либо только system и default). При создании на новом устройстве каких-либо объектов базы данных, относящихся к сегментам system или default, страницы данных этих объектов будут помечены как принадлежащие этим сегментам.

Попытка вручную установить в рассматриваемой записи значение поля segmap = 4, т.е. распределить все оставшееся пространство экстента базы данных ее сегменту журнала транзакций, приведет к тому, что сервер не запишет в этот экстент страницы данных, не относящиеся к журналу транзакций. Однако в экстенте останется некоторое количество страниц данных сегментов system или default.

Это не позволит серверу сохранить дамп журнала транзакций командой dump transaction. Пока все страницы распределенных базе данных областей серверного устройства не станут доступными журналу транзакций, принудительная установка значения поля segmap, соответствующего наличию только сегмента журнала транзакций, не позволит сохранить отдельные дампы журнала транзакций.

Здесь мы сталкиваемся с противоречием. Используя только стандартные хранимые процедуры, администратор сервера в принципе не может установить значение segmap = 4 для любого экстента базы данных, которым назначены посторонние сегменты. Однако вы в любой момент можете вручную установить требуемое значение путем прямой модификации системной таблицы sysusages.

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

Однако в некоторых случаях администратору сервера все же приходится прибегать к модификации системных таблиц вручную. Хотя подобные методы работы официально не поддерживаются Sybase, читателю все же следует знать об их существовании.

При необходимости быстрого восстановления базы данных в команде create database указывается параметр for load. В результате все экстенты воссоздаваемой базы данных получают значение segтар = 3, за исключением одного с segmap = 4 (здесь мы предполагаем, что одна из строк предложения create database содержала параметр log on). Завершив команду create database for load, вы должны загрузить дамп базы данных.

После этого, используя процедуры sp_addsegment, sp_extendsegment и sp_dropsegment, вручную разнесите сегменты базы данных по правильным серверным устройствам. Этим вы восстановите в таблице sysusages ранее существовавшие значения полей segmap всех экстентов базы данных. Правильное выполнение всех процедур манипулирования сегментами (со строгим соблюдением их очередности) представляет собой весьма утомительное занятие, особенно для больших баз данных, расположенных на множестве серверных устройств. Значительно проще внести нужные изменения непосредственно в записи таблицы sysusages, основываясь на значениях полей Istart записей sysusages, относящихся к загруженной таблице данных.

Отметим, что значения полей vstart зависят от виртуальных номеров серверных устройств vdevno.

Поэтому они могут измениться, если при восстановлении сервера его устройства были проинициализированы командой disk init в другом порядке. Однако значения параметров Istart остаются прежними при условии, что порядок создания экстентов базы данных и их размеры соответствовали первоначальным. В результате мы получаем возможность использовать Istart при установке полей segmap вручную. При этом значение segmap зависит от диапазона значений Istart.

Снова обратимся к базе данных db1. Предположим, что она была воссоздана командой create database с параметром for load. Эта команда восстановила в таблице sysusages три записи, сохранив порядок их следования и размеры соответствующих фрагментов дискового пространства.

Можно приступить к восстановлению прежних значений полей segmap этих записей. Напомним, что любая операция по модификации sysusages (или любой другой системной таблицы) должна выполняться как единая транзакция, т.е. начинаться командой begin tran <название_транзакции>, что позволит в случае ошибок воссоздать исходное состояние таблицы sysusages. Найдем все записи таблицы sysusages, имеющие dbid = 4, после чего установим segmap = 3 для записей со значением поля Istart в диапазоне от 0 до 5119.

Напомним, что в прежней базе данных dbl первый экстент с segmap = 3 имел длину в 5120 страниц (10 Мбайт). Мы не случайно говорим здесь обо всех записях со значением поля Istart в диапазоне от 0 до 5119″. Из-за изменившейся структуры свободных областей серверных устройств сервер может отказаться снова выделить 10 Мбайт в качестве единого фрагмента дискового пространства.

Тогда прежней области базы данных будут соответствовать два экстента длиной, например, в 7 и 3 Мбайт, представленные в таблице sysusages двумя отдельными записями. Перейдя к следующим записям sysusages, соответствующим базе данных dbl (dbid = 4), мы установим segmap = 4 для всех записей с Istart, находящимся в диапазоне от 5120 до 7679, a segmap = 3 — для записей со значением поля Istart, равным 7680 (или большим этого числа). В итоге прежняя структура назначения сегментов областям базы данных окажется восстановленной.

Разумеется, описанный метод становится невозможным при отсутствии копии прежней таблицы sysusages. Это относится и к операции восстановления структуры базы данных вручную процедурой sp_createeegment и другими подобными командами. В них все равно потребуется указать исходные размеры экстентов базы данных с сохранением прежнего порядка их следования. Подобный процесс можно ускорить с помощью командного файла p_dbcreate, генерирующего все необходимые команды для воссоздания базы данных с параметром for load и ее сегментации путем модификации записей таблицы sysusages.

Такой командный файл окажется крайне полезным при восстановлении базы данных на прежнем сервере. Им можно воспользоваться и для переноса базы данных на другой сервер, поскольку и в этом случае вам потребуется создать прежний набор экстентов базы данных для сохранения ее сегментации. Желательно, чтобы структура и названия серверных устройств нового сервера совпадала со старым.

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

Команда load database и таблица sysusages

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

Именно в таком порядке производится запись базы данных в дамп, а также загрузка ее страниц из ранее созданного дампа. Поэтому при воссоздании базы данных (как на прежнем, так и на новом сервере) вновь распределяемые экстенты дискового пространства должны иметь прежние размеры и назначаться в прежнем порядке. Для базы данных db1 сначала создадим 10-мегабайтный экстент и назначим его сегментам system и default (segmap = 3).

Затем — 5-мегабайтный экстент, содержащий сегмент журнала транзакций (segmap = 4), и, наконец, еще один 10-мегабайтный экстент с segmap = 3. Вновь создаваемые экстенты базы данных могут быть образованы из нескольких отдельных областей дискового пространства, которым будут соответствовать несколько строк таблицы sysusages.

Важно лишь, чтобы общий объем и порядок следования экстентов с одинаковыми значениями segmap оставались прежними. В нашем примере загружаемый дамп базы данных dbl будет содержать 10 Мбайт страниц данных сегментов system и default (segmap = 3); 5 Мбайт журнала транзакций (segmap = 4); еще 10 Мбайт страниц данных, также относящихся к сегментам system и default.

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

Если это соответствие нарушается, загружаемые страницы данных попадают в экстенты базы данных, назначенные другим сегментам. Например, страницы журнала транзакций вместо сегмента logsegment попадут в сегменты system и default (и наоборот). Это не скажется на возможности выборки данных из восстановленной базы данных, но фактически исключит процесс записи в любые ее сегменты.

Серверу придется записывать модифицированные страницы объекта данных сегмента default на серверное устройство, которое согласно таблице sysusages назначено исключительно сегменту
журнала транзакций (segmap = 4).

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

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100