2016-04-14 9 views
0

Ich habe diese Funktion, die es sollte erhalten json und speichern Sie die Werte auf einem RDS MySQL db.MySQL Python-Connector nicht commit

def saveMetric(metrics): 
    cnx  = RDS_Connect() 
    cursor = cnx.cursor() 
    jsonMetrics = json.loads(metrics) 
    #print type(jsonMetrics['Metrics']) 
    # Every 2000 registries, the script will start overriding values 
    persistance = 2000 
    save_metrics_query = (
      "REPLACE INTO metrics " 
      "SET metric_seq = (SELECT COALESCE(MAX(row_id), 0) %% %(persistance)d + 1 FROM metrics AS m), " 
      "instance_id = \'%(instance_id)s\', " 
      "service = \'%(service)s\' , " 
      "metric_name = \'%(metric_name)s\', " 
      "metric_value = %(metric_value)f" 
      ) 
    for metric in jsonMetrics['Metrics']: 
     formatData = {} 
     formatData['persistance'] = persistance 
     formatData['instance_id'] = arguments.dimensionValue 
     formatData['service'] = jsonMetrics['Service'] 
     formatData['metric_name'] = metric 
     formatData['metric_value'] = jsonMetrics['Metrics'][metric] 

     print save_metrics_query % formatData 

     try: 
      cursor.execute(save_metrics_query, formatData, multi=True) 
      logger('info','Metrics were saved successfully!') 
      cnx.commit() 
     except mysql.connector.Error as err: 
      logger('error', "Something went wrong: %s" % err) 
    cursor.close() 
    cnx.close() 

RDS_Connect() wurde bereits getestet und es funktioniert gut. Das Problem ist, dass nach dem Ausführen der Funktion die Daten nicht in der DB gespeichert werden. Ich denke, es gibt ein Problem mit dem Commit, aber ich sehe keine Fehler oder Warnmeldungen. Wenn ich die Abfrage manuell ausführe, werden die Daten gespeichert.

Hier ist die Abfrage, die nach dem Parsen der json läuft:

REPLACE INTO metrics SET metric_seq = (SELECT COALESCE(MAX(row_id), 0) % 2000 + 1 FROM metrics AS m), instance_id = 'i-03932937bd67622c4', service = 'AWS/EC2' , metric_name = 'CPUUtilization', metric_value = 0.670000 

Wenn es hilft, ist dies die json ist, dass die Funktion erhält:

{ 
"Metrics": { 
    "CPUUtilization": 1.33, 
    "NetworkIn": 46428.0, 
    "NetworkOut": 38772.0 
}, 
"Id": "i-03932937bd67622c4", 
"Service": "AWS/EC2" 
} 

ich etwas Hilfe schätzen würde.

Grüße!

UPDATE:

fand ich, dass das Problem auf die Formatierungscodes auf der Abfragevorlage verwandt war. Ich schrieb die Funktion wie folgt wieder:

def saveMetric(metrics): 
    cnx  = RDS_Connect() 
    jsonMetrics = json.loads(metrics) 
    print json.dumps(jsonMetrics,indent=4) 

    persistance = 2000 
    row_id_query_template = "SELECT COALESCE(MAX(row_id), 0) % {} + 1 FROM metrics AS m" 
    row_id_query = row_id_query_template.format(persistance) 

    save_metrics_query = (
     "REPLACE INTO metrics " 
     "SET metric_seq = (" + row_id_query + ")," 
     "instance_id = %(instance_id)s," 
     "service = %(service)s," 
     "metric_name = %(metric_name)s," 
     "metric_value = %(metric_value)s" 
     ) 

    for metric in jsonMetrics['Metrics']: 
     formatData = {} 
     formatData['instance_id'] = arguments.dimensionValue 
     formatData['service'] = jsonMetrics['Service'] 
     formatData['metric_name'] = metric 
     formatData['metric_value'] = jsonMetrics['Metrics'][metric] 

     if arguments.verbose == True: 
      print "Data: ",formatData 
      print "Query Template: ",save_metrics_query.format(**formatData) 

     try: 
      cursor = cnx.cursor() 
      cursor.execute(save_metrics_query, formatData) 
      logger('info','Metrics were saved successfully!') 
      cnx.commit() 
      cursor.close() 
     except mysql.connector.Error as err: 
      logger('error', "Something went wrong: %s" % err) 

    cnx.close() 

Wie Sie sehen können, habe ich außerhalb der SELECT-Format. Ich glaube, das ganze Problem aufgrund dieser Linie war:

"metric_value = %(metric_value)f" 

ich geändert:

"metric_value = %(metric_value)s" 

und jetzt funktioniert es. Ich denke, die Formatierung war falsch, bei einem Syntaxfehler (ich weiß nicht, wie die Ausnahme nie ausgelöst wurde).

Danke an alle, die sich die Zeit genommen haben, mir zu helfen!

+0

Der Titel Ihrer Frage bezieht sich auf einen Fehler beim Festschreiben an die Datenbank, aber Ihr Code und der Text der Frage beziehen sich auf den JSON, den Ihre Funktion verarbeitet. Scheitert Code, der direkt in die Datenbank schreibt? Können Sie den Mindestcode angeben, der das Problem veranschaulicht? – brycem

+0

können Sie bitte den Import von 'RDS_Connect()' – Tommy

+0

auch können Sie bitte 'jsonMetrics ['Metriken']' 'da Ihr Commit innerhalb einer for-Schleife, die davon abhängt, dass nicht leer ist – Tommy

Antwort

0

Das war die Lösung.Ich änderte:

"metric_value = %(metric_value)f" 

An:

"metric_value = %(metric_value)s" 

eine Fehlersuche durch tuend ich einen Syntaxfehler auf dem SQL gefunden. Irgendwie hat sich die Ausnahme nicht gezeigt.

0

Ich habe nicht wirklich MySQL verwendet, aber die docs scheinen darauf hinzuweisen, dass Aufruf cursor.execute mit multi = True nur einen Iterator zurückgibt. Wenn das wahr ist, dann würde es eigentlich nichts einfügen - Sie müssten .next() auf dem Iterator aufrufen (oder einfach darüber iterieren), um den Datensatz tatsächlich einzufügen.

Es geht auch mit multi=True gegen die Verwendung von Parametern zu beraten:

Wenn Multi auf True gesetzt ist, execute() ist in der Lage in der Operation String angegeben mehrere Anweisungen auszuführen. Es gibt einen Iterator zurück, der die Verarbeitung des Ergebnisses jeder Anweisung ermöglicht. Die Verwendung von Parametern funktioniert in diesem Fall jedoch nicht gut, und es ist normalerweise eine gute Idee, jede Anweisung einzeln auszuführen.

tl; dr: Entfernen Sie diesen Parameter, da der Standardwert False ist.

Verwandte Themen