O AUTO_INCREMENT pode ser usado com segurança em um ANTES do TRIGGER no MySQL

O método Postgres do Instagram de implementar IDs personalizados para Sharding é ótimo, mas eu preciso da implementação no MySQL.

Então, converti o método encontrado na parte inferior deste blog, aqui:http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram

Versão do MySQL:

CREATE TRIGGER shard_insert BEFORE INSERT ON tablename
FOR EACH ROW BEGIN

DECLARE seq_id BIGINT;
DECLARE now_millis BIGINT;
DECLARE our_epoch BIGINT DEFAULT 1314220021721;
DECLARE shard_id INT DEFAULT 1;

SET now_millis = (SELECT UNIX_TIMESTAMP(NOW(3)) * 1000);
SET seq_id = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = "dbname" AND TABLE_NAME = "tablename");
SET NEW.id = (SELECT ((now_millis - our_epoch) << 23) | (shard_id << 10) | (SELECT MOD(seq_id, 1024)));
END

A tabela é mais ou menos assim:

CREATE TABLE tablename (
    id BIGINT AUTO_INCREMENT,
    ...
)

Pergunta, questão:

Há um problema de simultaneidade aqui. Ao gerar 100 threads e executar inserções, estou recebendo valores de sequência duplicados, o que significa que dois gatilhos estão obtendo o mesmo valor de incremento automático. Como posso consertar isso?

Tentei criar uma nova tabela, por exemplo "tablename_seq", com uma linha, um contador para armazenar meus próprios valores de incremento automático e, em seguida, fazer atualizações nessa tabela dentro do TRIGGER, mas o problema é que não consigo LOCK a tabela em um Procedimento Armazenado (gatilho), então tenho o exatamente o mesmo problema, não posso garantir que um contador seja único entre os gatilhos :(.

Estou perplexo e realmente gostaria de receber dicas!

Solução possível:

O MySQL 5.6 possui UUID_SHORT (), que gera valores incrementais únicos, que são garantidos como únicos. Na prática, ao chamar isso, parece que cada chamada aumenta o valor +1. Usando: SET seq_id = (SELECT UUID_SHORT ()); parece remover o problema de simultaneidade. O efeito colateral disso é que agora (aproximadamente) não mais que 1024 pastilhas podem acontecer por milissegundo em todo o sistema. Se houver mais, é possível que haja um erro DUPLICATE PRIMARY KEY. A boa notícia é que, nos benchmarks da minha máquina, recebo ~ 3.000 inserções / s com ou sem o gatilho que contém UUID_SHORT (), para que não pareça retardá-lo.

questionAnswers(2)

yourAnswerToTheQuestion