2009-07-10 9 views
5

Estoy desarrollando una aplicación web multi-tenant usando LAMP. Todos mis datos de sesión de usuario están actualmente almacenados en mysql con el tipo de tabla InnoDB.MySQL Session Table Approach

¿Hay alguna forma de que pueda usar el tipo de tabla MEMORY (solía ser HEAP) para almacenar las sesiones actuales y usar la función de recolector de elementos no utilizados del controlador de sesión para mover sesiones entre InnoDB (tabla normal) y (en) Tabla de MEMORIA?

¿Esta configuración afectará de alguna manera cuando deseo agrupar & configuración maestro-esclavo en una etapa posterior?

Gracias de antemano, ocptime

Respuesta

6

Escribir un custom session handler es sorprendentemente fácil, pero creo que hay probablemente mejores maneras de almacenar los datos de sesión de MEMORY tablas.

Un esquema algo así como (levantado con los cambios de a previous question)

CREATE TABLE IF NOT EXISTS `session` (
    `id` char(32) NOT NULL, 
    `data` varchar(20000) NOT NULL, 
    `time_created` timestamp NOT NULL default '0000-00-00 00:00:00', 
    `time_updated` timestamp NOT NULL default '0000-00-00 00:00:00' on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `time_created` (`time_created`), 
    KEY `time_updated` (`time_updated`) 
) ENGINE=MEMORY DEFAULT CHARSET=utf8; 

entonces lo que sólo hay que definir sus funciones de controlador de sesión, como se indica en el enlace de arriba o en este tutorial. Si desea guardar la información de su sesión durante la recolección de basura, solo tendrá que crear una tabla idéntica a la anterior usando el motor INNODB y agregar un bit al final de la función gc() que copia la fila de las tablas MEMORY a INNODB.

Sin embargo, las tablas MEMORY tienen algunos límites bastante significativos. No pueden usar las columnas BLOB o TEXT - por eso tengo ese feo varchar(20000) arriba. Tienen un tamaño máximo de 16 MB. Si tiene muchos usuarios, mantiene una gran cantidad de estado o tiene problemas con la recolección de basura, puede alcanzar ese límite y bloquearse.

Una mejor idea es utilizar memcache session handler, especialmente si no necesita almacenar información de la sesión en un futuro lejano. Estoy bastante seguro de que memcached es más rápido que cualquier RDBMS (incluso con tablas MEMORY) y se adapta bien por diseño. Además, no tendrá que escribir sus propias funciones de controlador de sesión.

+1

Es posible aumentar el tamaño máximo de la tabla ajustando la variable del sistema [max_heap_table_size] (https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_max_heap_table_size). –

3
InnoDB: ~40 milliseconds Cons: (Slowest) 
MEMORY: ~22 milliseconds Cons: (16MB Max) 
MyISAM: ~25 milliseconds Cons: (Table-level locking) 

estoy usando (gs), por lo que no puede hacer Memcache, pero eso sería lo mejor.

Yo personalmente estaba considerando usar MEMORY, pero no sabía si el beneficio de rendimiento superaría el costo de los límites de tamaño, etc. Así que hice lo que todo buen programador debería hacer al optimizar: lo perfilé.

Mi página php en cuestión se almacena en caché en sabelotodo, por lo que las únicas operaciones que suceden aquí son una búsqueda de expresiones regulares en el URL y un robo de sesión de SQL para comprobar si el usuario está conectado.

De todos modos aquí están los resultados : Con InnoDB recibía ~ 40 milisegundos esperando una solicitud. (Medí esto en cromo con las herramientas de desarrollador.) Después de cambiar la tabla a MEMORIA obtuve ~ 20 milisegundos por solicitud. ¡Guauu! 50% de mejora! Pero espera ... ¿qué hay de MyISAM? Intenté eso y obtuve ~ 22-23 milisegundos por solicitud. Oh.

Esto es solo yo probándolo, no una aplicación a escala completa.Una aplicación real tendría miles de personas escribiendo en esa tabla cada segundo, y MyISAM haría el bloqueo a nivel de tabla, lo que podría ser malo (Which MySQL database engine is better for storing sessions and session data: MyISAM or InnoDB?).

Así que me estoy quedando con la memoria, por ahora. Es una gran mejora para esas páginas en caché, ¡pero te animo a que hagas un perfil! Si su sitio web está reconstruyendo cada página, los 10 milisegundos podrían no importar.

+0

¿Cómo afectaría el bloqueo de nivel de tabla al rendimiento en una aplicación de mayor escala? ¿Sería efectivamente bloquear a los usuarios cuando alguien intenta escribir en la sesión como en un inicio de sesión? – Lightbulb1

+0

@ Lightbulb1, * cada vista de página * tiene que actualizar la tabla de sesión en la base de datos para actualizar la última hora accedida (para saber cuándo caducar la sesión y cuándo las sesiones pueden recogerse como basura). Si dos personas obtienen una página al mismo tiempo, una persona tiene que esperar hasta que la escritura de la otra persona finalice porque Mysql bloquea hasta que la escritura se complete (a menos que haga una [LOW_PRIORITY] (http: //dev.mysql .com/doc/refman/5.0/es/update.html) actualización, que solucionaría el problema). Sin embargo, todo esto es solo una optimización prematura. Si tu sitio está tan ocupado, considera memcached. – andychase

+0

Gracias por la información. No he usado Memcache antes, así que es algo sobre lo que tengo que investigar más. Será la solución adecuada para el futuro. – Lightbulb1

0

Utilice la tabla InnoDB para la sesión. He escuchado que la tabla de memoria al insertar bloquea toda la tabla, mientras que InnoDB bloquea solo la fila en particular que debe manipularse.