Ir para o conteúdo

Blogue ·

O único limite real à ocupação de um bastidor

Dois engenheiros escolhem a mesma unidade de bastidor ao mesmo tempo. O formulário diz livre a ambos. Quem decide é um índice único parcial, e mais nada.

Por Provibr

Dois engenheiros estão a colocar máquinas no mesmo bastidor. Ambos abrem o formulário, ambos olham para o U nove, ambos veem um slot livre, ambos carregam em guardar. Faça o seu código de aplicação o que fizer entre esses dois pedidos, existe uma janela em que ambos leem a mesma resposta, e verificação nenhuma antes da escrita a fecha.

Esta é a corrida mais antiga do manual e tem uma resposta correta: quem decide é a base de dados. Tudo o que está por cima dela existe para produzir uma recusa legível, e não para evitar uma colisão. Trocar essa ordem é exatamente a forma de acabar com uma regra de unicidade que se fura num dia atarefado e, num centro de dados, furar significa alguém com um carrinho parado à frente de um bastidor que já está cheio.

A fronteira é um índice

A ocupação é guardada duas vezes de propósito. Uma marcação tem uma linha de cabeçalho, que é a coisa que alguém criou: esta face, desta unidade até àquela e, no caso de uma colocação, a máquina que lá está. E tem uma linha por cada slot ocupado: este bastidor, esta face, este único U.

A tabela de slots existe por uma única razão. Leva um índice único parcial sobre o bastidor, a face e o número do slot, limitado às linhas que não foram libertadas. Esse índice é o único limite real à ocupação em todo o sistema. Nenhum outro o pode ser, porque um índice único não consegue juntar tabelas: só vê as colunas da linha em que assenta, pelo que o bastidor e a face têm de estar desnormalizados na linha do slot para que a restrição sequer exista.

O preço é que libertar uma marcação são duas escritas dentro de uma transação, já que a data de libertação vive tanto no cabeçalho como nos slots. O retorno é que a invariante é imposta pela base de dados e não pelo cuidado de quem escrever a próxima funcionalidade.

Medimos isto em vez de raciocinar sobre isto. Duas ligações reais ao Postgres, uma barreira mútua para que ambas estejam dentro da sua transação antes de qualquer uma confirmar, ambas a marcar o U nove da frente. Resultado: exatamente uma marcação escrita, um erro 23505 a nomear esse índice, e nenhuma linha de cabeçalho órfã deixada para trás pela reversão. É essa a frase que se quer conseguir escrever sobre uma garantia de concorrência, e não se consegue escrevê-la a partir da leitura do código.

Para que serve na verdade a verificação antes da escrita

Existe uma função pura que planeia uma marcação, e ela recusa de três maneiras, por esta ordem.

A face não existe. Uma estrutura aberta sem traseira não é um bastidor onde se pendure alguma coisa por trás, e é por isso que saber se um bastidor tem frente e traseira é uma propriedade do bastidor e não um pressuposto.

Fora dos limites. O intervalo inteiro tem de caber entre a unidade inicial do bastidor e o seu fim, inclusive. Nem todos os bastidores começam no um e nem todos numeram para cima, pelo que isto é aritmética contra a geometria daquele bastidor em concreto e não contra o número quarenta e dois.

Ocupado, e esta recusa leva consigo a lista dos slots que colidem. Uma mensagem que diz «cheio» manda alguém de volta ao formulário sem ideia nenhuma de onde procurar. Uma mensagem que diz que o U nove e o U dez da frente estão tomados manda essa pessoa para a resposta.

Nenhuma destas é a fronteira. Ambos os engenheiros do primeiro parágrafo passam as três. A função existe para que o caso normal, que é uma pessoa de cada vez a enganar-se, produza uma frase em vez de um código de erro de base de dados.

A profundidade desconhecida comporta-se como total

Todos os ativos têm uma classe de profundidade: total, meia ou desconhecida. Um artigo de meia profundidade marca apenas a face onde está pendurado. Um artigo de profundidade total marca a frente e a traseira.

O desconhecido marca também a frente e a traseira, e essa escolha merece ser defendida, porque a predefinição intuitiva é a contrária. O desconhecido parece dados em falta que serão preenchidos mais tarde e, enquanto se espera, parece inofensivo deixar o outro lado livre.

Não é inofensivo. Uma máquina cuja profundidade se revele total não pode ser instalada se entretanto alguém tiver enchido a traseira, e a correção acontece com a máquina já em obra. Bloquear a traseira custa um slot que talvez pudesse ter. Não a bloquear custa uma entrega. O desconhecido não é a ausência de uma restrição, é uma restrição que ainda não se consegue nomear, e o lado seguro dela é o conservador.

O mesmo princípio percorre o resto do modelo de capacidade: um peso desconhecido, um consumo de energia desconhecido ou um estado de marcação desatualizado leem-se como desconhecido ou bloqueado, e nunca como capacidade livre.

Uma colocação nunca expira

As marcações vêm em quatro espécies. Uma colocação é uma máquina que está fisicamente ali. Um bloqueio é espaço retirado de serviço para cablagem. Uma retenção para movimentação e uma reserva são as duas que guardam espaço para algo em trânsito ou encomendado. Só a primeira tem hoje um ecrã; as outras três existem como dados para que a primitiva seja uma coisa e não quatro coisas parecidas.

Uma restrição de verificação na base de dados impõe que uma colocação não tenha data de expiração. Parece uma regra pequena. O que ela evita é uma linha que deixa de contar em silêncio numa terça-feira enquanto a máquina continua aparafusada lá dentro, ou seja, um bastidor que o software acredita ter um slot livre. Uma reserva que expira é uma funcionalidade; uma colocação que expira é uma mentira com um temporizador em cima.

Uma segunda restrição de verificação exige que uma colocação tenha um ativo, já que as outras três espécies legitimamente não têm nenhum, e um índice único parcial permite no máximo uma colocação ativa por ativo. Sem esse índice, a mesma máquina pode ficar registada em dois bastidores ao mesmo tempo. Isso não é um problema de qualidade de dados que se note num relatório; é um problema que se nota quando alguém está parado à frente do bastidor errado.

Vale a pena saber uma coisa sobre os índices desta forma: são globais e não delimitados por organização. Uma máquina que já leve uma linha ativa colide com a restrição de unicidade e não com uma verificação de titularidade, mesmo quando a segunda tentativa vem de outra organização. Esse é o lado seguro, e significa também que testar o caso das duas organizações precisa de um terceiro ativo, porque a restrição dispara antes de a lógica de titularidade sequer correr.

A mesma forma um nível acima

Entregar uma máquina a um cliente tem estrutura idêntica, e precisa de dois índices em vez de um, porque são duas invariantes que as pessoas costumam enunciar como uma só frase.

Um serviço está no máximo numa máquina. Sem isso, um serviço pode apontar para dois ativos e a sua ficha de localização aponta em duas direções.

Uma máquina é entregue no máximo a um serviço. Sem isso, a mesma máquina é vendida duas vezes, e descobre-se quando dois clientes telefonam.

Ambos são índices únicos parciais sobre linhas cuja data de fim ainda está vazia, que é a mesma construção do índice dos slots e pela mesma razão: a verificação na aplicação produz a recusa legível, o índice decide quem ganha.

Uma regra não conseguiu entrar na base de dados. Um vínculo tem de apontar para um serviço dedicado, e uma restrição de verificação não consegue ler outra tabela. Essa vive na função que escreve o vínculo, e vale a pena ser explícito sobre quais das suas regras são impostas pelo esquema e quais são impostas por um caminho de código, porque a segunda espécie só vale tanto quanto o número de caminhos de escrita que alguém se lembre de encaminhar por ela.

Os vínculos são históricos e não atuais. É a data de fim que torna a linha inativa, e todas as leituras de uma localização física filtram por ela e pela organização tanto do vínculo como do ativo. Retire esses filtros e um antigo cliente lê o bastidor e a unidade do cliente que veio a seguir. Isso foi provado vermelho antes de ser corrigido, que é a única maneira de saber que um filtro está a fazer alguma coisa.

O que registaríamos

  1. Ponha a unicidade onde a linha está. Se a restrição precisar de juntar tabelas, desnormalize as colunas de que ela precisa; um índice não junta tabelas e um gatilho não é uma restrição.
  2. Materialize a unidade de disputa. Uma linha por slot ocupado, e não um intervalo num cabeçalho, porque um intervalo não pode ser único contra outro intervalo.
  3. Prove a corrida com duas ligações e uma barreira. Raciocinar sobre níveis de isolamento não é prova.
  4. Deixe que a verificação prévia seja uma mensagem e não uma defesa, e faça com que nomeie os slots exatos que colidem.
  5. Faça com que o desconhecido se comporte como o caso caro, para que uma medição em falta nunca se apresente como espaço livre.

Para ser claro quanto ao ponto em que isto está: o trabalho de logística de centro de dados vive atrás de um sinalizador de lançamento que está desligado por predefinição, com uma definição por organização por cima dele, pelo que nada do que está acima é comprável hoje. Duas coisas estão por provar: a medição de concorrência foi feita contra marcações de bloqueio, num teste direto à base de dados, e não contra o caminho da colocação em si, e as espécies retenção para movimentação e reserva ainda não têm quem as escreva. O hábito mais geral de deixar a base de dados ser o árbitro aparece também noutros pontos deste produto, em como os endereços são distribuídos a partir de um conjunto e em como um intervalo de VMID é na verdade uma fronteira de permissões.

Do trabalho de centro de dados na Provibr. Porque é que as cinco perguntas de capacidade sobre um bastidor não podem ser somadas está em espaço em bastidor não é capacidade, e o que acontece quando um sistema externo afirma saber onde está uma máquina está em quando o NetBox é a fonte da verdade.

Comece com um host e um agente

Crie uma conta, instale o agente com um único comando e ligue o seu primeiro host Proxmox. O período experimental dura 14 dias e não pede quaisquer dados de pagamento.