Comprobar una migración con recuentos y hashes

25 minIntermedio

Para saber si una migración salió bien, comparas cada colección de MongoDB y de TeselaDB con su recuento, una suma y un hash de sus documentos.

Antes de mover el tráfico a TeselaDB, comprueba que cada colección tiene los mismos documentos que en MongoDB. Lanzas las mismas consultas de solo lectura contra los dos y comparas lo que devuelven.

Lo que vas a construir

Un script de mongosh que da, para cada colección, su recuento, la suma de un campo numérico y un hash SHA-256 de todos sus documentos en orden de _id. Si los tres valores coinciden en MongoDB y en TeselaDB, la colección se copió entera.

Requisitos

  • Los dos lados de la migración de Migrar desde MongoDB: el MongoDB de origen en el puerto 27018 y TeselaDB con su cadena en TESELADB_URI, o tus propios servidores con acceso de lectura.
  • Que las escrituras en MongoDB estén paradas, o una copia hecha con --oplog y aplicada con --oplogReplay.

1. Recuento y suma

La suma de un campo numérico detecta documentos que faltan o que cambiaron, y cuesta una sola agregación:

JavaScript
db.pedidos.aggregate([{ $group: { _id: null, n: { $sum: 1 }, total: { $sum: "$total" } } }]);

2. Hash de cada colección

El hash recorre los documentos en orden de _id y los pasa a Extended JSON canónico, así que cambia si cambia cualquier campo de cualquier documento, aunque el recuento y la suma del paso anterior sigan coincidiendo:

JavaScript
const crypto = require("crypto");
const hash = crypto.createHash("sha256");
db.pedidos
  .find()
  .sort({ _id: 1 })
  .forEach((doc) => hash.update(EJSON.stringify(doc, { relaxed: false })));
print(hash.digest("hex"));

Con una colección vacía, el hash es el de una entrada vacía, el SHA-256 de cero bytes, que es lo que escribe el ejemplo cuando pedidos no tiene documentos:

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Probarlo

Shell
cat > verificar.js <<'EOF'
db = db.getSiblingDB("tienda");
printjson(db.pedidos.aggregate([{ $group: { _id: null, n: { $sum: 1 }, total: { $sum: "$total" } } }]).toArray());
const crypto = require("crypto");
const hash = crypto.createHash("sha256");
db.pedidos
  .find()
  .sort({ _id: 1 })
  .forEach((doc) => hash.update(EJSON.stringify(doc, { relaxed: false })));
print(hash.digest("hex"));
EOF
mongosh "mongodb://127.0.0.1:27018/" --quiet --file verificar.js
mongosh "$TESELADB_URI" --quiet --file verificar.js

Las órdenes juntan los dos bloques en un fichero, con una primera línea que elige la base de la migración, y lo lanzan contra los dos lados, donde los recuentos, las sumas y los hashes tienen que coincidir. Con los tres pedidos de prueba, los dos lados dan n: 3, total: 97 y el mismo hash. Repite con cada colección. Si un hash no coincide y el recuento sí, busca el documento distinto partiendo la colección por rangos de _id y comparando el hash de cada parte.

Limpiar

Las comprobaciones solo leen, así que no dejan nada en ninguna de las dos bases. Borra el fichero del script con la orden de abajo y limpia los contenedores con la guía de migración.

Shell
rm verificar.js

Siguientes pasos