2016-03-31 3 views
1

私は今これを試していますが、インターネット上での検索では解決策が出ていません。PythonがMySQLアップデートでハングアップする

アクセスする前に別のプロセスが自分のDBにアクセスしているかどうか確認したいと思います。私はカラムidとstateを持つテーブルを持っています。状態が1の場合は0に変更してアクセスし続けます。それ以外の場合はそのままにします。以下は、それが動作しませんなぜ私が見ることができない、私のコードですが、それはcursor.execute(set_lock)

get_lock = "SELECT state FROM running WHERE id=1" 
cursor.execute(get_lock) 
result = cursor.fetchall() 
if(result[0][0]): 
    set_lock = "UPDATE running SET state=0 WHERE id=1" 
    cursor.execute(set_lock) 

は、私はそれがカーソルの再利用とは何かを持っているかなり確信している、ここで最後の行にするたびにハングアップしますしかし、なぜそれが問題になるべきかわからない、私はそれを成功させる前にやった。あなたが偉大な助けをするなら、私は、問題解決があったが、修正がフレーク状だと思った

乾杯


、で開始する動作するように見えたが、その後、間違った状態を返す始めました。 PHPMyAdminでMySQLステートメントを実行すると、必要に応じて1が返されますが、結果を出力するときには0が返され、ifステートメントの内容はスキップされます。

cursor.execute("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;") 
get_lock = "SELECT state FROM running WHERE id=1;" 
cursor.execute(get_lock) 
result = cursor.fetchall() 
if(result[0][0]): 
    set_lock = "UPDATE running SET state=0 WHERE id=1;" //Lock 
    cursor.execute(set_lock) 
    cursor.execute("COMMIT;") 

    ---- DO WHAT I NEED TO DO ---- 

    set_lock = "UPDATE running SET state=1 WHERE id=1;" //Unlock 
    cursor.execute(set_lock) 
    cursor.execute("COMMIT;") 

cursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;") 
cursor.close() 

+3

その間はhttp://stackoverflow.com/questions/10935850/when-to-use-select-for-updateを読んでください。現在の実装は、トランザクションの分離に応じて競合状態でオープンされている可能性があります。 –

+1

ありがとう、私のためのソリューションにつながる。 –

+2

更新と更新を選択した後、コミットすることで行ロックを解放する必要があります。さもなければ、更新のためのもう1つの選択は行ロックを待つのをブロックするでしょう。 –

答えて

1

Ilja'sコメントの次のリードのおかげで解決策が見つかりました。

get_lock = "SELECT state FROM running WHERE id=1 FOR UPDATE;" 
cursor.execute(get_lock) 
result = cursor.fetchall() 
if(result[0][0]): 
    set_lock = "UPDATE running SET state=0 WHERE id=1;" 
    cursor.execute(set_lock) 
    cursor.execute("COMMIT;") 

最初は、SELECTステートメントのタイプミスが原因でこれが機能しませんでした。また、最後のステートメントは重要ですcursor.execute("COMMIT;")

これを読んだ後question解決策があるようですが、その動作は断続的でした。

cursor.execute("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;") 
get_lock = "SELECT state FROM running WHERE id=1;" 
cursor.execute(get_lock) 
result = cursor.fetchall() 
if(result[0][0]): 
    set_lock = "UPDATE running SET state=0 WHERE id=1;" //Lock 
    cursor.execute(set_lock) 
    cursor.execute("COMMIT;") 

    ---- DO WHAT I NEED TO DO ---- 

    set_lock = "UPDATE running SET state=1 WHERE id=1;" //Unlock 
    cursor.execute(set_lock) 
    cursor.execute("COMMIT;") 

cursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;") 
cursor.close() 
+3

私は実際にあなたが 'SELECT ... FOR UPDATE'を使うべきであることを意味しました。 'READ UNCOMMITTED'を使うと、他のプロセスが' SELECT'の前に 'UPDATE'を発行することができれば、更新された値を(ダーティーリードで)得ることができますが、ロックが設定されていないことを確認してから、2つのUPDATEを発行し、ロックを取得したと考え続ける。 –

+1

私がそれを読む方法は私に 'READ UNCOMMITTED'メソッドにつながります。私はあなたが何を言っているのかを見ます。私はそれがどのように行くのか見ていきますが、あなたのコメントを心に留めておきます。ご協力いただきありがとうございます。 –

関連する問題