16

MySQLdbモジュールを使用してPythonからMySQL5.0を使用しています。

データベーステーブル全体の内容をロードして返す単純な関数について考えてみます。

def load_items(connection):
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM MyTable")
    return cursor.fetchall()

SELECTこのクエリは、単純なデータロードを目的としており、その単一のステートメントを超えるトランザクション動作はありません。

このクエリが実行された後、同じ接続が他のタスクを実行するために再度使用されるまでにしばらく時間がかかる場合がありますが、その間、他の接続はデータベースで動作し続けることができます。

操作が接続に未完了のトランザクションを残していないことを確認するためconnection.commit()に、呼び出しの直後に電話をかける必要がありますか?cursor.execute(...)

4

1 に答える 1

20

考慮に入れる必要がある2つのことがあります:

  1. 有効な分離レベル
  2. トランザクションで「見たい」状態の種類

MySQLのデフォルトの分離レベルは、トランザクション内で2回実行すると、他のトランザクションが変更をコミットした場合でも、まったく同じデータが表示されることREPEATABLE READを意味します。SELECT

ほとんどの場合、人々は2番目のselectステートメントを実行するときにコミットされた変更を確認することを期待しています。これはREAD COMMITTED分離レベルの動作です。

MySQLでデフォルトレベルを変更せず、同じトランザクションでSELECTを2回実行するとデータベースに変更が見られると予想される場合、「同じ」トランザクションでそれを行うことはできず、コミットする必要があります。最初のSELECTステートメント。

トランザクション内のデータの一貫した状態を実際に確認したい場合は、明らかにコミットしないでください。

次に、数分後、最初のプロセスがトランザクションである操作を実行し、コミットを試みます。このコミットは失敗しますか?

それは完全にあなたの「トランザクションである」の定義に依存します。リレーショナルデータベースで行うことはすべて「トランザクション」です(これは実際にはMySQLには完全には当てはまりませんが、議論のために、ストレージエンジンとしてInnoDBのみを使用している場合はこれを想定できます)。

その「最初のプロセス」がデータのみを選択する場合(つまり、「読み取り専用トランザクション」)、もちろんコミットは機能します。別のトランザクションがすでにコミットしているデータを変更しようとして、一緒に実行しているREPEATABLE READ場合は、おそらくエラーが発生します(ロックが解放されるまで待機した後)。その場合のMySQLの動作については100%ではありません。

動作を理解するには、お気に入りのSQLクライアントを使用して2つの異なるセッションでこれを手動で試す必要があります。分離レベルも変更して、さまざまなレベルの影響も確認してください。

于 2012-11-08T11:33:59.463 に答える