Pregunta

Estamos utilizando MySQL con el motor de almacenamiento InnoDB y muchas transacciones, y nos encontramos con un problema: necesitamos una buena forma de emular las SEQUENCE de Oracle en MySQL. Los requisitos son:  - soporte de concurrencia  - seguridad de transacción  - Máximo rendimiento (lo que significa minimizar bloqueos y puntos muertos)

No nos importa si algunos de los valores no se utilizarán, es decir, los huecos en la secuencia están bien. Hay una forma fácil de archivar que al crear una tabla InnoDB separada con un contador, sin embargo, esto significa que participará en la transacción e introducirá bloqueos y la espera. Estoy pensando en probar una mesa MyISAM con bloqueos manuales, ¿alguna otra idea o las mejores prácticas?

¿Fue útil?

Solución

Si el incremento automático no es lo suficientemente bueno para sus necesidades, puede crear un mecanismo de secuencia atómica con n secuencias nombradas como esta:

Crea una tabla para almacenar tus secuencias:

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

Suponiendo que tienes una fila para 'foo' en la tabla, puedes obtener atómicamente la siguiente identificación de secuencia como esta:

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

No se requieren bloqueos. Ambas instrucciones deben ejecutarse en la misma sesión, de modo que la variable local @next se defina realmente cuando se produce la selección.

Otros consejos

La forma correcta de hacerlo se encuentra en Manual de MySQL :

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

Somos una empresa de juegos de transacciones de alta y necesitamos este tipo de soluciones para nuestras necesidades. Una de las características de las secuencias de Oracle fue también el valor de incremento que también se podría establecer.

La solución utiliza DUPLICATE KEY .

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

Para obtener el siguiente índice:

Resuma lo siguiente con un procedimiento almacenado o una función sp_seq_next_val (VARCHAR) :

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

¿No manejará esto la columna de identidad de MySQL en la tabla?

CREATE TABLE table_name (    ID INTEGER AUTO_INCREMENT PRIMARY KEY )

¿O está buscando usarlo para otra cosa que no sea simplemente insertarlo en otra tabla?

Si también está escribiendo usando un lenguaje de procedimiento (en lugar de solo SQL), la otra opción sería crear una tabla que contenga un único valor entero (o entero largo) y un procedimiento almacenado que lo bloquee, seleccionado de lo incrementó y lo desbloqueó antes de devolver el valor.

(Nota: siempre incremente antes de devolver el valor; maximiza la posibilidad de no obtener duplicados si hay errores, o envuelva todo en una transacción).

Luego lo llamará independientemente de su inserción / actualización principal (para que no quede atrapado en ninguna transacción creada automáticamente por el mecanismo de llamada) y luego la pase como un parámetro a cualquier lugar donde desee usarla.

Debido a que es independiente del resto de las cosas que estás haciendo, debería ser rápido y evitar los problemas de bloqueo. Incluso si vio un error causado por el bloqueo (es poco probable que no esté sobrecargando la base de datos), podría llamarlo una segunda / tercera vez.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top