Быстрая локализация проблем производительности Microsoft SQL Server в Quest Foglight



    В прошлой статье об инструменте для мониторинга Foglight for Databases мы рассказывали о возможностях контроля из единого интерфейса SQL Server, Oracle, PostgreSQL, MySQL, SAP ASE, DB2, Cassandra и MongoDB. Сегодня разберём подходы к быстрому выявлению причин нештатной работы Microsoft SQL Server:

    • Поиск источника блокировки;
    • Сравнение настроек БД «было-стало» с привязкой к метрикам производительности;
    • Поиск изменений в структуре БД, из-за которых снизилась производительность.

    Подробности под катом.

    Foglight for Databases — инструмент мониторинга за производительностью и изменениями в популярных базах данных. Если вы не знакомы с этим продуктом — рекомендуем прочитать предыдущую статью. А ниже мы привели скриншоты из интерфейса для демонстрации возможностей Foglight и простоты поиска проблем в БД.

    Поиск источника блокировки


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

    image

    Дежурный администратор, который уже получил уведомление, переходит в представление SQL PI (Performance Investigator). В столбце Workload заметно красное поле, которое означает ненулевое значение параметра Lock Wait.

    image

    После клика по графику Workload открывается детальное представление источников нагрузки на БД, а в столбце слева меню для проведения многомерного анализа производительности. Здесь, как и на скриншоте выше видно, что блокировка вызывает большую утилизацию ресурсов. В меню слева есть специальное представление Locked Objects, в котором и обнаружится заблокированный объект.

    image

    В Locked Objects хранятся заблокированные объекты. В правой части экрана причины блокировок: длительность, с какого сервера (или рабочей станции), какой программой, от какого пользователя и исполняемый объект, который привёл к блокировке.

    image

    При переходе на исполняемый объект, откроется новое представление с возможностью просмотра содержимого этого объекта. И после нажатия на View Batch Text откроется исполненный код.

    image

    Ускорение времени диагностики — залог успешной работы команды ИТ.

    Сравнение настроек БД «было-стало»


    К драматическому снижению производительности могут также приводить изменения, произведенные разработчиками или администраторами БД. Но в момент проблемы неважно кто это сделал — важно что произошло. С этим и попробуем разобраться. Открываем контекстное меню проблемного экземпляра БД.

    image

    В открывшемся меню нужно перейти на SQL PI (Performance Investigator), чтобы открыть представление с многомерным анализом.

    image

    Перейдём на представление Baseline для оценки поведения метрики в сравнении с её обычными значениями.

    image

    На графике видно, что после 13:40 начался аномальный рост потребления ресурсов.

    image

    В это представлении настроим что с чем сравнивать. Сейчас рассмотрим сравнение метрики самой с собой (по базовой линии), т.к. выше выявили аномальное отклонение. Вообще, можно также сравнить производительность и с другим экземпляром БД.

    image

    После выбора объектов для сравнения появится заветная кнопка Compare.

    image

    На среднем представлении видно, что аномальные значения наблюдались по метрикам: Active Time, Executions и Logins Rate. Начнём новое сравнение для выявления изменений.

    image

    Сравним значения метрик с самими собой, но день назад.

    image

    После выбора настроек, появится кнопка Compare, на которую нужно нажать.

    image

    Появится представление, на котором есть измерения для сравнения. Для демонстрации мы выберем пункт меню Programs. В разделе Statistics уже виден двукратный рост значения метрики Executions.

    image

    Слева и справа от шкалы в разделе меню Programs отображаются значения метрик. Здесь видим, что Active Time и Executions выросли почти в два раза, а это повод для проведения детального разбора ситуации.

    image

    Таким же образом можно проводить сравнительный анализ и по другим метрикам, а любое представление выгрузить в PDF-отчёт.

    Поиск изменений в структуре БД


    Изменения индексов, execution plans и других объектов может носить недокументированный характер. Разработчик или администратор БД вносит, казалось бы, незначительные изменения, о которых через некоторое время может забыть. В интерфейсе Foglight for Databases изменения конфигурации привязываются к изменениям производительности. Для выявления изменений переходим с главного экрана мониторинга БД на представление Workload.

    image

    Допустим, нам известно, что с какой-то клиентской машины генерируется большая нагрузка на БД. Раскрываем в представлении слева Client Machines.

    image

    Batches отсортированы в соответствии с создаваемой нагрузкой на БД. Перейдём на первый объект в списке и далее посмотрим изменения по нему (Change Tracking).

    image

    На графике, согласно легенде справа, отмечены соответствующие изменения за выбранный период. Первое изменение здесь — удаление индекса, второе — добавление нового execution plan. Как видно, после удаления индекса резко возросла нагрузка Other Wait — фиолетовая зона (к ней также относится выполнения batch job). Четвертое изменение — увеличение значения уровня параллелизма, что потенциально привело к повышение количества запросов (IO Wait — голубая зона). Рассмотрим последствия добавления нового execution Plan.

    image

    После перехода открылись детали нового execution plan. Теперь сравним произошедшие изменения.

    image

    После перехода открылись детали нового execution plan.

    image

    Этот же execution plan можно открыть в Management Studio прямо из интерфейса Quest Foglight.

    image

    Так он выглядит в консоли Management Studio.

    image

    При переходе на представление History можно увидеть изменения метрик во времени.

    image

    Представление History можно использовать для оценки влияния изменений на ту или иную метрику. Далее переходим на представление Other.

    image

    На этом представлении видно какие batches повлияли на нагрузку БД. Они уже отсортированы в порядке убывания.

    image

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

    Если вам понравился Foglight for Databases и вы хотели бы его попробовать на своих БД — оставьте заявку на получение дистрибутивов и триального ключа в форме обратной связи на нашем сайте. Стабильной работы баз данных и быстрой локализации нештатной работы!
    Gals Software
    Компания
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 2

      0

      Требуются ли права sa для работы утилиты, ну или иначе: какие нужны права для работы этой утилиты?

        0
        Права sa нужны только для создания специального пользователя для мониторинга и его объектов. Под спойлером скрипт. Однако, если используется технология mirroring, без прав dba не обойтись.

        Скрипт создания пользователя foglight для SQL Server
        use master;
        Declare	@LoginName				NVARCHAR(256) ,
        		@DBName					NVARCHAR(256) ,
        		@GrantSSISPermissions   bit,
        		@SQLStatement			NVARCHAR(4000);
        
        Select	@LoginName = ?, 			--	Please type the login name to be used for logging-in to SQL Server by the cartridge.
        		@GrantSSISPermissions = ?;  --  The input value for @GrantSSISPermissions should be 0 or 1. (1 - means that user has the SSIS permissions and 0 - means that user doesn't have the SSIS permissions.)
        
        If ( REPLACE ( CONVERT ( VARCHAR(2) , ServerProperty ( 'ProductVersion' ) ) , '.' , '' ) < 9 )
        Begin
        		--	Adding the sysadmin permissions
        
        		If Not Exists (	Select	*
        						From	[master].dbo.spt_values As spv, [master].dbo.sysxlogins As lgn
        						Where	spv.name = 'sysadmin'
        						And		lgn.[name] = @LoginName
        						And		spv.low = 0
        						And		spv.[type] = 'SRV'
        						And		lgn.srvid Is Null
        						And		spv.number & lgn.xstatus = spv.number )
        		Begin
        				Execute	[master].dbo.sp_addsrvrolemember	@LoginName , N'sysadmin';
        		End
        End
        Else
        Begin
        		If Not Exists	(	Select	*
        							From	sys.server_principals As A INNER JOIN sys.server_role_members As B
        									ON		A.principal_id = B.member_principal_id
        									INNER JOIN sys.server_principals As C
        									ON		B.role_principal_id = C.principal_id
        							Where	A.[name] = @LoginName
        							And		C.[name] = N'sysadmin' )
        		Begin
        				--	Granting Server permissions
        				use master;
        				If Not Exists (	Select	*
        								From	sys.server_principals As A INNER JOIN sys.server_permissions As B
        										ON		A.principal_id = B.grantee_principal_id
        								Where	A.[type] In ( 'S' , 'U' , 'G' , 'C' , 'K' )
        								And		A.[name] = @LoginName
        								And		B.permission_name = N'VIEW ANY DEFINITION'
        								And		B.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'GRANT VIEW ANY DEFINITION TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				If Not Exists (	Select	*
        								From	sys.server_principals As A INNER JOIN sys.server_permissions As B
        										ON		A.principal_id = B.grantee_principal_id
        								Where	A.[type] In ( 'S' , 'U' , 'G' , 'C' , 'K' )
        								And		A.[name] = @LoginName
        								And		B.permission_name = N'VIEW SERVER STATE'
        								And		B.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'GRANT VIEW SERVER STATE TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				--	Creating the user in each DB
        
        				Select	@DBName = N'';
        
        				While Exists (	Select	*
        								From	[master].sys.databases
        								Where	[name] > @DBName
        								And		HAS_DBACCESS ( [name] ) = 1
        								And		[state] = 0
        								And		is_read_only = 0 )
        				Begin
        						Select	@DBName = MIN ( [name] )
        						From	[master].sys.databases
        						Where	[name] > @DBName
        						And		HAS_DBACCESS ( [name] ) = 1
        						And		[state] = 0
        						And		is_read_only = 0;
        
        						Select	@SQLStatement = N'USE	[' + @DBName + N']
        												  If Not Exists (	Select	*
        																	From	[master].sys.server_principals As A INNER JOIN sys.database_principals As B
        																			ON		A.[sid] = B.[sid]
        																	Where	A.[name] = N''' + @LoginName + N''' )
        												  Begin try
        														CREATE USER [' + @LoginName + N'];
        												  End try
        												  begin catch
        												  end catch';
        
        												  --print @SQLStatement;
        
        						Execute	( @SQLStatement );
        				End
        
        				--	Granting EXECUTE Permissions on master
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN [master].sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN [master].sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN [master].sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'xp_enumerrorlogs'
        								And		C.[type] = 'EX'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[master]
        												GRANT EXECUTE ON [master].dbo.xp_enumerrorlogs TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN [master].sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN [master].sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN [master].sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'xp_readerrorlog'
        								And		C.[type] = 'EX'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[master]
        												GRANT EXECUTE ON [master].dbo.xp_readerrorlog TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
                 --	Granting EXECUTE Permissions on msdb
        
                  If Not Exists (	Select	*
                          From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
                              ON		A.[sid] = B.[sid]
                              INNER JOIN msdb.sys.database_permissions As C
                              ON		B.[principal_id] = C.[grantee_principal_id]
                              INNER JOIN msdb.sys.all_objects As D
                              ON		C.[major_id] = D.[object_id]
                          Where	A.[name] = @LoginName
                          And		D.[name] = N'agent_datetime'
                          And		C.[type] = 'EX'
                          And		C.[state] In ( 'G' , 'W' ) )
                  Begin
                      Select	@SQLStatement = N'USE	[msdb]
                                  GRANT EXECUTE ON msdb.dbo.agent_datetime TO [' + @LoginName + N'];';
        
                      Execute	( @SQLStatement );
                  End
        
        				--	Granting SELECT Permissions on msdb
        
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'log_shipping_monitor_primary'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.log_shipping_monitor_primary TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'log_shipping_monitor_secondary'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.log_shipping_monitor_secondary TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        	
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'log_shipping_primaries'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.log_shipping_primaries TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'log_shipping_secondaries'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.log_shipping_secondaries TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'log_shipping_primary_secondaries'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.log_shipping_primary_secondaries TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'sysalerts'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.sysalerts TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        	
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'syscategories'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.syscategories TO [' + @LoginName + N'];';
        						
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'sysjobactivity'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.sysjobactivity TO [' + @LoginName + N'];';
        						
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        	
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'sysjobs'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.sysjobs TO [' + @LoginName + N'];';
        
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				If Not Exists (	Select	*
        								From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        										ON		A.[sid] = B.[sid]
        										INNER JOIN msdb.sys.database_permissions As C
        										ON		B.[principal_id] = C.[grantee_principal_id]
        										INNER JOIN msdb.sys.all_objects As D
        										ON		C.[major_id] = D.[object_id]
        								Where	A.[name] = @LoginName
        								And		D.[name] = N'sysjobhistory'
        								And		C.[type] = 'SL'
        								And		C.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.sysjobhistory TO [' + @LoginName + N'];';
        						
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        
        				If ( Not Exists (	Select	*
        									From	[master].sys.server_principals As A INNER JOIN msdb.sys.database_principals As B
        											ON		A.[sid] = B.[sid]
        											INNER JOIN msdb.sys.database_permissions As C
        											ON		B.[principal_id] = C.[grantee_principal_id]
        											INNER JOIN msdb.sys.all_objects As D
        											ON		C.[major_id] = D.[object_id]
        									Where	A.[name] = @LoginName
        									And		D.[name] = N'dbm_monitor_data'
        									And		C.[type] = 'SL'
        									And		C.[state] In ( 'G' , 'W' ) )
        					And Exists (	Select	*
        									From	msdb.sys.all_objects
        									Where	[name] = N'dbm_monitor_data' )
        					And		REPLACE ( CONVERT ( VARCHAR(2) , ServerProperty ( 'ProductVersion' ) ) , '.' , '' ) = 9 )
        				Begin
        						Select	@SQLStatement = N'USE	[msdb]
        												GRANT SELECT ON msdb.dbo.dbm_monitor_data TO [' + @LoginName + N'];';
        						
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				--	Adding the db_datareader permissions
        
        				Select	@DBName = N'';
        
        				While Exists (	Select	*
        								From	[master].sys.databases
        								Where	[name] > @DBName
        								And		HAS_DBACCESS ( [name] ) = 1
        								And		[state] = 0
        								And		is_read_only = 0 )
        				Begin
        						Select	@DBName = MIN ( [name] )
        						From	[master].sys.databases
        						Where	[name] > @DBName
        						And		HAS_DBACCESS ( [name] ) = 1
        						And		[state] = 0
        						And		is_read_only = 0;
        
        						Select	@SQLStatement = N'USE	[' + @DBName + N']
        												If Not Exists (	Select	*
        																From	[master].sys.server_principals As A INNER JOIN sys.database_principals As B
        																		ON		A.[sid] = B.[sid]
        																		INNER JOIN sys.database_role_members As C
        																		ON		B.principal_id = C.member_principal_id
        																		INNER JOIN sys.database_principals As D
        																		ON		C.role_principal_id = D.principal_id
        																Where	A.[name] = N''' + @LoginName + N'''
        																And		D.[name] = N''db_datareader'' )
        												Begin
        														Execute	sp_addrolemember N''db_datareader'' , N''' + @LoginName + N''';
        												End';
        
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        			
        
        				--	Adding the replmonitor permissions on all distribution databases
        				Select	@DBName = N'';
        				While (	Exists (	Select	name
        									From	[master].sys.databases
        									Where	[name] > @DBName 
        									And		is_distributor = 1 
        									and has_dbaccess(name) = 1))
        				Begin
        
        						Select	@DBName = MIN ( [name] )
        						From	[master].sys.databases
        						Where	[name] > @DBName 
        						And		is_distributor = 1 
        						And		has_dbaccess(name) = 1;
        
        						Select	@SQLStatement = N'USE	[' + @DBName + N']
        												Begin
        														Execute	sp_addrolemember N''replmonitor'' , N''' + @LoginName + N''';
        											End';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );												
        						
        				End
        								
        				--	Adding the db_ddladmin permissions
        
        				Select	@DBName = N'';
        
        				While Exists (	Select	*
        								From	[master].sys.databases
        								Where	[name] > @DBName
        								And		HAS_DBACCESS ( [name] ) = 1
        								And		[state] = 0
        								And		is_read_only = 0 )
        				Begin
        						Select	@DBName = MIN ( [name] )
        						From	[master].sys.databases
        						Where	[name] > @DBName
        						And		HAS_DBACCESS ( [name] ) = 1
        						And		[state] = 0
        						And		is_read_only = 0;
        
        						Select	@SQLStatement = N'USE	[' + @DBName + N']
        												If Not Exists (	Select	*
        																From	[master].sys.server_principals As A INNER JOIN sys.database_principals As B
        																		ON		A.[sid] = B.[sid]
        																		INNER JOIN sys.database_role_members As C
        																		ON		B.principal_id = C.member_principal_id
        																		INNER JOIN sys.database_principals As D
        																		ON		C.role_principal_id = D.principal_id
        																Where	A.[name] = N''' + @LoginName + N'''
        																And		D.[name] = N''db_ddladmin'' )
        												Begin
        														Execute	sp_addrolemember N''db_ddladmin'' , N''' + @LoginName + N''';
        												End';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        
        				--	Granting trace permissions
        
        				If Not Exists (	Select	*
        								From	sys.server_principals As A INNER JOIN sys.server_permissions As B
        										ON		A.principal_id = B.grantee_principal_id
        								Where	A.[type] In ( 'S' , 'U' , 'G' , 'C' , 'K' )
        								And		A.[name] = @LoginName
        								And		B.permission_name = N'ALTER TRACE'
        								And		B.[state] In ( 'G' , 'W' ) )
        				Begin
        						Select	@SQLStatement = N'use master;GRANT ALTER TRACE TO [' + @LoginName + N'];';
        						--print @SQLStatement;
        						Execute	( @SQLStatement );
        				End
        		End
        End
        
        --Role needed to inspect mirroring
        
        if (select count(*) from msdb.sys.database_principals where name='dbm_monitor') = 1
        begin
        	if (select count(*) from msdb.sys.database_principals where name=@LoginName) = 0
        	begin
        		set @SQLStatement=N'USE [msdb]
        							If Not Exists (	Select	*
        											From	[master].sys.server_principals As A INNER JOIN sys.database_principals As B
        													ON		A.[sid] = B.[sid]
        											Where	A.[name] = N''' + @LoginName + N''' )
        							Begin try
        								CREATE USER [' + @LoginName + N'];
        							End try
        							begin catch
        							end catch';
        	--print @SQLStatement;
        	exec (@SQLStatement);
        	end
        	if (select count(*) from msdb.sys.database_principals where name=@LoginName) = 1
        	begin 
        		If ( REPLACE ( CONVERT ( VARCHAR(2) , ServerProperty ( 'ProductVersion' ) ) , '.' , '' ) < 11 )
        			exec msdb..sp_addrolemember 'dbm_monitor', @LoginName
        		else
        		set @SQLStatement=N'USE [msdb]
        					ALTER ROLE [dbm_monitor] ADD MEMBER ['+@LoginName+N']';
        		 --print @SQLStatement;
        	exec (@SQLStatement);
        	end
        end
        
        if (select count(*) from sys.databases where name='SSISDB') = 1 and @GrantSSISPermissions = 1
        Begin
        		If Not Exists	(	Select	*
        							From	sys.server_principals As A INNER JOIN sys.server_role_members As B
        									ON		A.principal_id = B.member_principal_id
        									INNER JOIN sys.server_principals As C
        									ON		B.role_principal_id = C.principal_id
        							Where	A.[name] = @LoginName
        							And		C.[name] = N'sysadmin' )
        		Begin
        			--Granting SSIS permissions
        
        		
        			set @SQLStatement=N'USE [SSISDB]
        														  If Not Exists (	Select	*
        																		From	[master].sys.server_principals As A INNER JOIN sys.database_principals As B
        																				ON		A.[sid] = B.[sid]
        																		Where	A.[name] = N''' + @LoginName + N''' )
        													  Begin try
        															CREATE USER [' + @LoginName + N'];
        													  End try begin catch end catch;
        													  Begin try
        													  ALTER ROLE  [ssis_admin] ADD MEMBER [' + @LoginName + N'];
        													  End try begin catch end catch;
        						';
        						--print @SQLStatement;
        						exec (@SQLStatement);
                 End
        
        End
        
        

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.