¿Es posible (y cómo) convertir una gran tabla MyISAM en InnoDB sin desconectar la aplicación? Requiere insertar un par de filas en esa tabla cada segundo, pero es posible suspenderla durante aproximadamente 2 minutos.
Obviamente ALTER TABLE ... engine = innodb no funcionará. Por lo tanto, tenía el plan de crear una nueva tabla con el motor innodb y copiar el contenido en ella. Y al final, suspenda el hilo de registro de la aplicación y RENAME TABLE.
Desafortunadamente, incluso copiar en lotes pequeños de 100 filas genera un retraso significativo después de un tiempo.
Editar : las filas existentes nunca cambian, esta tabla se utiliza para iniciar sesión.
Respuestas:
Cree una configuración Master-Master de la siguiente manera:
logTable
logTable_new
como innodbINSERT INTO logTable_new SELECT * FROM logTable
(psuedocode) en MasterB, que envía la replicación a MasterAlogTable_new
en MasterA termine de sincronizarse, cambie las tablasfuente
Dada la restricción de:
Mientras realiza el registro, si tiene una buena manera de establecer un marcador para que pueda saber en qué momento comienza el proceso, de modo que pueda volver a aplicar los registros o hacer que los registros se escriban en un archivo de texto para luego puedes ingerirlos con
LOAD DATA INFILE
Parte del problema es que escribir en lotes más pequeños significa que los índices tienen que ser recalculados una y otra vez; es mejor que lo ejecute todo de una vez, pero esto podría causar un retraso 'notable' en el sistema ... pero no tiene que hacerlo en su servidor de producción.
LOAD DATA INFILE
)fuente
¿Está agregando algún retraso entre cada lote, o simplemente agrupando las actualizaciones y ejecutando cada lote directamente después del anterior?
Si es así, intente escribir la conversión en su idioma favorito con algo como:
Esto debería garantizar que la conversión no tome más de más o menos la mitad de la capacidad de su servidor, incluso permitiendo diferencias en la carga impuesta ya que el uso del sistema varía con el tiempo.
O bien, si desea utilizar la mayor cantidad de tiempo posible cuando el servicio está relativamente inactivo pero retrocediendo (posiblemente haciendo una pausa durante un período de tiempo bastante prolongado) cuando la base de datos necesita hacer algún trabajo para sus usuarios, reemplácela
sleep for as long as the update took
conif the server's load is above <upper measure>, sleep for some seconds then check again, loop around the sleep/check until the load drops below <lower measure>
. Esto significará que puede avanzar en tiempos de silencio, pero se detendrá por completo cuando el servidor esté ocupado realizando su carga de trabajo normal. La determinación de la carga dependerá de su sistema operativo: en Linux y similar, el valor promedio de carga de 1 minuto de/proc/loadavg
o la salida deuptime
debería hacer.<lower measure>
y<upper measure>
puede ser el mismo valor, aunque es habitual en controles como este tener una diferencia para que su proceso no continúe iniciando y luego pausando inmediatamente debido a que su propio reinicio influye en la medida de carga.Por supuesto, esto no funcionaría para las tablas donde las filas antiguas pueden modificarse, pero funcionará bien para una tabla de registro como la que usted describe.
Deberá ignorar la sabiduría habitual de crear índices después de llenar la nueva tabla en este caso. Si bien eso es más eficiente cuando desea que las cosas sean lo más rápido posible (el efecto sobre el resto del sistema sea condenado), en este caso no desea el gran exceso de carga al final del proceso como el los índices se crean completamente de una vez, ya que este es un proceso que no puede pausar cuando las cosas se llenan.
fuente
Algo como esto funcionaría?
$auto_increment
tabla de registromytable
no cambie).$auto_increment
valor usandoSHOW TABLE STATUS LIKE 'mytable'
.CREATE TABLE mytable_new LIKE mytable
ALTER TABLE mytable_new AUTO_INCREMENT=$auto_increment ENGINE=Innodb
RENAME TABLE mytable TO mytable_old, mytable_new TO mytable
INSERT INTO mytable SELECT * FROM mytable_old
.Puede hacer el paso 7 en lotes o en una declaración, ya que no debería estar bloqueando el registro normal.
fuente