Event Notification para kill

Algum tempo atras fiz um post sobre Event Notification para monitorar DeadLock o que funciona muito bem,,,

Com um pouco de modificação o mesmo código pode ser utilizado para muitas outras coisas,,, por exemplo: limitar acesso a uma instância bloqueando a conexão do usuário…

Aí você pensa: “posso fazer isso por trigger, por que fazer diferente?”

Eu respondo,,, se você trabalha em ambientes com alto volume de conexões, ou ambientes que as vezes sofrem com falta de recursos como cpu ou memória sabe que a trigger pode ser uma pedra no sapato,,, ao invés de respeitar o filtro e impedir apenas algumas conexões ela bloqueia tudo e todos…

Já com o Event Notification é o contrário,,, no pior cenário ele só para de funcionar…

Os dois pontos que vejo como mais complicados são:

  • Não é possível personalizar uma mensagem para o usuário que sofreu o kill
  • Dependendo do que você fizer, ele pode começar a encher o errorlog com mensagens de kill

com o código abaixo consegui chegar a 20.000 tentativas de conexão simultâneas e nenhuma conseguiu conectar,,,


--apenas para constatar quais tipos de eventos podemos tratar... o que queremos eh o audit_login
select * from sys.event_notification_event_types with (nolock)
where type_name like '%login%'
use master
go

alter database BASE_DE_ADMINISTRACAO_DO_DBA set enable_broker with rollback immediate
go

alter database BASE_DE_ADMINISTRACAO_DO_DBA set TRUSTWORTHY on
go

use BASE_DE_ADMINISTRACAO_DO_DBA
go

CREATE QUEUE [Login_Killer_Queue]
GO

CREATE SERVICE [Login_Killer_Service]
AUTHORIZATION [dbo]
ON QUEUE [dbo].[Login_Killer_QUEUE]
([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification])
GO
CREATE ROUTE Login_Killer_Route
WITH SERVICE_NAME = 'Login_Killer_Service',
ADDRESS = 'LOCAL';
GO
DECLARE @AuditServiceBrokerGuid [uniqueidentifier]
,@SQL [varchar](max);

-- Pega o service broker guid da base de dados
SELECT @AuditServiceBrokerGuid = [service_broker_guid]
FROM [master].[sys].[databases]
WHERE [name] = 'ADM_BDADOS'

-- Cria e executa o SQL dinamico para criar o objeto do evento de notificacao
SET @SQL = 'IF EXISTS (SELECT * FROM sys.server_event_notifications
WHERE name = ''Login_Killer_Notification'')

DROP EVENT NOTIFICATION Login_Killer_EventNotification ON SERVER

CREATE EVENT NOTIFICATION Login_Killer_EventNotification
ON SERVER
WITH fan_in
FOR AUDIT_LOGIN
TO SERVICE ''Login_Killer_Service'', '''
+ CAST(@AuditServiceBrokerGuid AS [varchar](50)) + ''';'
EXEC (@SQL)
GO
SELECT * FROM [sys].[server_event_notifications]

select * from sys.server_event_session_actions with (nolock)
CREATE TABLE [dbo].[DBA_FailedConnectionTracker](
[host_name] [varchar](128) NOT NULL,
[login_name] [varchar](128) NOT NULL,
[spidu] int,
[FailedLoginData] XML
) ;

CREATE PROCEDURE dbo.spc_DBA_FailedConnectionTracker
AS
BEGIN
SET NOCOUNT ON;
-- looping infinito
WHILE (1 = 1)
BEGIN
DECLARE @messageBody VARBINARY(MAX);
DECLARE @messageTypeName NVARCHAR(256);
WAITFOR (
RECEIVE TOP(1)
@messageTypeName = message_type_name,
@messageBody = message_body
FROM [Login_Killer_Queue]
), TIMEOUT 500
-- se nao houver mensagens saia
IF @@ROWCOUNT = 0
BEGIN
BREAK ;
END ;
-- se o tipo da mensagem for um EventNotification para a fila atual
IF (@messageTypeName = 'http://schemas.microsoft.com/SQL/Notifications/EventNotification')
BEGIN
DECLARE @XML XML,
@host_name varchar(128) ,
@login_name varchar(128) ,
@SPID varchar(5);

SELECT @XML=CONVERT(XML,@messageBody)
,@host_name = ''
,@login_name = ''
,@SPID ='';

-- Pega o SPID e as informacoes de login
SELECT @SPID = @XML.value('(/EVENT_INSTANCE/SPID)[1]', 'varchar(5)')
, @host_name = @XML.value('(/EVENT_INSTANCE/HostName)[1]', 'NVARCHAR(128)')
, @login_name = @XML.value('(/EVENT_INSTANCE/LoginName)[1]', 'NVARCHAR(128)')
;

DECLARE @kill varchar(8000) = '';
--Caso o hostname e o login entrem no criterio abaixo
if ((@host_name like 'SPO%') and (@login_name like '%_user'))
SELECT @kill = @kill + 'kill ' + @SPID + ';'
EXEC(@kill);

--/* esta parte pode ser comentada para não gerar "log" do kill
if ((@host_name like 'SPO%') and (@login_name like '%_user'))
INSERT INTO [dbo].[DBA_FailedConnectionTracker]
([host_name], [login_name], FailedLoginData,spidu)
values ( @host_name, @login_name,@XML,@SPID);
--*/
END;
END;
END;
--inicia a matanca

ALTER QUEUE [dbo].[Login_Killer_Queue]
WITH STATUS = on
,ACTIVATION (PROCEDURE_NAME = [spc_DBA_FailedConnectionTracker]
,STATUS = ON
,MAX_QUEUE_READERS = 1
,EXECUTE AS OWNER)
GO

Ativando um Windows trial

As vezes é legal voltar a trabalhar um pouco com outras coisas além de SQL Server,,,

Essa semana fiz uma consultoria em Active Directory,,,, Fui resolver alguns problemas de replicação e configurar um novo domain controler para replicação,,,

Até aí nenhum grande problema,,, o cliente já havia instalado o SO (Windows Server 2012R2),,, atualizei o SO, alteramos o nome, adicionando ao domínio,,, até aí tudo tranquilo,,,

O problema: o cliente havia instalado o SO na versão trial de 180 dias,,, quando tentamos registrar o Windows ele informava que o número de série não era compatível com a versão instalada,,,

Em contato com o time de suporte da MS eles informaram que a única opção era reinstalar o SO na versão correta,,, o que na teoria não estava errado,,, mas sempre tem um jeito,,,,

Caso você tenha instalado um SO trial e queira registra-lo como full faça o seguinte:

  1. Abra o prompt em modo elevado e digite  dism /online /get-targeteditions
  2. Ele vai te mostrar para quais versões você pode elevar a instalação atual,,,
  3. Tenha em mãos com o serial da versão que você quer usar
  4. Agora digite:  DISM /online /Set-Edition:ServerStandard /ProductKey:XXXXX-XXXXX-XXXXX-XXXXX-XXXXX /AcceptEula Onde neste caso a edição é para qual queremos registrar este SO e o xxxx é o número de série,,,
  5. Se você fez certo será apresentada uma mensagem de erro,,,, Error 87
  6. Você não tem como forçar um upgrade de versão usando um serial que nao seja de KMS,,, haha pegadinha do malandro,,,
  7. Entre nesse site https://technet.microsoft.com/en-us/library/jj612867.aspx e copie o serial correto para sua versão,,,
  8. Substitua o xxxxx por esse serial e agora sim vai funcionar,,, só que ele não avisa que vai reiniciar,,, provavelmente ele deve reiniciar umas 2x
  9. Após isso, você deve conseguir ativar seu Windows com onseu serial sem problemas,,,

Caso não funcione sempre tem a opção do backup, reinstalar certo dessa vez e restore,,,