Temos um banco de dados SQL Server que possui uma especificação de auditoria de banco de dados que audita todas as ações de execução no banco de dados.
CREATE DATABASE AUDIT SPECIFICATION [dbAudit]
FOR SERVER AUDIT [servAudit]
ADD (EXECUTE ON DATABASE::[DatabaseName] BY [public])
Descobrimos que algumas consultas gravam no log de auditoria o uso de uma função escalar para cada linha de um conjunto de resultados. Quando isso acontece, o registro é preenchido antes que possamos colocá-lo em ETL em seu local de descanso final e temos uma lacuna em nosso registro.
Infelizmente, devido a motivos de conformidade, não podemos simplesmente parar de auditar todas as EXECUTE
declarações.
Nosso primeiro pensamento para abordar esse problema é usar a WHERE
cláusula na Auditoria do Servidor para filtrar a atividade. O código ficou assim:
WHERE [object_id] not in (Select object_id from sys.objects where type = 'FN' )
Infelizmente, o SQL Server não permite o operador IN relacional (provavelmente porque não deseja consultar toda vez que precisar gravar no log de auditoria).
Gostaríamos de evitar escrever um processo armazenado que codifique a cláusula object_id
na WHERE
cláusula, mas esse é o nosso pensamento atual sobre a melhor maneira de abordar esse problema. Existe uma abordagem alternativa que devemos considerar?
Percebemos que, quando a função escalar está em uso em um CTE recursivo, ela faz com que a consulta grave no log de auditoria de todas as linhas do conjunto de resultados.
Existem algumas funções avaliadas escalares que são entregues por um fornecedor que não podemos excluir ou mover para um banco de dados alternativo.
We've found that some queries will write to the audit log the use of a scalar function for every row in a result set.
- Esse é um dos efeitos colaterais mais magníficos das UDFs escalares que eu já ouvi e ouvi muito.Respostas:
Existem algumas opções que consegui trabalhar. Todas as opções lidam com variações de predicados de filtro. NOTA: você deve desativar o Audit Server, a fim de fazer alterações e, em seguida, re- habilitar -lo.
Primeiro, a abordagem mais genérica é filtrar todas as UDFs escalares. Você pode fazer isso usando o
class_type
campo de auditoria. A documentação indica que esse campo éVARCHAR(2)
, mas não permite especificar uma sequência. No entanto, consegui o seguinte para trabalhar:(mais informações sobre essa investigação aqui: Server Audit Mystery: Filtering class_type obtém a mensagem de erro 25713 )
A próxima abordagem mais genérica não é uma opção, pois foi declarado que este é um banco de dados fornecido pelo fornecedor e, portanto, nenhuma alteração pode ser feita. Então eu vou cobrir isso por último.
A abordagem menos genérica (mas definitivamente funciona) é filtrar o nome da função específica:
Ou, se vários nomes:
Embora não seja muito genérica, essa abordagem deve ser adequada, pois o número de funções a serem filtradas deve ser bastante pequeno e não será muito frequente a introdução de novas funções.
Finalmente, para outras pessoas que enfrentam essa situação e não estão impedidas de fazer alterações: você pode colocar funções em seu próprio esquema e filtrar apenas esse esquema. Isso é mais genérico do que filtrar as funções individualmente. Supondo que você crie um esquema nomeado
fn
e coloque as funções nele:TAMBÉM, com relação aos dois comentários a seguir na pergunta:
e:
O
IN
operador não é o problema. É verdade que não é suportado, mas é apenas uma abreviação de uma lista deOR
condições. O problema real é o uso do T-SQL. Somente literais - strings ou números - são permitidos. Portanto, você não seria capaz de executar um Procedimento Armazenado de qualquer maneira. Nem você pode usar as funções internas.fonte
=
para estar<>
na minha resposta. Eu também só testei e funciona como anunciado :-)