2011-08-15 8 views
6

Digamos que estaba escribiendo una aplicación donde debería obtener notificaciones en tiempo real de un servidor, y digamos que esas notificaciones se almacenan en una base de datos mysql. para que consiga que tendría que mantener el sondeo del servidor MySQL (seguir repitiendo el mismo seleccione consulta hasta que realmente obtener resultados) pero calculo que es una forma muy ineficiente de hacerlo ya que la mayoría de las veces el selecto convertiría hasta vacio. Si lo hago a menudo es una tensión irracional en el servidor si lo hago rara vez las notificaciones llegarían muy tarde. así que me preguntaba si hay una manera para que digamos una consulta mysql para bloquear hasta obtener un resultado que coincide con una condición de que se disponga.¿Hay alguna forma de que MySQL espere a que se inserten las filas que coincidan con una condición?

list = query ("SELECT * FROM `notifications` WHERE `unread`=1") ; 

en lugar de devolver una lista vacía si no hay notificaciones no leídas, sería en cambio esperar hasta que realmente hay notificaciones no leídas para volver

Respuesta

8

le recomiendo usar el patrón producer consumer, implementados con una nueva tabla como el "cola de trabajo". No hay necesidad de un procedimiento almacenado, porque el desencadenador es tan simple.

  1. Un disparador sería poblar la cola de trabajo
  2. código sería sondear la tabla cola de trabajo. Como la tabla sería muy pequeña, la consulta sería rápida y de poca carga.
  3. Código haría todo lo que necesita y eliminar filas de la mesa cuando haya terminado - manteniéndolo lo más pequeño posible

Crear una tabla con el id de la notification para ser procesado y una columna "estado de tramitación", por ejemplo:

create table work_queue (
    id int not null auto_increment, 
    notification_id int references notifications, 
    status enum ('ready', 'processing', 'failed') 
); 

crear un disparador simple que rellena una tabla de la cola de trabajo:

delimiter $ 
create trigger producer after insert on notifications 
for each row begin 
    insert into work_queue (notification_id, status) 
    select new.id, 'ready' 
    where new.unread; 
end; $ 
delimiter ; 

Su bacalao e tendría el pseudo código:

  1. select * from work_queue where status = 'ready' order by id limit 1
  2. update work_queue set status = 'processing' where id = <row.id>
  3. hacer lo que tiene a notifications where id = <row.notification_id>
  4. ya sea delete from work_queue where id = <row.id> o update work_queue set status = 'failed' where id = <row.id> (que tendrá que averiguar qué hacer con los objetos fallidos)
  5. Dormir 1 segundo (esta pausa debe ser aproximadamente la misma que la tasa de llegada máxima de notificaciones; deberá sintonizar esto para equilibrar entre el tamaño de la cola de trabajo y la carga del servidor)
  6. Goto 1.

Si usted tiene un solo proceso de votación, no hay necesidad de preocupaciones de bloqueo. Si tiene múltiples procesos de sondeo, tendrá que manejar las condiciones de carrera.

+0

idea interesante, supongo que no hay otra manera más que sondear, gracias por la respuesta :) –

+0

no hay otra manera, por lo que desea hacer su encuesta lo más rápido posible.Tengo que decir que son los 10 puntos más duros de reputación que he ganado :) – Bohemian

+0

supongo que usar una tabla de memoria podría ser un buen impulso aquí –

Cuestiones relacionadas