Estou envolvido no gerenciamento de um aplicativo com um grande número de bancos de dados SQL Server 2014 e estou extraindo tamanhos de tabela e índice para rastrear a capacidade. Estou usando a seguinte consulta:
select
db_name() as DBName,
object_schema_name(i.object_id) as SchemaName,
object_name(i.object_id) as TableName,
isnull(i.name,'(HEAP)') as IndexName,
ps.SizeInPages
from
sys.indexes i
inner join
(
select ps.object_id,ps.index_id,sum(ps.row_count) as IndexRows, sum(ps.used_page_count) as SizeInPages, count(*) as PartitionCount
from sys.dm_db_partition_stats ps
group by ps.object_id,ps.index_id
) ps on
ps.object_id = i.object_id and
ps.index_id = i.index_id
where
object_schema_name(i.object_id) not in ('cdc','sys')
Idealmente, eu gostaria de executar esta consulta a partir de um SQL Login com as permissões mínimas necessárias, mas até agora parece que o usuário precisa VIEW SERVER STATE
e SELECT
permissões em todas as tabelas. Também tentei colocar a consulta acima em um procedimento armazenado e conceder EXECUTE
permissões à conta do usuário, mas sys.indexes
ainda é filtrada com base no que o usuário tem direitos de seleção.
Existe outra maneira de fazer isso que estou perdendo?
Existem algumas maneiras de alcançar o que você está procurando.
Vou mostrar-lhe dois, mas há outras maneiras também.
A primeira é assinar um procedimento e permitir que outros usuários o usem
grant execute on object::yourprocedure
apenas especificando.Antes de tudo você precisa de uma chave mestra, que eu suponho que você já tenha, e você pode verificá-la usando
sys.symmetric_keys
DMV e procurando por registro que tenha '##' como prefixo. Se não, basta criar uma chave mestra de banco de dadosEsta é uma chave muito importante, e certifique-se de fazer backup usando este guia
Agora você criará um certificado com base no qual criará o usuário de assinatura do módulo. Observe que é apenas para módulos de canto e você não pode usá-lo para testar privilégios etc.
Assim como a chave mestra, você também precisa fazer backup desse certificado. guia
Agora estamos criando um usuário com certificado que terá todos os direitos:
Existem duas maneiras de fornecer os direitos necessários:
exec sp_addrolemember 'db_datareader',UnlockCertifiedProcedures
GRANT VIEW DEFINITION TO UnlockCertifiedProcedures
,GRANT VIEW DATABASE STATE TO UnlockCertifiedProcedures
Feito isso, o próximo passo é realmente assinar este procedimento, então quem tiver direitos para 'executar' o procedimento herdará os direitos do usuário do certificado.
Testar:
create user TestUser WITHOUT LOGIN grant execute on OBJECT::YourProcedure to TestUser execute as user = 'TestUser' exec Schema.YourProcedure
A segunda opção é criar um usuário e executar o procedimento como aquele usuário especificado.
Crie o procedimento executando como esse usuário:
Agora simplesmente dê direitos de execução em um procedimento para um usuário especificado:
Como eu disse, existem outras maneiras, incluindo papéis, mas esses dois podem fazer um trabalho. Apenas lembre-se de que você não pode rastrear um usuário que executou o procedimento especificando 'executar como' (o login é possível). Também criar um certificado/chaves de banco de dados pode ser uma dor de cabeça quando você está migrando o banco de dados ou simplesmente restaurando-o em outro lugar.
Perguntei ao OP se o código se destina a ser executado em todo o servidor, ou seja, em todos os bancos de dados ou em alguns deles e ainda sem resposta, então suponho que ele precise que o código seja executado em TODOS os bancos de dados:
Primeiro, seu login deve acessar todos os bancos de dados, e você faz isso concedendo a ele
CONNECT ANY DATABASE PERMISSION
Então seu login deve acessar as definições de objetos sem acessar os dados (aqui está uma troca: ou você dá acesso de leitura em todas as suas tabelas, ou você dá acesso a todas as definições, isso significa todos os módulos incluídos, mas nenhum acesso a dados neste caso, então eu prefiro o último), isso é dado por
VIEW ANY DEFINITION
loginEssas duas permissões:
CONNECT ANY DATABASE PERMISSION
VIEW ANY DEFINITION
concedido ao login no nível do servidor é o conjunto mínimo de permissões para descobrir todos os tamanhos de todos os índices no servidor, basta alterar seu código para usar
sys.allocation_units
em vez desys.dm_db_partition_stats
Mas se você insistir em que seu código use
sys.dm_db_partition_stats
ele requerVIEW DATABASE STATE
em todos os bancos de dados, e você o concede concedendo apenas 1 vezVIEW SERVER STATE
permissão ao seu login......................................... Em resposta a esta:
Meu usuário não
l
tem permissão em um banco de dados , mas ele "vê" todas as tabelas (e outros objetos também) em um banco de dados, e não tem nenhum problema com sys.indexes enquanto ele não consegue ler nenhum dado; tudo o que ele tem nesse banco de dados é permissãoSELECT
VIEW DEFINITION
.................................................. ...................
Solução para apenas alguns bancos de dados:
Como o OP atualizou a pergunta dizendo que ele está aberto a outro código e o login já tem acesso ao banco de dados, sugiro conceder
VIEW DEFINITION
permissão apenas no banco de dados ao usuário em questão e usarsys.allocation_units
para obter tamanhos de índice como este:E aqui está o link para o artigo technet descrevendo a permissão VIEW DEFINITION
No nosso caso, concedemos
VIEW DEFINITION
em um banco de dados, portanto, o usuário concedido não tem acesso aos dados em si, mas a todos os metadados:Até onde eu sei, a solução mínima necessária de conjunto de permissões nesse caso é criar um procedimento de armazenamento que é executado dentro de um contexto representado. Faça isso por:
consulte: ( https://learn.microsoft.com/en-us/sql/t-sql/statements/execute-as-clause-transact-sql )
Em seguida, conceda aos usuários a execução nesse procedimento armazenado. Isso permitirá que o usuário visualize essas informações sem permissões adicionais (além de EXECUTE no SP).
testar:
Ao fazer isso, o procedimento armazenado será executado com as permissões do usuário designado ou (se definido como OWNER) do criador/proprietário do procedimento armazenado, em vez das permissões do usuário que está chamando EXECUTE (este é o comportamento padrão, que é por que sys.indexes está filtrando por permissões selecionadas no seu caso).
Os objetos subjacentes para a
sys.indexes
exibição são os seguintes:Para recuperar dados para a
sys.indexes
exibição, você precisariaGRANT SELECT ON <object> TO <user>
para todos os objetos acima. Infelizmente, isso não é possível, devido às seguintes restrições:Referência: Tabelas Base do Sistema
Pode ser mais fácil atribuir ao usuário em questão a função db_datareader para cada banco de dados para recuperar as informações relevantes.
Do meu teste esta manhã com um Windows Login em uma instância do SQL Server, não é suficiente ter
VIEW SERVER STATE
ouVIEW DATABASE STATE
recuperar as informações de sys.indexes.No entanto, aplicar a
db_datareader
função de banco de dados é suficiente para permitir o acesso à exibição sys.indexes.conjunto de resultados de sys.indexes com VIEW SERVER STATE e/ou VIEW DATABASE STATE
conjunto de resultados de sys.indexes com função db_datareader