Eu preciso executar um banco de dados de log do servidor SQL com 2 tabelas principais em 2 datacenters separados gravando em ambos ao mesmo tempo.
Tive a ideia de restaurar o banco de dados para o novo datacenter e, em seguida, propagar novamente a coluna de identidade para -1 e definir o incremento para -1, dessa forma nunca haveria chance de duplicar id's quando os dados precisassem ser combinados. DATACENTRE1 seriam inteiros positivos, DATACENTRE2 inteiros negativos
um incremento de -1 causaria algum problema?
Voltar para trás parece errado para mim.
Com apenas dois data centers, você também pode implementar intervalos de identidade. A menos que você percorra os valores de identidade em um ritmo alarmante, não há motivo para não ter:
Isso permitiria gerar 1 bilhão (bem, 999.999.999) valores no datacenter 1 antes que houvesse qualquer perigo de colisão com o datacenter 2. E você poderia adicionar uma restrição CHECK no datacenter 1 para evitar a sobreposição de valores, dependendo de como você prioriza erros versus duplicatas. Você também pode implementar um trabalho recorrente que verifica periodicamente o quão perto você está do limite inferior do outro centro de dados, se estiver preocupado em gerar mais de um bilhão de valores em qualquer centro de dados durante a vida útil do aplicativo (não importa Sua).
Se ~1 bilhão não for suficiente, existem outras duas alternativas para dar mais espaço para respirar:
Isso daria a cada centro de dados mais de 2 bilhões de valores não sobrepostos, sem perigo de colisão até que o centro de dados 1 se aproximasse de 0. E se isso ainda não for suficiente:
Ou, se você quiser manter todos os valores > 0, poderá dividir o intervalo positivo aproximadamente pela metade (você pode ser um pouco mais preciso do que isso se for mais pedante do que eu).
Eu nem sei como dizer esse número, mas é gigantesco. E, na realidade, você teria que trabalhar muito duro em um computador muito rápido para usar todos esses valores no momento em que seu tataraneto se formar na faculdade. E se você estiver no Enterprise Edition, poderá usar a compactação de dados para não pagar o hit de todos os 8 bytes, pelo menos no data center 1, até ultrapassar 2 bilhões lá.
Em um sistema que gerenciei, fiz isso de uma maneira um pouco diferente - tínhamos vários servidores da Web com instâncias do Express responsáveis por gerar números de identificação que precisavam ser exclusivos na empresa. Portanto, apenas configuramos um gerador de sequência em cada máquina (eles não precisavam realmente armazenar o valor) usando uma coluna BIGINT IDENTITY. Tínhamos < 9 servidores, então todos eles foram semeados assim:
Quando os valores foram usados e depois mesclados no sistema central, não apenas garantimos que não haveria duplicatas, mas também foi fácil reconhecer instantaneamente de qual servidor da Web eles vieram (o que às vezes era útil na depuração) sem introduzir nenhum composto principais requisitos. E não tínhamos preocupações de que qualquer servidor da Web pudesse gerar mais de 10 bilhões de valores.
Muitas pessoas usariam um GUID nesse cenário, mas acho que há vários argumentos fortes contra essa abordagem.
Não causará problemas porque o SQL Server permite que você faça isso:
Mas uma boa ideia a longo prazo pode ser um problema diferente. Outros podem acabar confusos (ou seja, tive que pensar na ordem da consulta acima, pois está de cabeça para baixo ao normal). Ou o que acontece quando alguém restaura o banco de dados e propaga novamente da
IDENTITY
maneira 'normal' e você tem IDs sobrepostos?É possível modificar seu esquema para que você tenha uma coluna 'site'? Em seguida, use o site e o ID como uma chave composta?
Alguns problemas que podem surgir com esta configuração:
Seguindo o link no comentário de @Martin Smith , valores negativos em uma coluna de identidade podem causar problemas com alguns aplicativos: Por que os designers de banco de dados não fazem as colunas de IDENTIDADE começarem com o valor mínimo em vez de 1?
Outra questão não está relacionada aos valores serem negativos, mas decrescentes, e se a identidade também for a chave agrupada da tabela. As estruturas de árvore B são mais eficientes quando percorridas da esquerda para a direita (valores mais baixos para os mais altos) e quando as inserções são feitas no lado direito (mais alto), por exemplo, quando a chave é sempre crescente. Essa propriedade é cada vez mais importante para a chave agrupada da tabela. Veja esta postagem no blog de Kimberly Tripp sobre as melhores propriedades das chaves em cluster, especialmente sobre o número cada vez maior de .
Com a tecla decrescente, você estará inserindo dados sempre do lado errado (esquerdo) do índice, causando a fragmentação do índice. Os efeitos podem não ser críticos para o seu caso, mas acho que você deve ter isso em mente se a identidade também for escolhida como a chave agrupada.
Ou, como sugere @Martin, tenha o índice clusterizado também definido como
DESC
para o datacenter (-1). Isso evitará qualquer um dos problemas acima com fragmentação.Outras opções para obter a mesma funcionalidade mantendo IDs crescentes é ter valores pares em um datacenter e ímpares no outro (ambos com incremento de +2) ou
siteID
adicionado à chave primária como @Stuart sugeriu.Apenas tente! (e depois relatar aqui :-)).
Não, não espero nenhum problema - afinal,
INT
o intervalo de dados do 's é de -2 bilhões a +2 bilhões - não vejo por que os números negativos devem se comportar de maneira diferente dosIDENTITY
números positivos....Isso soa como uma variação do particionamento de dados por chave. Um método alternativo é usar a semente e o incremento para que cada centro de dados gere valores que se intercalam, mas não colidem. Tente algo como:
Os valores de identidade em cada tabela têm lacunas:
Se você acha que pode ter DCs adicionais no futuro, defina o incremento para o número de DCs que você poderia ter (por exemplo, 4). Ao rolar, você teria:
As abordagens que tenho usado são:
Cada solução tem prós e contras.