アプリ版:「スタンプのみでお礼する」機能のリリースについて

MySQLデータベースを操作するPHPのプログラムを作っているところです。
操作の途中でエラーになった場合や、やり直しをしたい場合、操作開始前の状態にもどしたいのですが、どのようにプログラミングして良いのかわからないので教えてください。

具体的には、
 操作対象のテーブルを保存して、操作を開始し、
 エラーが発生した場合、復元して終了、
 正常終了の場合はコピーしたテーブルを削除して終了
したいです。PHPのプログラム例(SQLコマンド例?)を教えてほしいです。

A 回答 (8件)

https://dev.mysql.com/doc/refman/5.6/ja/commit.h …

上記にあるように、START TRANSACTION、COMMIT、および ROLLBACK を使います。
    • good
    • 0
この回答へのお礼

回答ありがとうございます
まさにこれです。

お礼日時:2021/01/01 16:42

> 一連の操作を見て、


 矛盾が見つかればやり直し

つまり、矛盾がおきる条件が確定しているから
INSERTする前にチェックするだけですべて解決です

いま例示されてあいまいなものではなく
具体的なテーブルとデータのサンプルが
あればどうしたらいいか回答のしようもありますが
    • good
    • 0
この回答へのお礼

yambejp さん、再度の回答ありがとうございます

>INSERTする前にチェックするだけですべて解決です

チェックするためには、
 メビウスの帯のように一連の操作、一つ一つを見ても発見は不可能なので、
 ユーザ操作後のデータベースを一旦作成して
 それが整合性の取れたデータベースになっているかをチェック
するので、結局同じことですね。

何度もありがとうございます。

お礼日時:2021/01/04 16:20

#6



いや、理解がおかしいです
論理的におかしなデータは投入してからもとに戻すのではなく
データ投入しないのです。
入れてから削除ではなく、入れていいか検索して
問題なければ投入、そうでなければ「なにもしない」という
処理が正しいです
なのでそこにはロールバックは発生しません
    • good
    • 0
この回答へのお礼

yambejp さん、再度の回答ありがとうございます

>いや、理解がおかしいです
>入れてから削除ではなく、入れていいか検索して
>問題なければ投入、そうでなければ「なにもしない」という
>処理が正しいです

そうなんですが、いつどこで判断したらよいのかで悩みました
操作毎にチェックするのでは、

操作1 AはBよりも大きい
操作2 BはCよりも大きい
操作3 CはAよりも大きいという情報を否定する操作
とすると操作2のときに矛盾が判明しますが、その時点では既に操作1は完了しています。また操作3まで実行すれば矛盾が解消されますが、操作3の実行を予測することは不可能です。

利用者が入力完了と言った時点で、一連の操作を見て、
 矛盾が見つかればやり直し
すれば良いと思ったのですが、まずいのでしょうかね。

もっと賢い解決策がお有りなら、ご教示お願いします!

お礼日時:2021/01/04 15:26

#5



>SQLに渡してみないと、変なデータかどうかは判断できない場合

データベースの構造や型を把握しないで送ることはありえません。
なので理論的にそういう場合はありません。

むしろSQL側の制限で、たとえばnot nullにnullを入れたり、
ユニークカラムにダブりを入れたりする場合は、
バリデートは通解して、入力自体が拒否されるのでロールバックさえ
不要です。
特殊な条件付けをする場合は、トランザクションで、条件を検索して
からデータ投入することになるでしょう。その場合もロールバックでは
ないです。
    • good
    • 0
この回答へのお礼

yambejp さん、再度の回答ありがとうございます

>データベースの構造や型を把握しないで送ることはありえません。
>なので理論的にそういう場合はありません。

想定されているエラーのレベルが違う気がします。

データベースの構造や型に合致していて局所的には整合性が取れたデータであり、別の状況では正しいデータであるが、現存するデータに追加すると初めて矛盾するような一連のデータというのは、ありえると思いますが。

非常に単純化した例では、
データベースに
 AはBよりも大きい
 BはCよりも大きい
という2つのデータを追加する場合。

もし、データベースに
 CはAよりも大きい
というデータが(間接的であっても)存在すれば、これらの操作はエラーとして処理を無効化するということです。

もしも、その先にこの矛盾を否定するような(CはAよりも大きいを導くデータの一部を削除する)操作をユーザが行う場合には、エラー処理とならずに正常終了とし、これらの操作は有効とします。

お礼日時:2021/01/04 14:47

> ユーザが変なデータを食べさせた



変なデータというくらいですから、想定がすでにありますよね?
であればSQLにわたす前にバリデート処理で所定のルールを
通過しない場合処理を行わないというのが普通です
    • good
    • 0
この回答へのお礼

yambejp さん、お久しぶりです。回答ありがとうございます

>SQLにわたす前にバリデート処理で所定のルールを
>通過しない場合処理を行わないというのが普通です

確かに、事前に変なデータなのかが判断出来る場合はそうなんですが、
SQLに渡してみないと、変なデータかどうかは判断できない場合もある気がしています。うまい例が見つからないのですが、気持ちとしては
 局所的に見れば整合性の取れた一連のデータであっても、
 現存するデータに追加すると矛盾するような一連のデータの挿入操作
でしょうか。
無かったことにしたいのは、矛盾が発見された直前の操作ではなく、そこに至るまでの一連の操作です。

お礼日時:2021/01/04 13:59

No.2です。



> まさにこれです。

具体的状況・・・というかプログラムの内容がわかりませんが、何かしらプログラム内で(プログラムの作成者にとって)予期せぬエラーが有った際にデータベースのテーブルが壊れてバックアップを落として修復せねばならないという状況になるということであれば、それは「トランザクションの単位や作りが悪い!」つまり「プログラムの設計誤り」ということになるかと思います。

参考まで。
    • good
    • 0
この回答へのお礼

貴重な意見、ありがとうございます。
>具体的状況・・・というかプログラムの内容がわかりませんが、
 ユーザが変なデータを食べさせた場合でも、被害が及ばないようにする、
 ユーザが途中で作業を中止したい場合に、それまでの操作をなかったことにする
ためです。

お礼日時:2021/01/01 17:12

>操作対象のテーブルを保存


CREATE TEMPORARY TABLE new_tbl AS SELECT * FROM orig_tbl;
――とか。
https://dev.mysql.com/doc/refman/8.0/en/create-t …
https://dev.mysql.com/doc/refman/8.0/en/create-t …

ただ、一般的なundo実装なら、テーブル丸コピーは牛刀割鶏かも。
    • good
    • 0
この回答へのお礼

回答ありがとうございます

>ただ、一般的なundo実装なら、テーブル丸コピーは牛刀割鶏かも。
START TRANSACTION、COMMIT、および ROLLBACK を使うのが正解ということでしょうか?

お礼日時:2021/01/01 16:44

リレーショナルデータベースですからCOMMITしていなければROLLBACKすればよいだけかと。

。。
COMMIT済のものも戻したいなら事前にバックアップをとっておきそれを落とせば元通りになります。

参考まで。
    • good
    • 0
この回答へのお礼

回答ありがとうございます
まさにこれです。

お礼日時:2021/01/01 16:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!