sql >> Base de Datos >  >> RDS >> Mysql

Cree un índice en una gran tabla de producción de MySQL sin bloqueo de tabla

[2017] Actualización:MySQL 5.6 admite actualizaciones de índices en línea

https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html#online-ddl-index-syntax-notes

En MySQL 5.6 y versiones posteriores, la tabla permanece disponible para operaciones de lectura y escritura mientras se crea o elimina el índice. La declaración CREATE INDEX o DROP INDEX solo finaliza después de que se completan todas las transacciones que acceden a la tabla, de modo que el estado inicial del índice refleja el contenido más reciente de la tabla. Anteriormente, modificar la tabla mientras se creaba o eliminaba un índice generalmente generaba un interbloqueo que cancelaba la instrucción INSERT, UPDATE o DELETE en la tabla.

[2015] Actualización de escrituras de bloques de índices de tablas en MySQL 5.5

De la respuesta anterior:

"Si usa una versión superior a la 5.1, los índices se crean mientras la base de datos está en línea. No se preocupe, no interrumpirá el uso del sistema de producción".

Esto es ****FALSO**** (al menos para las tablas MyISAM/InnoDB, que es lo que usa el 99,999 % de las personas. La edición agrupada es diferente).

Hacer operaciones de ACTUALIZACIÓN en una tabla BLOQUEAR mientras se crea el índice. MySQL es realmente estúpido acerca de esto (y algunas otras cosas).

Guión de prueba:

(   
  for n in {1..50}; do
    #(time mysql -uroot -e 'select  * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
    (time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
  done
) | cat -n &
PID=$!
sleep 0.05
echo "Index Update - START"
mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'
echo "Index Update - FINISH"
sleep 0.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'

Mi servidor (InnoDB):

Server version: 5.5.25a Source distribution

Salida (observe cómo la sexta operación se bloquea durante los ~400 ms que tarda en finalizar la actualización del índice):

 1  real    0m0.009s
 2  real    0m0.009s
 3  real    0m0.009s
 4  real    0m0.012s
 5  real    0m0.009s
Index Update - START
Index Update - FINISH
 6  real    0m0.388s
 7  real    0m0.009s
 8  real    0m0.009s
 9  real    0m0.009s
10  real    0m0.009s
11  real    0m0.009s

Vs operaciones de lectura que no bloquean (cambiar el comentario de línea en el script):

 1  real    0m0.010s
 2  real    0m0.009s
 3  real    0m0.009s
 4  real    0m0.010s
 5  real    0m0.009s
Index Update - START
 6  real    0m0.010s
 7  real    0m0.010s
 8  real    0m0.011s
 9  real    0m0.010s
...
41  real    0m0.009s
42  real    0m0.010s
43  real    0m0.009s
Index Update - FINISH
44  real    0m0.012s
45  real    0m0.009s
46  real    0m0.009s
47  real    0m0.010s
48  real    0m0.009s

Actualización del esquema de MySQL sin tiempo de inactividad

Hasta ahora, solo conozco un método para actualizar un esquema MySql y no sufrir una interrupción de la disponibilidad. Maestros circulares:

  • Master A tiene su base de datos MySQL ejecutándose
  • Ponga en servicio el Maestro B y haga que replique las escrituras del Maestro A (B es un esclavo de A)
  • Realice la actualización del esquema en el Maestro B. Se retrasará durante la actualización
  • Deja que el Amo B se ponga al día. Invariable:su cambio de esquema DEBE ser capaz de procesar comandos replicados desde un esquema de versión anterior. Los cambios de indexación califican. Las adiciones de columnas simples generalmente califican. ¿Quitar una columna? probablemente no.
  • Intercambie ATOMICAMENTE todos los clientes del maestro A al maestro B. Si quiere estar seguro (créame, lo desea), debe asegurarse de que la última escritura en A se replique en B ANTES B toma su primera escritura. Si permite escrituras simultáneas a más de 2 maestros, ... es mejor que comprenda la replicación de MySQL a un nivel PROFUNDO o se dirigirá a un mundo de dolor. Dolor extremo. Me gusta, ¿tienes una columna que es AUTOINCREMENT? estás jodido (a menos que uses números pares en un maestro y probabilidades en el otro). NO confíe en la replicación de MySQL para "hacer lo correcto". NO es inteligente y no te salvará. Es un poco menos seguro que copiar registros de transacciones binarias desde la línea de comandos y reproducirlos a mano. Aún así, desconectar todos los clientes del antiguo maestro y pasarlos al nuevo maestro se puede hacer en cuestión de segundos, mucho más rápido que esperar una actualización de esquema de varias horas.
  • Ahora el Maestro B es tu nuevo maestro. Tienes el nuevo esquema. La vida es buena. Toma una cerveza; lo peor ya pasó.
  • Repita el proceso con el Maestro A, actualizando su esquema para que se convierta en su nuevo maestro secundario, listo para tomar el control en caso de que su maestro principal (ahora el maestro B) pierda energía o simplemente fallezca sobre usted.

Una manera fácil de actualizar el esquema no lo es. Viable en un entorno de producción serio; sí lo es. Por favor, por favor, si hay una manera más fácil de agregar un índice a una tabla MySQL sin bloquear las escrituras, házmelo saber.

Buscar en Google me llevó a este artículo que describe una técnica similar. Aún mejor, aconsejan beber en el mismo punto del procedimiento (¡Tenga en cuenta que escribí mi respuesta antes de leer el artículo)!

pt-online-schema-change de Percona

El artículo Enlacé arriba habla de una herramienta, pt -cambio-de-esquema-en-línea , que funciona de la siguiente manera:

  • Cree una nueva mesa con la misma estructura que la original.
  • Actualizar el esquema en la nueva tabla.
  • Agregue un activador en la tabla original para que los cambios se mantengan sincronizados con la copia
  • Copiar filas en lotes de la tabla original.
  • Quite la mesa original y reemplácela con una nueva.
  • Dejar la mesa vieja.

Nunca he probado la herramienta yo mismo. YMMV

RDS

Actualmente estoy usando MySQL a través de RDS de Amazon . Es un servicio realmente ingenioso que envuelve y administra MySQL, lo que le permite agregar nuevas réplicas de lectura con un solo botón y actualizar de forma transparente la base de datos en todos los SKU de hardware. Es realmente conveniente. No obtiene acceso SUPER a la base de datos, por lo que no puede arruinar la replicación directamente (¿es esto una bendición o una maldición?). Sin embargo, puede usar Promoción de réplica de lectura para realizar sus cambios de esquema en un esclavo de solo lectura, luego promueva ese esclavo para que se convierta en su nuevo maestro. Exactamente el mismo truco que describí anteriormente, solo que mucho más fácil de ejecutar. Todavía no hacen mucho para ayudarte con el corte. Tienes que reconfigurar y reiniciar tu aplicación.