2016-04-14 10 views
0

私はこの関数がjsonを受け取り、RDS MySQLデータベースに値を格納するはずです。MySQLのPythonコネクタはコミットしません

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()はすでにテストされており、正常に動作しています。問題は、関数を実行した後、データがDBに保存されないということです。コミットに問題があると思いますが、エラーや警告メッセージは表示されません。クエリを手動で実行すると、データが格納されます。ここで

はJSONをパースした後に実行されるクエリです:

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 

ことができます場合は、この関数が受け取るJSONです:

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

私はいくつかの助けをいただければと思います。

よろしくお願いいたします。

UPDATE:

私は問題は、クエリテンプレートのフォーマッティングコードに関連していたことがわかりました。あなたが見ることができるように、私は外にSELECTをフォーマット

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() 

:私は再 は、このような関数を書きました。私は、全体の問題は、このラインによるものであったと考えている:

"metric_value = %(metric_value)f" 

私はに変更:

"metric_value = %(metric_value)s" 

、今それが動作します。私は書式設定が間違っていると思っています。文法エラーがあります(私は例外がどのようにスローされたのかわかりません)。

私を助ける時間を割いた皆様に感謝します!

+0

質問のタイトルはデータベースにコミットできなかったことを示しますが、コードと質問のテキストは、処理中のJSONを指します。データベースに直接書き込むコードも失敗しますか?問題を示す最小限のコードを提供できますか? – brycem

+0

'RDS_Connect()'のインポートを表示してもよろしいですか? – Tommy

+0

あなたのコミットは空でないものに依存するforループの内側にあるので、 'jsonMetrics ['Metrics']'を出力してください。 – Tommy

答えて

0

これが解決策でした。私が変更されました:

"metric_value = %(metric_value)f" 

た:

"metric_value = %(metric_value)s" 

私はSQLで構文エラーを発見したいくつかのトラブルシューティングを行います。何とか例外は表示されませんでした。

0

私は実際にMySQLを使用していませんが、docsは、マルチ= Trueのcursor.executeを呼び出すとイテレータを返すことを示しているようです。それが本当であれば、実際には何も挿入しません。実際にレコードを挿入するには、イテレータに.next()をコールするか、反復処理する必要があります。

またmulti=Trueでパラメータを使用しないことを助言するために行く:

マルチがTrueに設定されている場合は、(実行)は、操作文字列で指定された複数のステートメントを実行することができます。各ステートメントの結果を処理できるイテレーターを返します。ただし、この場合はパラメータを使用してもうまく動作せず、通常は各ステートメントを単独で実行することをお勧めします。

tl; dr:このパラメータを削除します(デフォルトはFalseです)。

関連する問題