質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

1378閲覧

Mysql、トランザクション処理が効かない理由

asus2

総合スコア22

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2019/02/19 02:59

編集2019/02/19 03:08

お世話になります。

下記の要領でトランザクション処理を行いたいのですが、
PDO::beginTransactionが効かずにどちらかが書き込みに失敗していてもどちらかの書き込みが実行されてしまいます。
(getAttributeで確認。※正直この方法できちんと確かめられているのかもわかりません。)

データベースエンジンはInnoDBになっていました。

ソースは下記のサイトを参考に作りました。
http://www.objective-php.net/mvc/model_ex
http://www.objective-php.net/mvc/data

理由のわかるかた、ご教示ください。

PHP 7.3.1
Mysql 8.0.15

php

1// ctrl.php 2  require("../〇〇/ModelBase.php"); 3 require("../●●/ChildrenDao.php"); 4 require("../〇〇/ChildrenDto.php"); 5 6 class ChildrenModel extends ModelBase 7 { 8 public function addChildren($brother_data, $sister_data) 9 { 10 $nowattr = $this->db->getAttribute(PDO::ATTR_AUTOCOMMIT); 11 echo $nowattr."<br>"; // 1 12 13 $this->db->beginTransaction(); 14 15 $nowattr = $this->db->getAttribute(PDO::ATTR_AUTOCOMMIT); 16 echo $nowattr."<br>"; // 1 17 18 $tbl_brother = new TableBrotherDto(); 19 $tbl_sister = new TableSisterDto(); 20 21 $tbl_brother->SetData($brother_data); 22 $tbl_sister->SetData($sister_data); 23 24 try 25 { 26 $brother = new TableBrotherDao(); 27 $sister = new TableSisterDao(); 28 29 $users->table_insert($tbl_brother); 30 $login->table_insert($tbl_sister); 31 32 $this->db->commit(); 33 return true; 34 35 } catch (Exception $e) { 36 $this->db->rollBack(); 37 throw $e; 38 } 39 } 40 } 41

php

1// TableChildrenDao.php 2 class TableBrotherDao extends ModelBase 3 { 4 protected $name = 'table_brother'; 5 6    ~略~ 7 public function table_insert($data){ 8 $res = $this->insert($data); 9 return $res; 10 } 11 }

php

1//ModelBase.php 2class ModelBase 3{ 4 private static $connInfo; 5 protected $db; 6 protected $name; 7 8 ~略~ 9 10 public function initDb() 11 { 12 $dsn = sprintf( 13 'mysql:host=%s;dbname=%s;port=3306;', 14 self::$connInfo['host'], 15 self::$connInfo['dbname'] 16 ); 17 $this->db = new PDO($dsn, self::$connInfo['dbuser'], self::$connInfo['password']); 18 $this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); 19 $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 20 } 21 22  ~関数略~ 23 24 // INSERTを実行 25 public function insert($data) 26 { 27    ~略~ 28 29 $res = $stmt->execute(); 30 $return $res; 31 } 32 33}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

$this->db->getAttribute(PDO::ATTR_AUTOCOMMIT)
の戻り値が1ならオートコミットしているのでrollbackしないのでは?

投稿2019/02/19 03:10

yambejp

総合スコア114572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/02/19 03:11

あ、おそらくこっちですね
asus2

2019/02/19 03:14

書き方が悪く申し訳ありません。 下記は >>PDO::beginTransactionが効かずにどちらかが書き込みに失敗していてもどちらかの書き込みが実行されてしまいます。 なぜPDO::beginTransactionが効かないのでしょうかという質問のつもりでした。
asus2

2019/02/19 03:18

PDO::beginTransactionを挟むとPDO::commitかPDO::rollBackが入るまではオートコミットが無効になると思っていたのですが、そういうわけでもないのでしょうか。
yambejp

2019/02/19 03:20

デフォルトでオートコミットがtrueなら $this->db->setAttribute(PDO::ATTR_AUTOCOMMIT,false); 的な処理をいれないといけないのでは?
asus2

2019/02/19 03:38

>>yamberjpさん この方法で解決しました! デフォルトでtrueの場合はPDO::beginTransactionしたところでオートコミットが無効になるわけではないのですね、勉強になりました。 ベストアンサーにしたいのでよろしければ別記で回答を書いていただけないでしょうか。
asus2

2019/02/19 03:41

すいません解決したと思ったら今度はコミットができていませんでした。 他に問題がありそうなのでもう少し考えてみます。
yambejp

2019/02/19 03:56

> 今度はコミット もう少し簡単なモデルをつかって試されることをお勧めします 例示されているものをみても情報が少なくてわかりませんし かりに全ソースを載せられてもすべてを検証することはできませんので。
guest

0

ベストアンサー

ChildlenModelTableBrotherDaoはそれぞれModelBaseを継承していますが、初期化を行うinitDbを見る限り、それぞれのdbプロパティに保存されるPDOオブジェクトが別々にnewされたものなのではないでしょうか。あるPDOオブジェクトがbeginTransactionしたからといって他のPDOオブジェクトには無関係です。同じPDOオブジェクトを共有するようにプログラムの構造を見直す必要があると思います。

投稿2019/02/20 04:32

crhg

総合スコア1175

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

asus2

2019/02/20 05:56

ご回答ありがとうございました。 たしかにこのやりかただと同一のPDOは使用されていませんね…。 まったく気づいていませんでした。また新たに構造から考えたいと思います。 ありがとうございました。
guest

0

トランザクション開始をtryの中で宣言しては。

投稿2019/02/19 03:10

m.ts10806

総合スコア80765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

asus2

2019/02/19 03:15

試してみましたが結果は変わらずでした。
m.ts10806

2019/02/19 03:57

あくまで導入部分です。 コミットもロールバックもtry-catch内でやっているのですし、宣言が外にあっては流れとしておかしいので。
m.ts10806

2019/02/19 04:02

スタートラインをコース外に設けてはいけません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問