¿Alguna forma de seleccionar sin provocar bloqueo en MySQL?
Consulta:
SELECT COUNT(online.account_id) cnt from online;
Pero la tabla en línea también se modifica mediante un evento, por lo que con frecuencia puedo ver el bloqueo al ejecutar show processlist
.
¿Existe alguna gramática en MySQL que pueda hacer que la declaración de selección no cause bloqueos?
Y olvidé mencionar arriba que está en una base de datos esclava MySQL.
Después de agregarlo al my.cnf:transaction-isolation = READ-UNCOMMITTED
esclavo, aparecerá el error:
Error 'No es posible el registro binario. Mensaje: El nivel de transacción 'LECTURA NO COMPROMETIDA' en InnoDB no es seguro para el modo binlog 'DECLARACIÓN' en la consulta
Entonces, ¿existe una forma compatible de hacer esto?
Encontré un artículo titulado "MYSQL CON NOLOCK"
https://web.archive.org/web/20100814144042/http://sqldba.org/articles/22-mysql-with-nolock.aspx
en MS SQL Server haría lo siguiente:
SELECT * FROM TABLE_NAME WITH (nolock)
y el equivalente de MySQL es
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
EDITAR
Michael Mior sugirió lo siguiente (de los comentarios)
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
COMMIT ;
Si la tabla es InnoDB, consulte http://dev.mysql.com/doc/refman/5.1/en/innodb-consistent-read.html : utiliza lectura consistente (modo sin bloqueo) para SELECT "que no No especifique FOR UPDATE o LOCK IN SHARE MODE si la opción innodb_locks_unsafe_for_binlog está configurada y el nivel de aislamiento de la transacción no está configurado en SERIALIZABLE. Por lo tanto, no se establecen bloqueos en las filas leídas de la tabla seleccionada".
Usar
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
Los documentos de la versión 5.0 están aquí .
Los documentos de la versión 5.1 están aquí .
Citando los documentos vinculados: Configuración de las características de la transacción (como se muestra arriba)...Sin ninguna palabra clave SESSION o GLOBAL:
La declaración se aplica sólo a la siguiente transacción realizada dentro de la sesión.
Las transacciones posteriores vuelven a utilizar el valor de sesión de las características nombradas.
La declaración no está permitida dentro de las transacciones.
Otra forma de habilitar la lectura sucia en MySQL es agregar una pista: BLOQUEAR EN MODO COMPARTIR
SELECT * FROM TABLE_NAME LOCK IN SHARE MODE;
Dependiendo de su tipo de tabla, el bloqueo se realizará de manera diferente, pero también lo hará un recuento SELECT. Para tablas MyISAM, una simple tabla SELECT count(*) FROM no debería bloquear la tabla ya que accede a metadatos para extraer el recuento de registros. Innodb tardará más ya que tiene que tomar la tabla en una instantánea para contar los registros, pero no debería provocar un bloqueo.
Al menos deberías tener concurrent_insert establecido en 1 (predeterminado). Luego, si no hay "espacios en blanco" en el archivo de datos para que la tabla los complete, se agregarán inserciones al archivo y las SELECT e INSERT pueden ocurrir simultáneamente con las tablas MyISAM. Tenga en cuenta que eliminar un registro crea un "espacio" en el archivo de datos que intentará llenarse con futuras inserciones y actualizaciones.
Si rara vez elimina registros, puede establecer concurrent_insert en 2 y las inserciones siempre se agregarán al final del archivo de datos. Luego, las selecciones e inserciones pueden ocurrir simultáneamente, pero su archivo de datos nunca se hará más pequeño, sin importar cuántos registros elimine (excepto todos los registros).
En resumen, si tiene muchas actualizaciones, inserciones y selecciones en una tabla, debe convertirla en InnoDB. Sin embargo, puedes mezclar libremente tipos de tablas en un sistema.