Configurando uma biblioteca central de repositórios de funções / procedimentos armazenados do CLR para procs internos armazenados em outros bancos de dados?

17

Gostaria de usar o código que desenvolvi no C # CLR para ser usado em todos os bancos de dados no sistema, para que não seja necessário definir cada um como confiável, ativar o CLR e manter um monte de código dentro de cada um .

Existe uma maneira melhor de fazer isso do ponto de vista administrativo e de segurança? As funções CLR são muito básicas, como disjuntores, validação de email, url en / decode, base64 e etc. Gostaria apenas que o esquema dbo em cada banco de dados pudesse acessar as funções.

  1. Existe alguma maneira simples de fazer isso?
  2. Também não estou claro se a dll CLR está incorporada e se eu mover o banco de dados, ele será marcado junto, ou eu tenho que movê-la também.

obrigado

Alex Erwin
fonte
1
OK parece bom. Contanto que eu não ouça grilos do silêncio mortal sobre a pergunta. Sempre teve sorte no stackoverflow
Alex Erwin
1
O dba.se é menos frenético do que o SO, mas tenho certeza de que você receberá uma boa atenção em uma pergunta como essa dentro de um dia ou mais. Você está feliz por ser paciente por tanto tempo?
21412 Jack Douglas as
Lol, paciência é uma virtude. Eu tenho uma quantidade razoável e a própria pergunta, eu acho, que a MS abordaria. E se você é um host do SQL Server que deseja expor algumas funções úteis, mas não tem o servidor aberto para o CLR com força total?
Alex Erwin

Respostas:

8

Na nossa empresa, temos essa configuração exata. Quando você cria um assembly CLR, uma representação binária do assembly é armazenada no banco de dados em que você o cria. Isso permite que você o leve com você (e até faça um script), caso você mova o banco de dados a qualquer momento.

Alguns meses atrás, nosso data center foi inundado - enchendo vários servidores cheios de água. Quando os reconstruí, usei apenas os backups do banco de dados que haviam sido feitos na noite anterior. Até agora, não tivemos problemas .. (toque na madeira!)

Não tenho certeza se isso é a coisa certa a ser feita do ponto de vista da segurança, mas a maneira como concedemos acesso aos procs do CLR etc é criar uma função no banco de dados compartilhado e adicionar usuários de outros bancos de dados a essa função. A função é então concedida para executar nos procs do CLR.

Pode haver problemas de acesso se o CLR estiver tentando fazer coisas como acessar recursos fora do banco de dados em que está contido, mas você pode definir a permissão no assembly ao criá-lo. O link abaixo tem muito mais informações sobre permissões do que posso explicar aqui:

http://msdn.microsoft.com/en-us/library/ms345101.aspx

Espero que isso ajude você.

Mr.Brownstone
fonte
6

O binário do assembly é armazenado como um blob no banco de dados, portanto é transportado para onde quer que o banco de dados vá. O CLR está ativado apenas na instância - não há configurações específicas do banco de dados para isso.

De qualquer forma, por que você está tentando fazer isso?

(Não estou tentando argumentar; só quero ouvir os motivos envolvidos, porque talvez o problema possa ser resolvido de uma maneira diferente que atenda às suas necessidades.)


Não há como fazer isso facilmente, exceto colocar o assembly em um banco de dados compartilhado.

Dito isso, acho que é vantajoso adotar a arquitetura centrada em banco de dados, a menos que exista uma situação específica que tenha razões muito convincentes para centralizar. O motivo é que colocar o assembly (ou qualquer outra coisa) fora do banco de dados cria uma dependência em seu ambiente. Essa é precisamente a abordagem oposta que a Microsoft está adotando nos bancos de dados contidos a partir do SQL Server 2012.

  • Quando você começa a precisar usar recursos como replicação ou cluster, essa dependência pode potencialmente adicionar uma quantidade enorme de complexidade à implantação, mas também à solução de problemas e procedimentos de failover.

  • Essa arquitetura é muito menos óbvia para as pessoas que não estão familiarizadas com o sistema (ou seja, é menos auto-detectável e menos documentada).

  • Se você acabar exigindo segurança diferente em bancos de dados diferentes ou qualquer coisa que envolva variação, estará em um mundo de ferimentos.

  • Se esses bancos de dados forem implantados para os clientes (parece que não serão, mas vou dizer isso por completo), isso adiciona complexidade ao procedimento, manutenção e solução de problemas de implantação.

  • Como todos os bancos de dados compartilhariam esse código, se algum erro fosse introduzido (ou corrigido!), Isso poderia interromper todos os aplicativos que dependem dos bancos de dados. O teste de unidade abrangente seria uma necessidade absoluta.

Se você possui vários bancos de dados que precisam da mesma funcionalidade, existem outras maneiras de reduzir a quantidade de duplicação envolvida, que eu assumo ser o objetivo do exercício. Mesmo um assembly CLR bastante complexo não ocupa muito espaço de armazenamento físico em comparação com os dados no próprio banco de dados (quase sempre), por isso não vejo isso como um argumento válido, a menos que você tenha literalmente milhares de pequenos bancos de dados que precisam disso. montagem.

O que você pode fazer é modificar outras partes do procedimento de implantação desses bancos de dados para reduzir a duplicação de origem. Por exemplo, crie e implante o assembly a partir do local comum do código CLR no controle de origem. Ou crie um script que implante o mesmo assembly nos bancos de dados. Automatize essa parte das coisas o máximo possível, e não será grande coisa.

Concordo que o que estou sugerindo é uma troca, porque ainda haverá alguma duplicação, mas isso deve ser equilibrado com os negativos envolvidos na implementação de uma arquitetura que não segue o padrão prescrito. Somente você pode decidir o que é certo para o seu ambiente.

Jon Seigel
fonte
Entendo o seu ponto de quebrar as coisas, mas é para simplificar as implementações de código. Nenhum exército de desenvolvedores aqui. Apenas eu. No entanto, tenho outras pessoas usando o banco de dados, portanto, preciso garantir que as funções estejam inacessíveis, a menos que sejam usadas nos procedimentos armazenados que eu defino.
Alex Erwin
1

Como as outras duas respostas afirmam corretamente, os assemblies são carregados em um banco de dados específico e não são de todo o sistema (embora eu esteja bastante certo de que o assembly_idvalor é único em todo o sistema). Isso significa que eles são copiados e restaurados com cada banco de dados em que são carregados.

Além disso, a configuração enabled/ disabledde CLR Integration(via sp_configure) é de todo o sistema. Como uma observação lateral, essa configuração é apenas para a funcionalidade CLR criada pelo usuário ; Em geral, o CLR é sempre ativado, pois certas funcionalidades internas dependem disso.

Dito isto, embora as outras duas respostas aqui apresentem pontos válidos, esses pontos não são específicos ao SQLCLR e não há menção dos fatores na tomada dessa decisão que são específicos ao código do SQLCLR. Há problemas de memória a serem considerados se você implantar código em cada banco de dados individual (supondo que você tenha muitos bancos de dados), possíveis problemas de contenção de recursos, possíveis problemas relacionados à segurança etc.

Forneci o que deveria ser uma lista abrangente de itens a serem lembrados, especificamente para o código SQLCLR, ao decidir entre um banco de dados centralizado e uma implantação de banco de dados individual. Em vez de duplicar a lista aqui, consulte a seguinte resposta (também aqui no DBA.SE):

Como usar melhor a função CLR do ponto de vista do desempenho (repita dentro de cada banco de dados ou tenha função geral)?

Além disso, em uma nota relacionada, eu questionaria por que qualquer banco de dados está sendo definido TRUSTWORTHY ON. A funcionalidade observada na pergunta (ou seja, "separadores de seqüência de caracteres, validação de email, url en / decode, base64, etc") é possível em um SAFEassembly. Você não deve usar os valores EXTERNAL_ACCESSou UNSAFEperission_set, a menos que seja absolutamente necessário. E se for necessário para um certo número de funções, elas devem estar em um Assembly separado que contenha apenas SAFEcódigo, para que quaisquer funções escalares que não acessam dados e sejam marcadas como IsDeterministic = truepossam aproveitar o benefício de desempenho de serem capaz de participar de planos paralelos.

Solomon Rutzky
fonte