Нельзя выполнять динамические административные представления (DMV) в режиме совместимости 80.
ЛОЖЬ
Для начала, существует большая путаница относительно того, что означает режим совместимости. Означает ли это, что базу данных можно восстановить/присоединить к серверу SQL Server 2000? Нет. Это означает, что некоторые аспекты синтаксического разбора T-SQL, поведения планов запросов, подсказки и некоторые другие вещи ведут себя так же, как в SQL Server 2000 (или 2005, если вы устанавливаете значение 90 на экземпляре 2008).
В SQL Server 2008 вы можете использовать ALTER DATABASE SET COMPATIBILITY_LEVEL для изменения уровня совместимости; в предыдущих версиях используется sp_dbcmptlevel. Чтобы увидеть, что контролирует уровень совместимости, обратитесь к статье электронной документации Уровень совместимости инструкции ALTER DATABASE (Transact-SQL).
Уровень совместимости не влияет на физическую версию базы данных — именно она повышается при обновлении и предотвращает восстановление/присоединение базы данных к предыдущей версии, поскольку у них есть максимальная физическая версия, которую они могут понять. См. мою статью в блоге Search Engine Q&A #13: Difference between database version and database compatibility level для получения более подробной информации, а также Msg 602, Level 21, State 50, Line 1 для получения подробной информации о сообщениях об ошибках, которые вы получаете при попытке присоединить/восстановить базу данных в предыдущей версии.
Но я отвлёкся, как обычно :-)
Одна из вещей, которая выглядит так, будто не работает, — это использование DMV в режиме совместимости 80. Вот простой скрипт для демонстрации с использованием SQL Server 2005:
CREATE DATABASE [DMVTest];
GO
USE [DMVTest];
GO
CREATE TABLE [t1] ([c1] INT);
CREATE CLUSTERED INDEX [t1c1] on [t1] ([c1]);
INSERT INTO [t1] VALUES (1);
GO
EXEC sp_dbcmptlevel DMVTest, 80;
GO
SELECT * FROM sys.dm_db_index_physical_stats (
DB_ID (N'DMVTest'), -- идентификатор базы данных
OBJECT_ID (N't1'), -- идентификатор объекта
NULL, -- идентификатор индекса
NULL, -- идентификатор секции
'DETAILED'); -- режим сканирования
GO
И действительно полезная ошибка, которую я получаю в ответ:
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near '('.
Насколько это невероятно полезно? Это точно указывает на проблему — нет.
Примечание: После написания этого я понял, что сам пал жертвой собственного мифа! DMV полностью поддерживаются в режиме совместимости 80. Что не поддерживается, так это вызов функции (например, OBJECT_ID) в качестве одного из параметров DMV. Спасибо Аарону Бертрану за указание на это!
Вот трюк с использованием функций в качестве параметров. Вы переключаете контекст на базу данных с уровнем совместимости 90 или выше — и затем вы можете направить DMV на базу данных с уровнем совместимости 80.
Очень круто. Проверьте:
USE [master];
GO
SELECT * FROM sys.dm_db_index_physical_stats (
DB_ID (N'DMVTest'),
OBJECT_ID (N'DMVTest..t1'),
NULL,
NULL,
'DETAILED');
GO
И это работает, даже если база данных DMVTest находится на 80-м уровне совместимости.
На что нужно обратить особое внимание — убедитесь, что вы используете правильный идентификатор объекта. Если бы я оставил второй параметр как OBJECT_ID ('t1'), он бы попытался найти идентификатор объекта таблицы t1 в базе данных master. Если он не найден, будет использовано значение NULL, что заставит DMV выполняться для всех таблиц в базе данных DMVTest. Если случайно в master есть таблица t1, её идентификатор объекта, скорее всего, отличается от идентификатора таблицы t1 в DMVTest, и тогда DMV завершится ошибкой.
И sys.dm_db_index_physical_stats — это не совсем DMV (динамическое административное представление); это динамическая административная функция, которая выполняет огромный объём работы для возврата результатов — поэтому вы хотите ограничить её только теми таблицами, которые вас интересуют. См. моей статье в блоге «Внутри sys.dm_db_index_physical_stats» для получения подробной информации о том, как она работает и насколько дорогостоящей может быть.
Итак, вам нужно использовать новую опцию трёхчастного имени в OBJECT_ID начиная с SQL Server 2005, чтобы убедиться, что вы захватываете правильный идентификатор объекта при переходе между контекстами баз данных.
Другой способ сделать это — использовать переменные и предварительно присвоить им значения, что можно сделать непосредственно из базы данных в режиме совместимости 80:
DECLARE @databaseID INT;
DECLARE @objectID INT;
SELECT @databaseID = DB_ID (N'DMVTest');
SELECT @objectID = OBJECT_ID (N't1');
SELECT * FROM sys.dm_db_index_physical_stats (
@dbid,
@objid,
NULL,
NULL,
'DETAILED');
GO
Суть: очередной миф повержен!

Комментариев нет:
Отправить комментарий