Fala pessoal!
Nesse artigo eu gostaria de compartilhar uma situaĂ§Ă£o que ocorreu durante um atendimento a um cliente onde eu trabalho, ou seja, mais um caso real do dia a dia. Tivemos uma ocorrĂªncia de database que entrou no modo suspect (nada a ver com esse post) e quando fui analisar o log do SQL Server para procurar mais informações sobre a base que ficou marcada como suspect, vi um monte de ocorrĂªncias de erro com a seguinte mensagem:
The activated proc ‘[dbo].[sp_syspolicy_events_reader]’ running on queue ‘msdb.dbo.syspolicy_event_queue’ output the following: ‘Cannot execute as the database principal because the principal “##MS_PolicyEventProcessingLogin##” does not exist, this type of principal cannot be impersonated, or you do not have permission.’
Entendendo o problema
Analisando a mensagem de erro, podemos ver que provavelmente isso se trata de problema de permissĂ£o ou o usuĂ¡rio padrĂ£o de sistema “##MS_PolicyEventProcessingLogin##” estĂ¡ Ă³rfĂ£o. Como expliquei em mais detalhes no artigo Identificando e resolvendo problemas de usuĂ¡rios Ă³rfĂ£os no SQL Server com a sp_change_users_login, um usuĂ¡rio fica “Ă³rfĂ£o” quando ele perde a associaĂ§Ă£o entre o login da instĂ¢ncia e o usuĂ¡rio do banco, geralmente apĂ³s processos de BACKUP/RESTORE ou quando o login de um usuĂ¡rio Ă© excluĂdo.
O login ##MS_PolicyEventProcessingLogin## vem instalado por padrĂ£o no SQL Server (desativado), responsĂ¡vel por algumas tarefas internas na instĂ¢ncia, como a leitura de eventos do Service Broker e gerenciamento de policies.
Como podemos observar nas permissões desse usuĂ¡rio, ele possui acesso de EXECUTE na Stored Procedure sp_syspolicy_events_reader:
Se tentarmos executar esse Stored Procedure como o usuĂ¡rio ##MS_PolicyEventProcessingLogin##, atravĂ©s de um mĂ©todo de IMPERSONATE (Para saber mais sobre IMPERSONATE, acesse este post), vemos a seguinte mensagem de erro:
1 2 3 4 5 |
USE [msdb] GO EXECUTE AS USER = '##MS_PolicyEventProcessingLogin##' GO |
Msg 15517, Level 16, State 1, Line 1
Cannot execute as the database principal because the principal “##MS_PolicyEventProcessingLogin##” does not exist, this type of principal cannot be impersonated, or you do not have permission.
Que Ă© exatamente a mensagem de erro que estamos lidando. Hummm..
Essas mensagens de erro no log do SQL Server geralmente sĂ£o geradas em instĂ¢ncias que utilizam o Service Broker para troca de mensagens (especialmente quando existem MUITOS registros de erro frequentemente) apĂ³s algum processo de BACKUP/RESTORE do database msdb.
Caso a sua instĂ¢ncia nĂ£o utilize o Service Broker, mesmo que esse usuĂ¡rio fique Ă³rfĂ£o, provavelmente vocĂª nĂ£o perceba esse problema.
Identificando o problema
Conforme jĂ¡ expliquei no artigo Identificando e resolvendo problemas de usuĂ¡rios Ă³rfĂ£os no SQL Server com a sp_change_users_login, para identificar se o usuĂ¡rio ##MS_PolicyEventProcessingLogin## estĂ¡ Ă³rfĂ£o, podemos utilizar a query abaixo:
1 2 3 4 5 6 7 8 9 |
SELECT A.[name] AS UserName, A.[sid] AS UserSID FROM msdb.sys.database_principals A WITH(NOLOCK) LEFT JOIN sys.sql_logins B WITH(NOLOCK) ON A.[sid] = B.[sid] WHERE B.[sid] IS NULL AND A.[name] = '##MS_PolicyEventProcessingLogin##' |
Se a query retornar alguma linha, Ă© porque o usuĂ¡rio ##MS_PolicyEventProcessingLogin## estĂ¡ Ă³rfĂ£o e precisaremos corrigir esse problema, associando o usuĂ¡rio do database msdb ao login correspondente.
Simulando o problema
Caso vocĂª queira testar e/ou simular esse problema em seu ambiente, basta ativar o Service Broker (ative o Database Mail, por exemplo) e execute os comandos abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
USE [master] GO CREATE LOGIN [teste] WITH PASSWORD = 'teste123', CHECK_EXPIRATION = OFF, CHECK_POLICY = OFF GO USE [msdb] GO ALTER USER [##MS_PolicyEventProcessingLogin##] WITH LOGIN = [teste] GO DROP LOGIN [teste] GO EXECUTE AS USER = '##MS_PolicyEventProcessingLogin##' GO EXEC dbo.sp_syspolicy_events_reader GO REVERT GO |
ApĂ³s alguns minutos, o seu log do SQL Server provavelmente jĂ¡ estarĂ¡ assim:
Corrigindo o problema
Agora que entendemos a situaĂ§Ă£o que estĂ¡ ocorrendo e identificamos que esses erros gerados no log do SQL Server sĂ£o devidos ao usuĂ¡rio ##MS_PolicyEventProcessingLogin## estar Ă³rfĂ£o, vamos corrigir esse problema.
Para isso, basta associar o login ao usuĂ¡rio, com o comando abaixo:
1 2 3 4 5 |
USE [msdb] GO ALTER USER [##MS_PolicyEventProcessingLogin##] WITH LOGIN = [##MS_PolicyEventProcessingLogin##] GO |
VocĂª tambĂ©m pode utilizar a sp_change_users_login para corrigir os usuĂ¡rios Ă³rfĂ£os:
1 2 3 4 5 |
USE [msdb] GO sys.sp_change_users_login 'Auto_Fix', '##MS_PolicyEventProcessingLogin##' GO |
Resultado:
The row for user ‘##MS_PolicyEventProcessingLogin##’ will be fixed by updating its login link to a login already in existence.
The number of orphaned users fixed by updating users was 1.
The number of orphaned users fixed by adding new logins and then updating users was 0.
ObservaĂ§Ă£o: Prefiro utilizar o ALTER USER, pois a sp_change_users_login estĂ¡ marcada como deprecated e pode ser removida em versões futuras do SQL Server.
ApĂ³s realizar essas alterações, as mensagens devem ter parado de ocorrer no log do SQL Server. Como sou teimoso, quero me certificar que estĂ¡ realmente funcionando ao invĂ©s de esperar pararem as mensagens de erro:
Agora sim, fiquei tranquilo. đŸ™‚
Espero que tenham gostado desse artigo e atĂ© a prĂ³xima!
Grande abraço!
Obrigado. Me ajudou!