Отлов несовместностей после перехода на SQL Server 2008. 1-я серия

Будем считать, что мы благополучно перешли на SQL Server 2008, потому что сколько можно. Уже 2010-й год на дворе. После перехода бестолку ловить discontinued фичи в базах и скриптах, потому что все, что поленились заранее вычистить, проявится само. Оно попросту не будет работать. Придется исправлять в боевых условиях. Удачи и поменьше вам такого удовольствия, а мы сконцентрируемся на том, что называется deprecated и obsolete. В прошлогоднем посте, разбирая Upgrade Advisor, мы обнаружили, что не все инструкции такого типа он в состоянии отловить, и я обещал подогнать для этого более надежные инструменты. Одним из таких инструментов является обычный виндузовый Performance Monitor, точнее, счетчики категории SQL Server:Deprecated Features, которые SQL Server 2008 добавляет туда при своей установке. Их названия достаточно самоописательные. Например, экземпляр по имени Data types: text ntext or image означает, что где-то встретилось поле таблицы или переменная этих типов, которые надлежит переделать на varchar/nvarchar/varbinary(max) . Если сделать что-то вроде declare @t table (fld1 text, fld2 image), счетчик SQL Server:Deprecated Features\Data types: text ntext or image увеличится на 2, потому что за грех считается каждая несовместность (в данном случае - и text, и image), а не по строкам или операторам, в которых эти несовместности встретились. Откройте PerfMon и добавьте в сбор все экземпляры счетчиков категории SQL Server:Deprecated Features.

рис. 1

Счетчики обнуляются при рестарте SQL Server и прирастают всякий раз, когда встретится какая-либо несовместность. Перезапустите SQL Server для чистоты эксперимента и посмотрите, как резко упали в ноль все графики. А, черт. Остановите Reporting Service и еще раз перезапустите SQL Server. Запустите типовую нагрузку, которую вы хотите проверить на вшивость. В смысле, на deprecated функциональность. Я в качестве типовой нагрузки возьму вторую часть (Deprecated) Скрипта 1 из поста SQL Server 2008 Upgrade Advisor. Давайте выполнять его построчно

select databaseproperty('AdventureWorks_2005', 'Version') --будет заменена на  databasepropertyex 
exec sp_dboption @dbname = 'AdventureWorks_2005', @optname = 'trunc. log on chkpt.', @optvalue = 'true' --sp_dboption в целом заменяется командой alter database; в данном случае действие эквивалентно ALTER DATABASE ... SET RECOVERY SIMPLE 
select * from Production.Product with (fastfirstrow) -- хинт заменен на OPTION (FAST N) 
...

и смотреть, что происходит с графиками на PerfMon. Они, как и следовало ожидать, прирастают по мере происхождения несовместностей:

рис. 2

Собственно, PerfMon здесь нужен только для наглядности демонстрации. По-хорошему, все его счетчики можно собрать на стороне SQL Server - см. https://blogs.msdn.com/alexejs/archive/2009/07/12/perfmon-sql-server-1-2.aspx, https://blogs.msdn.com/alexejs/archive/2009/07/26/perfmon-sql-server-3-4.aspx. В данном случае, поскольку это SQL Serverные счетчики, можно прибегнуть к Способу №4, заюзав DMVшку sys.dm_os_performance_counters (бывшую sys.sysperfinfo, которая, кстати, нынче является deprecated J):

select * from sys.dm_os_performance_counters where object_name like '%deprecated%'

рис. 3

Например, посмотрим текущее показание счетчика несовместностей типа SQL Server:Deprecated Features\Data types: text ntext or image, выполним некоторый скрипт и снова проверим показания счетчика:

select * from sys.dm_os_performance_counters where instance_name = 'Data types: text ntext or image' 
go 
declare @t table (fld1 text, fld2 image) 
go 
select * from sys.dm_os_performance_counters where instance_name = 'Data types: text ntext or image'

рис. 4

Все прекрасно работает. Тем не менее, метод имеет, на мой взгляд, два недостатка. Первый - он смотрит в масштабах всего сервера. Нельзя ограничить проверку на конкретную базу или приложение. Например, выше нам пришлось стопить службу отчетности, чтобы она не вносила свое влияние в результат эксперимента. Второе - метод не позволяет ничего сказать про то, в каком месте базы или кода встретилась пойманная несовместность. Ставить select * from sys.dm_os_performance_counters where object_name like '%deprecated%' после каждой строчки кода нереально. В следующей серии мы посмотрим, как можно преодолеть эти недостатки.

Автор: Алексей Шуленин