2012-09-01 15 views
5

Tengo una gran transacción que consiste en obtener muchos datos de la base de datos A, hacer algunas manipulaciones con estos datos y luego insertar los datos manipulados en la base de datos B. Solo tengo permisos para seleccionar en la base de datos A pero puedo crear tablas e insertar/actualizar, etc. en la base de datos B.manejo de grandes transacciones largas con perl dbi

La parte de manipulación e inserción está escrita en perl y ya está en uso para cargar datos en la base de datos B de otras fuentes de datos, así que todo eso requerido es obtener los datos necesarios de la base de datos A y usarlos para inicializar las clases perl.

¿Cómo puedo hacer esto para poder rastrear y recuperar fácilmente desde donde ocurrió el error si ocurre algún error durante los procedimientos de manipulación o inserción (desconexión de la base de datos, problemas con la inicialización de clase debido a valores no válidos, disco duro falla, etc.)? Hacer la transacción de una vez no parece una buena opción porque la cantidad de datos de la base de datos A significa que tomaría al menos un día o 2 para la manipulación de datos y la inserción en la base de datos B.

Los datos de la base de datos A pueden agruparse en alrededor de 1000 grupos usando claves únicas, con cada clave conteniendo miles de filas cada una. Una forma en que pensé que podía hacer era escribir un script que realiza commits por grupo, lo que significa que tengo que rastrear qué grupo ya se ha insertado en la base de datos B. La única forma en que puedo pensar es seguir el progreso de qué grupos tienen ha sido procesado o no está en un archivo de registro o en una tabla en la base de datos B. Una segunda forma que pensé que podría funcionar es volcar todos los campos necesarios para cargar las clases para su manipulación e inserción en un archivo plano, leer el archivo para inicializar las clases e insertar en la base de datos B. Esto también significa que tengo que hacer un poco de registro, pero debe limitarlo a la fila exacta en el archivo plano si ocurre algún error. El script se verá algo como esto:

use strict; 
use warnings; 
use DBI; 

#connect to database A 
my $dbh = DBI->connect('dbi:oracle:my_db', $user, $password, { RaiseError => 1, AutoCommit => 0 }); 

#statement to get data based on group unique key 
my $sth = $dbh->prepare($my_sql); 

my @groups; #I have a list of this already 

open my $fh, '>>', 'my_logfile' or die "can't open logfile $!"; 

eval { 
    foreach my $g (@groups){ 
     #subroutine to check if group has already been processed, either from log file or from database table 
     next if is_processed($g); 

     $sth->execute($g); 
     my $data = $sth->fetchall_arrayref; 

     #manipulate $data, then use it to load perl classes for insertion into database B 
     #. 
     #. 
     #. 
    } 
    print $fh "$g\n"; 
}; 
if ([email protected]){ 
    $dbh->rollback; 
    die "something wrong...rollback"; 
} 

Así que si no se produce algún error, sólo puede ejecutar este script de nuevo y debe saltar los grupos o filas que se han procesado y continuar.

Ambos métodos son solo variaciones sobre el mismo tema, y ​​ambos requieren volver al lugar donde he estado siguiendo mi progreso (en tabla o archivo), omitir los que se han comprometido con la base de datos B y procesar el datos restantes.

Estoy seguro de que hay una mejor manera de hacerlo, pero estoy luchando por pensar en otras soluciones. ¿Hay alguna otra forma de manejar transacciones grandes entre bases de datos que requieren manipulación de datos entre sacar datos de uno e insertarlos en otro? El proceso no necesita ser todo en Perl, siempre que pueda reutilizar las clases de Perl para manipular e insertar los datos en la base de datos.

Respuesta

2

Lamento decirlo pero realmente no veo cómo podría posiblemente resolver este problema tomando un atajo. A mí me suena como que ha pesar de las formas más razonables:

  • Guardar el estado de alguna tabla temporal/archivo (Me miro en "perldoc -f lazo", o SQLite) en cada paso
  • errores manejar adecuadamente TryCatch.pm, eval o lo que usted prefiere
  • registrar sus errores correctamente, es decir, los registros estructurados se puede leer en
  • Agregue un poco de la bandera de "hoja de vida" a la secuencia de comandos que se lee en el registro y los datos y los intentos anteriores de nuevo

Este i Probablemente esté siguiendo las líneas que ha estado pensando, pero como dije, no creo que haya una manera general "correcta" para manejar su problema.

+0

gracias por los comentarios, solo quería ver si había alguna alternativa en caso de que estuviese pensando demasiado estrecha y extrañara algo más simple/obvio – 1stdayonthejob

Cuestiones relacionadas