Pergunta

Estamos usando o MySQL com motor de armazenamento InnoDB e transações muito, e nós funcionamos em um problema: precisamos de uma boa maneira de imitar seqüências da Oracle no MySQL. Os requisitos são: - suporte a concorrência - a segurança de transações - desempenho máximo (ou seja, minimizando bloqueios e impasses)

Não importa se alguns dos valores não serão utilizados, ou seja, as lacunas na seqüência são ok. Existe uma maneira fácil de archieve que através da criação de uma tabela InnoDB separado com um contador, no entanto, isso significa que ele vai participar na transação e irá introduzir fechaduras e esperando. Estou pensando em tentar uma tabela MyISAM com fechaduras manuais, outras ideias ou melhores práticas?

Foi útil?

Solução

Se auto-incremento não é bom o suficiente para suas necessidades, você pode criar um mecanismo seqüência atômica com n seqüências nomeadas como este:

Criar uma tabela para armazenar suas sequências:

CREATE TABLE sequence (
  seq_name varchar(20) unique not null,
  seq_current unsigned int not null
);

Supondo que você tenha uma linha para 'foo' na tabela pode atomicamente obter o próximo ID de sequência como esta:

UPDATE sequence SET seq_current = (@next := seq_current + 1) WHERE seq_name = 'foo';
SELECT @next;

Não locks necessário. Ambas as declarações precisam ser executados na mesma sessão, de modo que o @next variável local é realmente definido quando o seleto acontece.

Outras dicas

A maneira certa de fazer isso é dado no MySQL manual do :

UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();

Somos uma empresa de jogos de alta transação e precisa este tipo de soluções para nossas necessidades. Uma das características das sequências da Oracle também foi o valor de incremento que também poderia ser definido.

O uso de soluções DUPLICATE KEY.

CREATE TABLE sequences (
  id BIGINT DEFAULT 1,
  name CHAR(20),
  increment TINYINT,
  UNIQUE KEY(name)
);

Para obter o índice seguinte:

Abstract o seguinte com um procedimento armazenado ou um sp_seq_next_val(VARCHAR) função:

INSERT INTO sequences (name) VALUES ("user_id") ON DUPLICATE KEY UPDATE id = id + increment;<br/>
SELECT id FROM sequences WHERE name = "user_id";

Será que não a coluna MySQL Identidade no punho tabela isso?

CREATE TABLE table_name ( id INTEIRO AUTO_INCREMENT PRIMARY KEY )

Ou você está olhando para usá-lo para algo que não seja apenas a inserção em outra tabela?

Se você estiver escrevendo usando uma linguagem processual, bem como (em vez de apenas SQL), em seguida, a outra opção seria criar uma tabela contendo um único inteiro (ou inteiro longo) valor e um procedimento armazenado que trancou-a, seleccionados a partir de -lo, incrementado-lo e abriu-a antes de retornar o valor.

(Nota - sempre incrementar antes de retornar o valor - é maximizar a chance de não obter duplicatas se houver erros -. Ou envolva a coisa toda em uma transação)

Você, então, chamar isso de forma independente de sua inserção principal / atualização (para que ele não seja pego em todas as transações criadas automaticamente pelo mecanismo de chamada) e, em seguida, passá-lo como um parâmetro para onde quer que você usá-lo.

Porque é independente do resto das coisas que você está fazendo isso deve ser rápida e problemas evitar o bloqueio. Mesmo se você não ver um erro causado pelo bloqueio (improvável, a menos que você está sobrecarregando o banco de dados), você poderia chamá-lo uma segunda / terceira vez.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top