4


1

トランザクションのロールバックが機能しない

PDOシステムの周りに追加機能を備えたデータベースラッパーを作成しました(はい、ラッパーの周りのラッパーを知っていますが、それはいくつかの追加機能を備えたPDOです)。 しかし、私は問題に気づきました。

次のように次のように機能しません。

beginTransaction());

$db->query('
 INSERT INTO test
 (data) VALUES (?)
 ;',
 array(
  'Foo'
 )
);
print_r($db->query('
 SELECT *
 FROM test
 ;'
)->fetchAll());

var_dump($db->rollBack());

print_r($db->query('
 SELECT *
 FROM test
 ;'
)->fetchAll());
?>

var_dumpは、beginTransactionおよびrollBack関数がtrueを返すため、エラーがないことを示しています。

最初のprint_r呼び出しはN個のアイテムの配列を表示し、2番目の呼び出しはN-1個のアイテムを表示すると予想しました。 しかし、そうではありません。両方とも同じ数のアイテムを表示します。

私の$ db→ query(<sql>、<values>)は他に何も呼び出さず、その後$ pdo→ prepare(<sql>)→ execute(<values>)(追加のエラー処理コースを使用)。

だから、MySQLのトランザクションシステムが機能しない、またはPDOの機能が機能しない、または何か間違っていると思う。

誰が問題が何であるか知っていますか?

5 Answer


13


データベースのタイプがinnoDBと等しいかどうかを確認します。 一言で言えば、データベースがトランザクションをサポートしているかどうかを確認する必要があります。


4


考えられる2つの問題

  1. テーブルは、トランザクションをサポートしないMyISAMです。 InnoDBを使用します。

  2. 自動コミットがオフになっていることを確認してください。


3


これは答えとして入力していますが、コメントは小さく、次のようになっています。

PDOは、さまざまな低レベルデータベースインターフェイスライブラリの単なるラッパーです。 低レベルのライブラリが文句を言わない場合、PDOも同様です。 MySQLはトランザクションをサポートしているため、トランザクション操作は構文エラーなどを返しません。 トランザクション内でMyISAMテーブルを使用できますが、それらに対して実行される操作は、自動コミットがまだアクティブであるかのように実行されます。

mysql> create table myisamtable (x int) engine=myisam;
Query OK, 0 rows affected (0.00 sec)

mysql> create table innodbtable (x int) engine=innodb;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into myisamtable (x) values (1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into innodbtable (x) values (2);
Query OK, 1 row affected (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select * from myisamtable;
+------+
| x    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> select * from innodbtable;
Empty set (0.00 sec)

mysql>

ご覧のとおり、トランザクションがアクティブで、一部のアクションがMyISAMテーブルで実行された場合でも、エラーはスローされませんでした。


2


MySQLはMyISAMテーブルタイプでのトランザクションをサポートしていません。MyISAMテーブルタイプは残念ながらデフォルトのテーブルタイプです。

トランザクションが必要な場合は、InnoDBテーブルタイプに切り替える必要があります。


0


これが発生する可能性のあるもう1つの理由は、特定のタイプのSQLステートメントが即時の自動コミットを引き起こすことです。 すぐにコミットされ、トランザクションを無視するトランザクションで実行される大きなスクリプトがありました。 最終的には、「ALTER TABLE」ステートメントがすぐにコミットを引き起こすためだとわかりました。

自動コミットを引き起こすステートメントのタイプは次のとおりです。

  • 「ALTER TABLE」など、テーブルまたはデータベースを変更するもの、 「CREATE TABLE」など

  • 「ALTER USER」など、テーブルのアクセス許可を変更するもの 「パスワードの設定」

  • そのテーブルをロックするか、新しいトランザクションを開始するもの

  • データ読み込みステートメント

  • 「ANALYZE TABLE」、「FLUSH」、または 「キャッシュインデックス」

  • レプリケーション制御ステートメント、たとえば、スレーブまたは マスター

詳細と完全なリストは、https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.htmlにあります。

特定のスクリプトでのみこの問題が発生し、InnoDBを使用していることが確実な場合は、スクリプト内のSQLステートメントがこれらに一致するかどうかを確認することをお勧めします。