|
|
|||||||||||||||||||||||||||||
|
Версия сервера, версия базы данных и уровни совместимости. Часть 2/4.Источник: sqlcmd
Насколько же успешно решается вопрос заданный в последнем предложении предшествующей части статьи? Насколько корректно ведет себя SQL Server версии X при попытке заставить его работать с базой данных созданной на сервере версии Y , причем X < Y ? Ну - "футболить" администратора в таком сценарии у сервера версии X получается просто на 5 с плюсом, никаких претензий! С информативностью же касательно причины подобного "футбола" сложнее. Диапазон сообщений которые вы можете получить в описываемом сценарии простирается от более-менее внятного This database is version YYY. This server is compatible with version XXX or previous. до загадочных Could not find row in sysindexes for database ID 10, object ID 1, index ID 1. Run DBCC CHECKTABLE on sysindexes. или даже The media family on device 'c:\abc\zyx.bck' is incorrectly formed. SQL Server cannot process this media family. Отсюда получаем простое и практичное правило: Если при восстановлении/подключении базы мы получаем "странное" сообщение (сообщение неожидаемое нами), то вне зависимости от его текста наш первый шаг - убедиться в совместимости версий базы и сервера. Обратите внимание, что даже в сообщении названным автором "внятным" вы получаете "голые" версии баз , без всяких сносок по их связям с версиями сервера . Про сообщения "загадочные" и говорить не приходится, там нет хотя бы даже такой, "сырой" информации. Стало быть, что бы реализовать наше "простое и практичное правило" на практике, нам, в общем случае, требуется решение двух задач:
Начнем со второго пункта. Прежде всего заметим себе, что формат версии обсуждаемой нами в текущий момент, много, много проще чем формат версии из предыдущего раздела. Версия базы - это трехзначное число . Да, вот так все просто. Ни точек тебе, ни компонентов номера версии как было в случае сервера. Однако соотнести это трехзначное число с той версией сервера что его "породил", намного сложнее чем провести параллель между числовой версией сервера и его коммерческим именем. Дело в том, что последняя "связь" является публичной, и публикуется официально, и, как было показано ранее, существуют даже отдельные сайты эту связь показывающие. Уравнение же "версия базы"="версия сервера", является, по причинам выходящим за рамки здравого смысла, закрытой и "внутрифирменной". Почему бы не публиковать ее вполне официально (как вариант, имея такую информацию, администратор получив задание на работу с базой версии YYY может, в свою очередь, "пробить" у руководства фирмы покупку апгрейда сервера текущего до нужной версии) - загадка. "Конспирологический" вариант объяснения: Microsoft подспудно толкает такого администратора на апгрейд "не глядя" до максимально предлагаемой в текущий момент версии сервера. Что, до некоторой степени, даже верно, по крайней мере с точки зрения долгосрочной перспективы. Как бы там ни было, а официальной таблицы "перевода" версий база ↔ сервер - нет . Все что нам способен предложить могучий Интернет - записки и наблюдения энтузиастов всемирного SQL-сообщества. Из этих самых записок вытанцовывается такая вот примерно табличка:
На сетевых просторах вы можете встретить различные варианты приведенной таблицы. Скажем ряд авторов в своих публикациях полагают, что серверу 2008-му соответствует версия базы 661 (а не 655), а версии 2008R2 - 665 (а не 661). Автор данных строк полагает, что такие расхождения проистекают, во-первых, из искусственной закрытости разбираемого вопроса, и, во-вторых, из-за элементарной человеческой невнимательности. С точки зрения все того же автора именно вариант таблицы представленный выше является корректным, но, разумеется, он с удовольствием выслушает ваши контр-аргументы в комментариях к данный статье. И если последние будут весомыми с не меньшим удовольствием внесет правки в обсуждаемую таблицу. Кроме того, понятное недоумение вызывают версии баз для серверов 2008 и 2008R2 со вторым и первым сервис-паками соответственно. Откуда эта запись через дробь? Разве не должно быть однозначного соответствия база ↔ сервер? В целом - да, такая однозначность быть обязана и в целом, как видите, она выдерживается. Однако тут у нас особый случай (точнее - пара), разбор которых мы отложим до заключительного раздела данной статьи.
Понятно, что в приведенную таблицу вошли не абсолютно все существующие на текущий момент номера версий баз, а лишь их наиболее значимые представители. Вам вполне может встретится база с версией в таблице неупомянутой, но тогда отыскав в той же таблице пару значений больше/меньше вашей версии вы хотя бы получите представление на каком сервере такая база была создана. Какие же выводы может сделать пытливый ум анализируя приведенную таблицу? А вот какие:
Итак, второй пункт нашего списка из двух задач решается с некоторым "скрипом" и неоднозначностями. Но - решается. Пункт первый (непосредственно нахождение номера версии базы) может быть описан и решен гораздо более четко, хотя и тут не все так просто, как было с версией сервера. В каком состоянии может находится база в тот момент когда мы решим поинтересоваться номером ее версии? Очевидно - в одном из вот таких:
Стало быть - по порядку. Если база уже существует, т.е. мы в свое время исполнили нечто вроде:
то, в вопросе определения версии базы у нас нет вообще никаких проблем. Во-первых, способ "быстрый и грязный":
вернет нам 661 что полностью соответствует версии 10.50.2500 сервера установленного на тестовой машине автора. Почему автор называет данный способ быстрым, полагаю, вполне понятно, но почему - "грязным"? А потому, что официальная документация говорит нам о параметреversion функции DATABASEPROPERTY вот какую вещь: Указано только в ознакомительных целях. Не поддерживается. Совместимость с будущими версиями не гарантируется.
То есть особого доверия этому результату нет. Сегодня все работает, а завтра? Гораздо более надежным, а потому предпочитаемым автором данных строк, является метод основанный на том факте, что пометка о номере версии базы вносится на загрузочную страницу ( boot page ) этой самой базы. Формат именно этой страницы меняется очень не часто, а ее местоположение в mdf-файле не менялось уже "тыщу лет" - это непременно девятая страница в первичной файловой группе. Но что бы воспользоваться этим надежным способом нам надо прибегнуть к небольшому "хаку", а именно нам потребуются услуги недокументированной команды DBCC PAGE. Стартовую информацию по ее применению можно почерпнуть из части второй, статьи "Как перестать называть журнал транзакций SQL Server лог-файлом и прекратить борьбу за его размер". А в нашем примере достаточно исполнить такую пару команд:
Мы получим довольно-таки внушительный отчет, но нас будет интересовать небольшой блок данных из второй части отчета, сразу за дампом двоичных данных. Этот блок даже имеет собственное имя - DBINFO, и вполне четко выделен в отчете. Говоря технически, DBINFO есть ни что иное как программная структура, несущая в своих полях массу ценной информации по каждой базе данных. В рамках обсуждаемого вопроса нас будут интересовать всего два поля этого блока/структуры. Вот как он выглядит на машине автора: ... DBINFO @0x0000000014A9A060 dbi_dbid = 15 dbi_status = 65544 dbi_nextid = 2121058592 Интересующие нас поля: dbi_createVersion (в левой колонке) и dbi_version (в правой). В данном случае, как видите, значения этих полей равны между собой и равны тому значению, что вернула нам функция DatabaseProperty. Однако в общем случае значения обсуждаемых полей могут и различаться, и в заключительном разделе статьи мы обсудим такой случай. Пока же зафиксируем вывод: Узнать версию подключенной базы надежнее через просмотр ее девятой ( boot ) страницы командой DBCC PAGE. Далее - что если у нас резервная копия и нам нужно узнать номер версии базы в ней содержащийся? Тут, можно сказать, дело едва ли не более простое чем в случае только что разобранном - заголовок резервной копии содержит всю необходимую информацию, нужно лишь ее извлечь. Для начала сделаем саму резервную копию:
А теперь - извлекаем искомое, не пытаясь, разумеется, восстановить базу:
Получаем очень "широкий" резалт-сет из одной строки, нас интересует всего одна колонка: DatabaseVersion 661 Насколько известно автору заголовки резервных копий созданных SQL сервером умышленно поддерживаются в обратно-совместимом состоянии с тем, что бы принеся .bak-файл с сервера 2012-го на сервер 2000-й (или же наоборот, бэкап сделали на 2000-м и пришли с ним на 2012-й) вы, как минимум, смогли увидеть вот эту самую информацию и сделать вывод о совместимости базы данных с текущим сервером. Если такой вывод будет отрицательным вы хотя бы сэкономите время не пытаясь инициализировать процесс восстановления абсолютно бесполезной (для данного конкретного сервера) базы данных. Напомню, что мы с вами тот же самый вопрос совместимости рассмотрим в заключительной части текущей статьи. Наконец - случай самый сложный: просто mdf-файл. Как узнать версию? Заголовка резервной копии у нас, понятно, нет, база в настоящий момент не подключена... Думаете - просто попробовать подключить базу? Вариант. Но - не идеальный, как минимум. Во-первых, нас могут ожидать сообщения об ошибках из-за несовместимости базы и сервера, что, конечно, переживаемо, хоть и неприятно. Но так мы хотя бы требуемый номер версии узнаем из текста ошибки, если, конечно, сообщение будет "вменяемым". Однако есть куда как более серьезное во-вторых: таким неподготовленным подключением мы можем... испортить базу! Сразу оговорюсь: в данном контексте "испортить" не равно "начисто сломать", после чего базу можно только выкинуть. Нет, после такой "порчи" база, в общем и целом, будет рабочей и все же, в определенном смысле - испорченной. Непонятно? Читайте далее, как обычно все встанет на свои места в заключительном разделе.
Ссылки по теме
|
|