Sincronizando dois bancos de dados no SQL Server

16

Eu tenho dois bancos de dados do SQL Server. Um é cliente (aplicativo Windows) e o segundo está no servidor. Eu quero sincronizar esses dois bancos de dados de vez em quando (por exemplo, a cada 2 minutos!).

Eu li sobre diferentes maneiras de sincronizar, como replicação, registro de data e hora, tabelas de log usando gatilhos, Microsoft Sync Framework e assim por diante.

Na verdade, não gosto de usar um método de sincronização que pode ser uma caixa preta (como replicação) porque não quero que as tabelas específicas do SQL Server sejam bloqueadas enquanto as atualizo e sincronizo com o servidor.

  1. qual método você acha que devo usar em tais circunstâncias? Lembre-se de que a cada vários minutos eu devo enviar várias alterações de tabela do cliente para o servidor e buscar também duas alterações de tabela do servidor.

  2. Eu encontrei um método que é estranho, mas novo. É possível que eu registre todos os procedimentos armazenados executados (de preferência específica) no cliente e os envie com seus parâmetros em um .sqlarquivo para o servidor e os execute lá? O mesmo acontecerá no servidor e enviado ao cliente. Você acha que esse é um método simples, mas útil ou não?

  3. por favor me sugira qualquer abordagem útil, se puder. Muito obrigado.

EDIT: Lembre-se de que esta é uma sincronização em tempo real e isso a torna especial. Isso significa que, quando o usuário cliente está usando a tabela, o processo de sincronização com o servidor deve ocorrer a cada vários minutos, para que nenhuma tabela seja bloqueada.

Emad Farrokhi
fonte
1
Lembre-se de que essas "caixas pretas" são relativamente bem documentadas em relação à forma como funcionam, como mantê-las e monitorá-las e o que você pode fazer para corrigi-las em cenários de falha comuns (e não tão comuns). Eu consideraria lançar meu próprio método de sincronização e ter que encontrar e corrigir bugs relacionados a casos extremos que as "caixas pretas" resolveram há muito tempo, se e somente se eu tivesse necessidades muito específicas de aplicativos (sincronização parcial ou a necessidade de resolução interativa de conflitos e assim por diante).
David Spillett
@ DavidSpillett: Você usou a replicação em um projeto de sincronização em tempo real com sucesso? Minha principal preocupação é a sincronização em tempo real e "bloqueio e bloqueio".
Emad Farrokhi

Respostas:

14

Bem, eu posso não entender, mas tento responder.

Você disse que precisa de uma solução de alto desempenho que seja executada com frequência (mínimo todos os 2 minutos) e que precisa de uma boa abordagem, que deve ser rápida sem travar. Mas você não quer um sistema de caixa preta.

Em vez de um sistema de caixa preta, usado em milhões de instalações com bons resultados, você tenta inventar a roda novamente e criar sua própria solução? Hum, parece um pouco estranho.

De fato, essas são minhas sugestões.

  1. Replicação, mesmo que você tenha dito que não a usará. É a solução mais fácil e melhor que você pode usar para isso. A replicação é fácil de configurar, replicar rapidamente e você não precisa inventar a roda novamente. Se você apenas esquisita quanto ao bloqueio, pode tentar definir ISOLATION LEVELcomo READ_COMMITTED_SNAPSHOT. Você pode ler mais sobre isso aqui . Isso consumirá parte do seu tempdb, mas sua tabela é sempre de leitura e gravação e a replicação pode funcionar em segundo plano.

Veja o exemplo abaixo:

ALTER DATABASE yourDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE yourDatabase SET READ_COMMITTED_SNAPSHOT ON
  1. O CDC (Change Data Capture) também pode ser uma solução. Mas, dessa forma, você precisa criar quase tudo sozinho. E fiz a experiência que CDCpode ser uma coisa frágil em algumas circunstâncias. CDCirá capturar todos os dados em uma tabela monitorada (você precisa especificar cada tabela monitorada manualmente). Depois, você obterá o valor antes e o valor após um INSERT, UPDATEou DELETE. CDCreterá essas informações por um período de tempo (você pode especificá-las por conta própria). A abordagem poderia ser usar CDCem determinadas tabelas que você precisa observar e replicar manualmente essas alterações no outro banco de dados. A propósito, também CDCusa a Replicação do SQL Server sob o capô. ;-) Você pode ler mais sobre isso aqui .

Aviso: CDCnão estará ciente das DDLalterações. Isso significa que, se você alterar uma tabela e adicionar uma nova coluna, CDCela observará a tabela, mas ignorará todas as alterações na nova coluna. De fato, ele registra apenas NULLcomo valor antes e depois. Você precisa reinicializá-lo após DDL-Alterar em uma tabela monitorada.

  1. A maneira como você descreveu acima é como capturar uma carga de trabalho usando o SQL Server Profiler e executá-la novamente em outro banco de dados para obter alguns benchmarks. Bem, isso poderia funcionar. Mas o fato de haver muitos efeitos colaterais é um pouco pesado demais para mim. O que você faz se capturar uma chamada de procedimento no seu cliente. Depois de executar o mesmo comando no seu banco de dados principal, pois está fora de sincronia? O procedimento pode ser executado, mas pode excluir / atualizar / inserir linhas que não estavam presentes no seu cliente. Ou como você lida com vários clientes com um princípio. Eu acho que isso é muito complicado. Na pior das hipóteses, você provavelmente destrói sua integridade.
  2. Outra idéia poderia ser baseada em aplicativos ou usando um gatilho. Dependendo de quantas tabelas você deseja sincronizar. Você pode gravar todas as alterações em uma tabela intermediária separada e executar uma tarefa do SQL Server Agent todos os x minutos para sincronizar essas linhas na tabela intermediária com seu mestre. Mas isso pode ser um pouco pesado se você tentar sincronizar (por exemplo) 150 tabelas. Você teria uma grande sobrecarga.

Bem, estes são os meus 2 centavos. Espero que você tenha uma boa visão geral e talvez tenha encontrado uma solução que funcione para você.

Ionic
fonte
9

Vou tentar enumerar algumas opções aqui com vantagens e desvantagens à medida que as percebo:

  1. Replicação do SQL Server - esta é a melhor e mais otimizada ferramenta nativa do SQL Server para esta tarefa. Mas há vários problemas: a. para todos os seus clientes, independentemente de serem ou não bancos de dados SQL Express, você precisará da licença CAL do SQL Server. Isso pode ser evitado usando o licenciamento por processador. b. Você não pode sincronizar o cliente SQL CE conforme aqui . c. O SQL Express ou o LocalDB não pode atuar como editor ou distribuidor , portanto, você tem menos controle sobre o processo de replicação do cliente.
  2. Microsoft Sync Framework - me parece mais adequado para bancos de dados menores de aplicativos móveis. Ele adiciona várias tabelas ao seu banco de dados e não é tão eficiente quanto a replicação. Como é implementado fora do SQL Server como um componente, será mais difícil de configurar. Não tenho experiência com ele, apenas tentei e decidi não usá-lo.

  3. Rastreamento de alterações no banco de dados . É uma função interna do SQL Server que faz para você alterar o rastreamento, incluindo inserções, atualizações e exclusões. Tudo o mais, como enviar e aplicar alterações, resolver conflitos etc., você terá que codificar a si mesmo.

  4. Colunas Rowversion (registro de data e hora) Se você não permitir todas as exclusões (sem sincronização de registros excluídos) - poderá implementar sua própria solução com base apenas nas informações de versão de linha. As colunas Rowversion também são usadas pelo SQL Server Replication, portanto, você precisará adicioná-las de qualquer maneira.
  5. CDC, conforme mencionado na resposta da Ionic - não tenho experiência com ele, pois está disponível apenas nas edições Enterprise ou Developer.

  6. Usar seu próprio truque para registrar procedimentos armazenados executados - depende muito da natureza do seu aplicativo de banco de dados. Mas quando os procedimentos ficam um pouco diferentes, você pode obter uma grande bagunça nos dados. E como você lida com conflitos?

Da sua pergunta, parece que você precisa sincronizar apenas algumas tabelas e não todos os grandes bancos de dados. Para esse fim, você deve analisar suas necessidades com mais detalhes do que especificou na pergunta, como:

  • As exclusões podem acontecer e o que acontece então?
  • Podem ocorrer conflitos, como evitá-los e como resolvê-los?
  • Como vou lidar com as alterações na estrutura da tabela?
  • ...

Se você descobrir que exclusões e conflitos não são problema seu e que sua estrutura não mudará muito, considere escrever sua própria lógica, mas ela pode aumentar facilmente para 1000 linhas de código.

Vojtěch Dohnal
fonte
2

Obrigado a todos por seus comentários.

Resolvi com êxito o processo de sincronização capturando os procedimentos armazenados executados não como um grupo, mas um por um que funcionou muito bem no meu caso. Como a integridade e tudo são cuidadosamente considerados, o sistema tem trabalhado em tempo real até agora.

Emad Farrokhi
fonte
Ótimo, no entanto, você pode explicar mais detalhadamente o que fez. Você simplesmente registra as chamadas dos procedimentos armazenados que foram executados e as armazena em alguma tabela / script temporário e faz com que um trabalho execute esse script e defina um campo (como um campo de bits ou um campo de data e hora em que você diz TODOS estes os registros que não foram processados ​​os processam e atualizam o campo de bits?) Estou feliz por ter resolvido seu problema, mas você precisa fornecer mais informações sobre o que fez para ajudar os outros a aprender?
25918 JonH
0

Resposta tardia, mas pode ser útil enfiar os visitantes

Tive um desafio semelhante ao tentar distribuir dados por diferentes servidores e resolvi-os usando ferramentas de terceiros ( Dif para alterações de esquema e DataDiff para sincronização de alterações de dados) e seguindo o script do PowerShell necessário para automatizar o processo:

#check for the existence of the Outputs folder
function CheckAndCreateFolder($rootFolder, [switch]$Outputs)
{
$location = $rootFolder

#setting up location 
if($Outputs -eq $true)
{
    $location += "\Outputs"
}

#if the folder doesn't exist it will be created
if(-not (Test-Path $location))
{ mkdir $location -Force:$true -Confirm:$false | Out-Null }

return $location
}

#root folder for the schema sync process
$rootFolder = "SchemaSync"

#schema output summaries location 
$outsLoc = CheckAndCreateFolder $rootFolder -Outputs

#ApexSQL Diff location, date stamp variable is defined, along with tools parameters 
$diffLoc   = "ApexSQLDiff"
$stamp = (Get-Date -Format "MMddyyyy_HHMMss") 
$Params = "/pr:""MyProject.axds""    /out:""$outsLoc\SchemaOutput_$stamp.txt"" /sync /v /f" 
$returnCode = $LASTEXITCODE

#initiate the schema comparison and synchronization process
(Invoke-Expression ("& `"" + $diffLoc +"`" " +$Params))

#write output to file
"$outsLoc\SchemaOutput_$dateStamp.txt"

#schema changes are detected
if($returnCode -eq 0)
{
"`r`n $returnCode - Schema changes were successfully synchronized" >> 

}
else
{
#there are no schema changes
if($returnCode -eq 102)
{
"`r`n $returnCode - There are no schema changes. Job aborted" >> 
}
#an error is encountered
else
{
"`r`n $returnCode - An error is encountered" >> 

#output file is opened when an error is encountered
Invoke-Item "$outsLoc\SchemaOutput_$stamp.txt"
}

}

Esse método agenda a comparação entre dois bancos de dados e sincroniza as alterações encontradas em tempo real. Aqui estão alguns artigos que oferecem instruções passo a passo:

https://solutioncenter.apexsql.com/automatically-compare-and-synchronize-sql-server-data/ https://solutioncenter.apexsql.com/how-to-automatically-keep-two-sql-server-database- esquemas em sincronização /

Monte Chavis
fonte