• Publicidad

Concurrencia y consultas a MySQL

Así que programas sin strict y las expresiones regulares son otro modo de hablar. Aquí encontrarás respuestas de nivel avanzado, no recomendable para los débiles de corazón.

Concurrencia y consultas a MySQL

Notapor damian1510 » 2013-01-07 15:30 @688

Hola, estoy teniendo problemas con un script que es una especie de dæmon, en el cual se crean varios procesos que hacen diferentes acciones en una BD MySQL. El tema es que los resultado resultan ilógicos, o "explota".

Resumiendo, el programa sería básicamente esto:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
...;

while (1) {

  my $child_id = fork();
  if ($child_id) {
     ...
  }
  else {
     # Se ejecutan varios módulos según parámetros en paralelo que acceden a la BD
     # (consultas, updates, etc.)
  }
}
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Tengo una clase que se encarga de conectarse a la BD y ejecutar las queries. Algunas funciones son estas:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub connect {
  2.     my $self = shift;
  3.  
  4.     $dsn = "DBI:mysql:database=$self->{database};host=$self->{host};port=$self->{port}";
  5.  
  6.     return $db if defined $db;
  7.  
  8.     $db = DBI->connect( $dsn, $self->{user}, $self->{password}, { RaiseError => 1 } );
  9.  
  10.     $db->{mysql_auto_reconnect} = 1;
  11.     $db->{InactiveDestroy}      = 1;
  12.     $db->{'AutoCommit'}         = 1;
  13.     return $db;
  14. }
  15.  
  16. sub executeSQLUpdate {
  17.     my $self = shift;
  18.     my $sql  = shift;
  19.  
  20.     my $mySQL = $db->prepare($sql) or print "Error en prepare $sql" . $db->errstr;
  21.  
  22.     $mySQL->execute() or print "Error en execute '$sql' \n ";
  23.     $mySQL->finish();
  24.     return;
  25. }
  26.  
  27. sub getValue {
  28.     my $self = shift;
  29.     my $sql  = shift;
  30.  
  31.     $self->connect();
  32.     my $mySQL  = $db->prepare($sql) or print "Error en prepare $sql" . $db->errstr;
  33.     my $result = $mySQL->execute()  or print "can't execute the query: " . $mySQL->errstr;
  34.  
  35.     if ( $mySQL->rows == 0 ) {
  36.         return undef;
  37.     }
  38.     else {
  39.         my @element = $mySQL->fetchrow_array();
  40.         return $element[0];
  41.     }
  42. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


¿Alguna idea de cómo puedo solucionar este tema?
¡Gracias!
Última edición por explorer el 2013-01-07 17:24 @766, editado 2 veces en total
Razón: Formateado de código con Perltidy y poner marcas Perl
damian1510
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-11-07 15:28 @686

Publicidad

Re: Concurrencia y consultas a MySQL

Notapor explorer » 2013-01-07 18:07 @797

Yo activaría todos los logs y pondría print() o say() por todas partes, para saber qué está haciendo el programa en cada momento. Y mirar el log de actividad de MySQL, por supuesto, para saber qué consultas se han hecho, y cómo.

Poco más se me ocurre viendo el código, ya que yo lo veo bien...
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Concurrencia y consultas a MySQL

Notapor damian1510 » 2013-01-11 09:55 @455

¡Gracias! Eso lo venía haciendo y las consultas estaban bien, el error se genera porque al parecer la concurrencia le genera problemas a la BD, aunque esto no debería ocurrir.

Otra cosa que probé es de chequear las conexiones abiertas, pero parece está todo bien.
¿Hay algo que debería tener en cuenta y que se me esté pasando para trabajar con fork() en Perl y con el acceso al MySQL?

¡Se agradece cualquier sugerencia!
Saludos.
damian1510
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-11-07 15:28 @686

Re: Concurrencia y consultas a MySQL

Notapor explorer » 2013-01-11 23:39 @027

Pero, ¿qué problemas dice la base de datos que tiene?

¿Too many connections?

Por eso hay que ver los logs, para saber qué mensaje de error saca...

MySQL tiene una variable que indica el máximo número de conexiones simultáneas: max_connections, siendo su valor, por defecto, de 100. ¿Cuántas conexiones simultáneas pretendes hacer?

Tampoco sé a qué te refieres con la expresión "el programa explota". ¿Quieres decir que el programa Perl termina con un mensaje de error? ¿Cuál?

Otra cosa... cuando se accede a la base de datos, ¿en dónde se hace el bloqueo? Si suponemos que solo se hacen SELECT, no importa, pero si se hacen INPUT o UPDATE, la base de datos bloqueará la tabla o el registro, y durante ese tiempo, no podrá acceder nadie más.

En caso de bloquear por tabla, te recomiendo que leas la página de manual de DBD::mysql, la sección sobre mysql_auto_reconnect, ya que comenta que no es recomendable.

Atento a lo que dice el manual de DBI sobre InactiveDestroy: en un proceso con fork(), o bien el padre o bien el hijo, debe tener marcada esta acción, PERO no ambos, en todos los handles que compartan. Según el código de connect(), así debería ser...

En esa misma sección te dan una pista para realizar la traza de un proceso con fork(): aumentando el nivel de trace de DBI a 9. Cada hijo se mostrará con su correspondiente id (buscar "trace" en el manual).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Concurrencia y consultas a MySQL

Notapor damian1510 » 2013-02-19 07:16 @344

Hola, gracias por la ayuda. Después de un tiempo seguí con esto. El problema era que cuando se creaban los hijos y terminaban quedaban en <defunc>. La solución fue agregarle antes del while()

$SIG{CHLD} = 'IGNORE';

Ahora ya no tengo más problemas.

¡Saludos!
damian1510
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-11-07 15:28 @686


Volver a Avanzado

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron