Actualización [2017]: 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 superior, la tabla permanece disponible para operaciones de lectura y escritura mientras se crea o quita el índice. La instrucció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, la modificación de la tabla mientras se creaba o quitaba un índice normalmente provocaba un interbloqueo que cancelaba la instrucción INSERT, UPDATE o DELETE en la tabla.
[2015] Actualización de tablas de índices de escritura de bloques en MySQL 5.5
De la respuesta anterior:
"Si utiliza una versión superior a 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 **** FALSE **** (al menos para las tablas MyISAM / InnoDB, que es lo que usa el 99,999% de la gente. Clustered Edition es diferente).
Hacer operaciones de ACTUALIZAR en una tabla se BLOQUEARÁ mientras se crea el índice. MySQL es muy, muy estúpido sobre 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 ~ 400ms que se necesitan para 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 (intercambie 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 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 Master B. Se retrasará durante la actualización
- Deje que el Maestro B se ponga al día. Invariante: su cambio de esquema DEBE ser capaz de procesar comandos replicados desde un esquema de versión descendente. Los cambios de indexación califican. Las adiciones de columnas simples generalmente califican. ¿Eliminar una columna? Probablemente no.
- Cambie ATÓMICAMENTE todos los clientes de Master A a Master B. Si desea estar seguro (confíe en mí, lo hace), debe asegurarse de que la última escritura en A se repita en B ANTESB toma su primera escritura. Si permite escrituras simultáneas a más de 2 maestros, ... comprenderá mejor la replicación de MySQL a un nivel PROFUNDO o se dirigirá a un mundo de dolor. Dolor extremo. ¿Tiene 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 que la replicación de MySQL "hará 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 a todos los clientes del antiguo maestro y cambiarlos 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ó.
- Repite el proceso con el Maestro A, actualizando su esquema para que se convierta en tu nuevo maestro secundario, listo para asumir el control en caso de que tu maestro primario (el maestro B ahora) pierda poder o simplemente muera sobre ti.
Una manera fácil de actualizar el esquema no lo es. Funcionable en un entorno de producción serio; sí lo es. Por favor, por favor, por favor, si hay una manera más fácil de agregar un índice a una tabla MySQL sin bloquear escrituras, hágamelo saber.
Buscar en Google me llevó a este artículo que describe una técnica similar. Aún mejor, recomiendan 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 que vinculé anteriormente habla sobre una herramienta, pt-online-schema-change , que funciona de la siguiente manera:
- Crea una nueva tabla con la misma estructura que la original.
- Actualice el esquema en una nueva tabla.
- Agregue un disparador en la tabla original para que los cambios se mantengan sincronizados con la copia
- Copie filas en lotes de la tabla original.
- Mueva la mesa original a un lado y reemplácela por una nueva.
- Suelta la mesa vieja.
Yo nunca probé la herramienta. YMMV
RDS
Actualmente estoy usando MySQL a través del RDS de Amazon . Es un servicio realmente ingenioso que concluye 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 tienes acceso SUPER a la base de datos, por lo que no puedes jugar con 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 cambios en el esquema en un esclavo de solo lectura y luego promover ese esclavo para que se convierta en su nuevo maestro. Exactamente el mismo truco que describí anteriormente, pero 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.