Banco de Dados

22 mai, 2017

Uso de sinônimos e o ciclo de vida do banco de dados

Publicidade

O conceito de sinônimo está disponível no SQL Server desde a versão 2005, mas até hoje ele é muito pouco usado. A ideia é muita simples: criar um apelido para um objeto de modo abstrair a localização deste objeto.

O uso de sinônimos reduz dramaticamente os problemas que acontecem durante o ciclo de vida destas aplicações que usam dados compartilhados entre vários bancos de dados.

Desenvolvendo com “hardcode”?

Desde que fiz meu primeiro curso de programação a algumas décadas atrás, ouço recomendações para evitar ao máximo a prática do hardcode. Talvez essa seja umas das premissas mais antigas na área de programação.

Se isso é aceito como verdade, porque não ter o mesmo cuidado quando se trata da integração entre bancos de dados diferentes?

Analisando mais a fundo, precisamos entender como é feita a referência a objetos de bancos de dados externos. Não há muito segredo nesta sintaxe, conhecida como qualificação completa dos objetos:

[Server_name].[Database_name].[Schema_name].[Object_name]

Onde

  • [Server_name]: é o nome da instância SQL ou do servidor do SGBD em questão; é opcional, caso o objeto referenciado esteja na mesma instância SQL do código que o invoca.
  • [Database_name]; é o nome do banco de dados a que pertence o objeto; é opcional, caso o objeto em questão esteja no mesmo banco de dados que o SQL do código que o invoca.
  • [Schema_name]: é o nome do esquema a que pertence o objeto; é opcional, caso o objeto em questão esteja associado ao esquema default da conexão ou caso pertença ao mesmo esquema que o SQL do código que o invoca.
  • [Object_name]: é o nome do objeto em questão; é o único item obrigatório da descrição.

A simplicidade desta sintaxe encobre alguns problemas que podem surgir durante o ciclo de vida de aplicações que usam dados de vários bancos de dados.

Hardcoding vs integração de bancos de dados

Eu considero como hardcoding criar scripts usando qualificadores de objetos de bancos de dados externos. E explico o porquê.

Se o script invoca um objeto de um outro banco de dados que esteja na mesma instância, o qualificador permite omitir o nome desta instância. Mas isso implica que os dois bancos de dados, tanto aquele em que o script se conecta, como também o banco onde existe o objeto invocado, deverão estar sempre na mesma instância durante todo o ciclo de vida da aplicação.

Essa premissa pode ser simples num ambiente com poucos bancos de dados e/ou em que o ciclo de vida da aplicação seja curto. Mas é uma exigência difícil de acomodar em ambientes produtivos mais complexos.

O mesmo acontece quando fazemos integração com bancos de dados de outras instâncias SQL ou de outros SGBDs. Geralmente, isso é feito através de linked servers, que serão necessariamente descritos nos qualificadores do objeto.

Quando qualquer das bases usadas pela aplicação for movida para uma nova instância, seja por mudança de versão do banco ou reorganização do ambiente, será necessário recriar estes links usando o mesmo nome, as mesmas características e as mesmas credenciais de segurança usados no linked server original. Não é difícil imaginar situações em que isso também possa causar problemas.

Solução sugerida

Um meio simples de evitar estes problemas é criar sinônimos para todos os objetos acessados em bases externas. Essa solução é aplicável a tabelas, visões, procedimentos armazenados e funções.

Basta conectar-se na base principal (aquela que faz a chamada aos objetos externos) e criar sinônimos para estes objetos externos, como mostra o exemplo a seguir:

USE [BasePrincipal]
GO  
CREATE SYNONYM aliasTabela1 FOR AdventureWorks2012.Person.Tabela1  
CREATE SYNONYM aliasVisaoX  FOR AdventureWorks2012.Finance.VisaoX  
GO

Não há segredo nenhum sobre como usar os sinônimos em qualquer declaração SQL, pois o sinônimo é visto como sendo ele próprio um novo objeto. Os exemplos a seguir, com e sem uso de sinônimos, retornam exatamente o mesmo resultado.

USE [BasePrincipal]
GO  
-- CONSULTA COM QUALIFICADORES
SELECT C.Campo1, C.Campo2, T.Campo7, T.Campo8
FROM TabelaClientes C
   INNER JOIN AdventureWorks2012.Person.Tabela1  T
WHERE C.Campo 5 = 'X'

-- CONSULTA IDÊNTICA COM SINÔNIMO
SELECT C.Campo1, C.Campo2, T.Campo7, T.Campo8
FROM TabelaClientes C
   INNER JOIN aliasTabela1 T
WHERE C.Campo 5 = 'X'

Os sinônimos são muito fáceis de criar e também de serem usados. Mas é de fundamental importância que se garanta que todas as declarações SQL desta aplicação, incluindo jobs, robôs etc usem os sinônimos dos objetos em 100% dos scripts. Portanto, ele tem que ser visto com um padrão de programação para aquela aplicação.

Este esforço se pagará no momento em que se fizer necessária a migração de qualquer das bases usadas por esta aplicação. Neste caso, basta verificar quais são as instâncias de origem e destino de cada uma das bases envolvidas (a principal e as vinculadas), verificar quais são os sinônimos que são usados nestas bases e, finalmente, recriar os sinônimos usando os novos parâmetros.

Para listar os sinônimos que existem em cada base, basta consultar a tabela de sistema sys.synonyms, como no exemplo a seguir:

SELECT * FROM sys.synonyms

Comentários finais

Sinônimos são uma solução simples e eficiente para gerenciamento de objetos externos ao banco de dados e são muito úteis ao longo do ciclo de vida da aplicação.

Pense nisso quando começar um projeto novo. Na prática, funciona como uma apólice de seguro que pode economizar centenas de horas de retrabalho durante a vida útil da sua aplicação.

Leituras sugeridas

  1. Use Synonyms to Abstract the Location of SQL Server Database Objects, por Ray Barley
  2. Synonyms (Database Engine), por Rick Byham & Craig Guyer
  3. SQL Server Best Practices – Implementation of Database Object Schemas, por seMichael Redman