2016-05-16 12 views
1

Mein Nodejs-Projekt verwendet derzeit node-mysql.Nodejs - Knoten-Mysql-Transaktion mit einer Schleife

Ich habe ein mehrstufiges Datenarray, das ich in mehrere Tabellen einfügen möchte. Transaktion ist das, woran ich gedacht habe, um mein Ziel zu erreichen. Im Folgenden finden Sie die Umrisse meines Codes:

const mysql = require("mysql") 
const pool = mysql.createPool({ // connectionLimit=10 by default 
    connectionLimit: 5, // 10 by default 
    host: 'somehost', 
    user: 'userblah', 
    password: 'passworblah', 
    database: 'dbblah' 
}) 

pool.getConnection(function(err, dbConnection) { 

dbConnection.beginTransaction(function(err1) { 
     if (err1) { 
      console.log(“Unable to begin the transaction”) 
      return 
     } 

     arrayElements.forEach(function(element) { 
      var insert1 = mysql.format(“INSERT INTO table1(…) VALUES (…)”, […]) 
      dbConnection.query(insert1, function(error1, result1) { 
       if (error1) { 
        return dbConnection.rollback(function() { 
         console.log(“Insert failed”) 
        }) 
       } 

       const lastID = result1.insertId 

       // A: more loops coming here to insert sub-data to more tables with lastID 

       // B: SHOULD I dbConnection.commit here??? 
      }) 
     }) 
    } 
} 

Ich denke, es ist an B-dbConnection.commit zu früh ist (während die forEach los ist)? Was soll ich tun, um sicherzustellen, dass alles erledigt ist, dann commit?

Antwort

1

Sie ignorieren, dass db-Aufrufe grundsätzlich IO-Aufrufe sind. Sie brauchen Zeit, um zu verarbeiten. Wenn Sie also die Anweisung insert für forEach aufrufen, werden alle Aufrufe ausgelöst, und sie warten nicht auf die Antwort der Abfrage.

var async = require('async') 
const mysql = require("mysql") 
const pool = mysql.createPool({ // connectionLimit=10 by default 
    connectionLimit: 5, // 10 by default 
    host: 'somehost', 
    user: 'userblah', 
    password: 'passworblah', 
    database: 'dbblah' 
}) 

pool.getConnection(function(err, dbConnection) { 

dbConnection.beginTransaction(function(err1) { 
     if (err1) { 
      console.log(“Unable to begin the transaction”) 
      return 
     } 

     Async.eachSeries(arrayElements,function iteratorOverElems(element,callback) { 
      var insert1 = mysql.format(“INSERT INTO table1(…) VALUES (…)”, […]) 
      dbConnection.query(insert1, function(error1, result1) { 
       if (error1) { 
        return callback(err) 
        }) 
       } 

       const lastID = result1.insertId 
      moreInsertion(arguments, 
        function (err,result){ 
        if(err){ 
         return callback(err) 
        } 
        // A: more loops coming here to insert sub-data to more tables with lastID  
        //now return the iterator 
        return callback(); 
        }) 

      }) 
     },function finalCb(err){ 
        if(err){ 
         //rollback 
        }else{ 
        // commmit here when all the insertions have been successful    
        } 
    }); 
    } 
} 

Dies ist kein definitiver Code. Sie müssen daran arbeiten. Verwenden Sie die Async-Bibliothek, um die asynchrone Funktionsverarbeitung für jedes Element in forEaching looping function zu verwalten.

Ich denke, Sie sollten festschreiben, wenn alle Abfragen erfolgreich waren sonst Rollback.

Die async.eachSeries funktioniert wie Aufruf-Iterator für jedes Element. Wenn der Callback mit dem Argument err aufgerufen wird, werden die restlichen Elemente ignoriert und der letzte Callback aufgerufen. Für weitere Informationen siehe async doc https://github.com/caolan/async#each

+0

Danke, 'async' deutet darauf hin! – quanguyen