• Publicidad

Multihilos con Bases de Datos

Todo acerca de las bases de datos que existen: SQL, MySQL, Oracle, Postgres, CSV, etc.

Multihilos con Bases de Datos

Notapor scuyda » 2012-07-06 18:17 @803

Buenas, los molesto por un problema que tengo al tratar de actualizar una base de datos desde distintos hilos generados.
La idea del script es dado una lista de procesos procesarlos en paralelo en una cantidad de hilos determinados (en este ejemplo 4). La idea es que cada hilo grabe en una base de datos su inicio y su fin usando una única conexión abierta en el cuerpo principal.

El error que me está dando es (handles can't be shared between threads and your driver may need a CLONE method added)

Una idea de cómo resolverlo, probé con shared la variable de conexión y me dio "Invalid value for shared scalar"

Muchas Gracias

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use threads;
  3. use DBI;
  4. use POSIX qw(strftime);
  5.  
  6. my (@thr, @flag_thr);
  7. my ($hilolibre, $maxhilos, $flag_hilo);
  8. my $CONECT_DB;
  9. my ($sth, @registro);
  10. my ($fechahora);
  11.  
  12. my $ODBCMONITOR  = "DBI:ODBC:BUE_01_SAS_Monitor";
  13. ## Genero Fecha y hora
  14. $fechahora = strftime('%Y-%m-%d %H:%M:%S', localtime(time));
  15. ## Conectar a la base de Monitoreo mediante ODBC
  16. $CONECT_DB = DBI->connect($ODBCMONITOR) ;
  17. ## Chequeo si se realizo correctamente la conexion
  18. if ($? != 0)
  19. {
  20.         my $error_code = $CONECT_DB->err;
  21.         $CONECT_DB->disconnect;
  22.         print "\n$error_code\n";
  23.         exit -1;
  24. }
  25. ## Proceso
  26. $maxhilos = 4;
  27. for (my $numeroproceso = 0; $numeroproceso <= 10; $numeroproceso ++)
  28. {
  29.     $hilolibre = -1;
  30.     $flag_hilo = 0;
  31.     while ($flag_hilo == 0)
  32.     {
  33.          $hilolibre += 1;
  34.          ## Controlo que no se ejecuten mas hilos de los parametrizados
  35.          if ($hilolibre < $maxhilos)
  36.          {
  37.               ## Si el $flag_thr[$hilolibre] no existe el hilo esta libre para uso
  38.               if (!defined($flag_thr[$hilolibre]))
  39.               {
  40.                   $flag_hilo = 1
  41.               }
  42.               else
  43.               {
  44.                    ## Si $thr[$hilolibre] existe y termino la ejecucion puedo usra el hilo
  45.                    my $isrun = $thr[$hilolibre]->is_joinable();
  46.                    if ( $flag_thr[$hilolibre] == 0 && $isrun)
  47.                    {
  48.                        my $aux = $thr[$hilolibre]->join();
  49.                        print "Hilo Finalizo $hilolibre\n";
  50.                        $flag_hilo = 1;
  51.                        $flag_thr[$hilolibre] = 1;
  52.                    }
  53.               }
  54.          }
  55.          else
  56.          {
  57.               ## LLegue al maximo de hilo vuelo a buscar desde el inicio
  58.               $hilolibre = -1;
  59.          }
  60.     }
  61.     ## Creo el hilo y levanto el flag de en ejecucion
  62.     $thr[$hilolibre] = threads->create(\&proceso, $hilolibre, $numeroproceso, $fechahora );
  63.     $flag_thr[$hilolibre] = 0;
  64. }
  65. ## Paro hasta que terminen todo los hilos
  66. $hilolibre = 0;
  67. print "Veo si terminaron todos\n";
  68. while ($hilolibre < $maxhilos)
  69. {
  70.     ## Controlo que no se ejecuten mas hilos de los parametrizados
  71.     my $isrun = $thr[$hilolibre]->is_joinable();
  72.     next if (!$isrun);
  73.     my $aux = $thr[$hilolibre]->join()if ( $flag_thr[$hilolibre] == 0 );
  74.     print "Hilo $hilolibre finalizado\n";
  75.     $hilolibre ++;
  76. }
  77. ## Cierro conexion a la base
  78. $CONECT_DB->disconnect;
  79. exit 0;
  80.  
  81.  
  82.  
  83. sub proceso
  84. {
  85.     my @Param = @_;
  86.     my $random_number = int(rand(10)) + 1;
  87.  
  88.     print "Empieza hilo Nro: $Param[0] Proceso:$Param[1] Tiempo: $random_number\n";
  89.     ## Grabo en Logs Estado de inicio del proceso
  90.     $sqlstm = "Insert into Logs values ($Param[0], $Param[1], $Param[2], 'Inicio')";
  91.     $sth = $CONECT_DB->prepare($sqlstm);
  92.     $sth->execute();
  93.     ## Simulo tiempo de proceso
  94.     sleep $random_number;
  95.     ## Actualizo en log estado de finalizacion
  96.     $sqlstm = "Update Logs set Estado = 'Finalizo' Where Proceso = $Param[1] and Fecha = $Param[2]";
  97.     $sth = $CONECT_DB->prepare($sqlstm);
  98.     $sth->execute();
  99.  
  100.     return $random_number;
  101.  }
  102.  
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4
Avatar de Usuario
scuyda
Perlero nuevo
Perlero nuevo
 
Mensajes: 4
Registrado: 2009-09-04 10:48 @492

Publicidad

Re: Multihilos con Bases de Datos

Notapor explorer » 2012-07-06 20:56 @913

Bueno, no tengo mucha idea, pero según este mensaje hay un par de soluciones. La primera es pasar el handle en el momento del create() del thread. La segunda dice que cada thread se conecte al socket de salida, que, la verdad, no sé a qué se refiere.

De todas maneras, en el propio manual de DBI dice: Handles can't be shared across threads. (sección Threads and Thread Safety de DBI).

Finalmente, dice: Using DBI with perl threads is not yet recommended for production environments.

Así que la solución es que cada thread cree su propio handle. O quizás pasar el handle en el create(). O leer el enlace que está en esa sección, porque comenta que, después de todo, su funcionamiento no es tan "ideal" como es de esperar.
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: Multihilos con Bases de Datos

Notapor scuyda » 2012-07-10 08:27 @394

Muchas gracias, voy a probar con pasarla en el create. Después comento el resultado.
Avatar de Usuario
scuyda
Perlero nuevo
Perlero nuevo
 
Mensajes: 4
Registrado: 2009-09-04 10:48 @492


Volver a Bases de datos

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 4 invitados