instrução SQL para designar um mestre conjunto
-
11-07-2019 - |
Pergunta
Eu agrupados aplicações que requerem um dos nós de ser designado como o mestre. Os nós do cluster são monitorados em uma tabela com nodeID , isMaster , LastTimestamp colunas.
Cada nó no cluster vai tentar se tornar um mestre a cada X segundos. Nó só pode se tornar um mestre se qualquer
- não existe nenhum outro nó mestre
- LastTimestamp no nó mestre atual é mais velho por 2 * X
Quando uma das condições acima é satisfeita ??p>
- do nó mestre atual isMaster devem ser apuradas
- do novo nó mestre isMaster deve ser definido
- do novo nó mestre LastTimestamp deve ser definido como 'empresa' timestamp.
O que é o única declaração (portátil) SQL para alcançar o acima, sem a possibilidade de dois ou mais nós se tornando o mestre?
Solução
Não é este tipo de coordenação normalmente tratada pelo próprio DBMS, em vez de aplicativos em execução no DBMS? Eu também posso imaginar maneiras de fazê-lo no DBMS estou familiarizado, mas sem saber mais sobre o seu sistema (que presumivelmente é usando discos compartilhados, para que todos os nós de ver os mesmos dados, existem protocolos que impedem o acesso simultâneo presumivelmente bloqueio aos dados; é um processo de usuário no nó mestre que atualiza periodicamente o LastTimestamp), ele vai ser duro para ajudar muito. E, como Jamie Amor apontou, o DBMS deve permitir que vários processos para coordenar o acesso aos registros relevantes -. A principal registro relevante sendo o registro mestre de corrente
[ Editado :. Talvez eu estava lendo muito para isso
A instrução UPDATE única tem a ver atualizações diferenciais em duas linhas da tabela, e deve falhar se apenas uma das duas atualizações é possível. Ou seja, ele deve tanto a mudança do atual mestre de ser não-master e também alterar o seu próprio recorde por isso é o mestre. Uma questão é como é que o DBMS impor a 'apenas uma linha pode ser o mestre' restrição. Vamos supor que obras e a declaração como um todo irá falhar se houver um problema - como deveria. Por que as pessoas muitas vezes omitir o nome da tabela, mesmo quando eles fornecem os nomes das colunas? Oh bem, o nome da tabela é daqui em diante ClusterControl . Cada nó deve conhecer o seu próprio NodeID de alguma forma; Eu usei {MyNodeID} para indicar onde que aparece no SQL.
Você precisa de uma atualização batimentos cardíacos separada:
UPDATE ClusterControl
SET lastTimestamp = CURRENT_TIMESTAMP
WHERE NodeID = {MyNodeID};
A actualização "aproveitar status de mestre" poderia ser:
UPDATE ClusterControl
SET lastTimestamp = (CASE
WHEN NodeID = {MyNodeID} THEN CURRENT_TIMESTAMP
ELSE lastTimestamp END),
isMaster = (CASE
WHEN NodeID = {MyNodeId} THEN 'Y'
ELSE 'N' END)
WHERE (NodeID = {MyNodeID} AND isMaster = 'N') OR
(NodeID != {MyNodeID} AND
lastTimestamp < CURRENT_TIMESTAMP - INTERVAL '120' SECOND AND
isMaster = 'Y'
);
A teoria por trás do update 'aproveitar status de mestre' é (cláusula SET):
- campo LastTimestamp para o novo mestre é definido para o timestamp atual, mas o velho mestre é inalterada.
- o campo isMaster é alterado para 'Y' para o novo mestre e a 'N' para a idade mestre.
A teoria por trás da cláusula WHERE é:
- Apenas alterar o registro para o nó atual se não é o mestre atual ou o registro para o nó mestre atual quando este nó não é o nó atual e a hora é mais de 120 segundos ( "2 * X" na questão) de idade.
Uma vez que existe um (possivelmente mítica) restrição no local para garantir que apenas uma linha tem o sinalizador 'Y', isso deve falhar como necessária quando o mestre é até à data.
SQL Untested!
]
Outras dicas
Eu posso imaginar uma solução para um banco de dados Oracle, mas eu não tenho certeza que seria portátil. Por que essa necessidade de ser uma única instrução SQL portátil? A maioria de banco de dados permitem bloqueio mesa e transações, que permitem que você faça esse tipo de coisa em múltiplas declarações.