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.
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