原因:
当社のオンライン ビジネスの 1 つでは、DB クラスの古いバージョンの CodeIgniter フレームワークを使用していますが、DB トランザクション処理部分に設計上の欠陥がありますが、欠陥とはみなされない可能性があります。しかし、それは私たちの本番環境に影響を及ぼし、連鎖反応を引き起こしました。ビジネスに大きな影響を与えるため、トラブルシューティングが困難です。この問題は、今年の 3 月中旬に codeigniter China のウェブマスターである Hex に報告しましたが、その後、忘れていました。今日まで、オンライン ビジネスでこの問題を改めて考え、再度調査することにしました。具体的な理由は、ゆっくり聞いてください。 (この問題は最新バージョンVersion 2.1.0にも存在します)
分析:
CodeIgniter フレームワーク バージョン 2.1.0 を例にとると、systemdatabaseDB_driver.php の CI_DB_driver クラスの 58 行目に $_trans_status 属性があります。
同時に、このクラスのクエリメソッドにこの属性を割り当てるためのコードがあります。ファイルの306行目と307行目を参照してください
トランザクション処理を使用する場合、この属性がロールバックの判定条件になるというコメントもここにあります。
520 行目のトランザクション送信メソッド trans_complete のコードは次のとおりです。
// トランザクションがネストされている場合、最も外側のトランザクションのみを開始/コミット/ロールバックします
if ($this->_trans_ Depth > 1)
{
$this->_trans_ Depth -= 1;
TRUE を返します;
}
// クエリが失敗した場合、query() 関数はこのフラグを FALSE に設定します
if ($this->_trans_status === FALSE)
{
$this->trans_rollback();
// 厳密モードで実行していない場合は、リセットします
// _trans_status フラグにより、後続のトランザクション グループ
// 許可されます
if ($this->trans_strict === FALSE)
{
$this->_trans_status = TRUE;
}
log_message('デバッグ', 'DB トランザクションの失敗');
FALSE を返します;
}
$this->trans_commit();
TRUE を返します;
}
535行目では、_trans_status属性がfalseの場合、ロールバックが発生し、falseが返されます。
弊社の業務コードでは、プログラマーの過失により、trans_complete()メソッドが正しく実行されたかどうかを判断せず、ユーザーに操作が成功したことを直接伝えていましたが、実際にはプログラムがロールバック命令を発行していました。 DB を更新し、DB レコードを正常に更新できませんでした。ユーザーが次の操作を実行すると、プログラムは対応するレコードが更新されていないことを検出し、前の操作が完了していないことをユーザーに思い出させ、再度操作を実行するように通知します。何度も…
トラブルシューティングのプロセスも非常に興味深いもので、最初は PHP コードからは常に問題がわかりず、trans_complete() メソッドの戻りに焦点を当てていませんでした。ロールバックがこの属性によって引き起こされたことがわかったのは、後の strace パケット キャプチャ分析の結果でした。
CIを設定した設計者が、同一スクリプト内に複数のトランザクションが存在する場合、トランザクション間の関係が重要となるためにCIを設定していることもコメントから容易に理解できます。ここでの trans_strict 属性はスイッチです。 trans_strict が false の場合、非厳密モードになります。これは、複数のトランザクション間の関係は重要ではなく、相互に影響を与えないことを意味します。現在のトランザクションに実行に失敗した SQL ステートメントがありますが、影響はありません。 _trans_status は TRUE に設定されます。
これが非常に思慮深い考察であることは疑いの余地がありません。ビジネスがより厳密なコードで実行されるように、複数のトランザクション間の関係が考慮されます。
ただし、私たちのコードでは、間違った SQL ステートメントがトランザクション内ではなく、トランザクション処理の外で実行されます。トランザクションの理解によれば、トランザクション外の SQL はトランザクション内の SQL よりも重要であることが明確にわかります。トランザクション外の SQL は間違っていてもかまいませんが、トランザクション内の SQL は正しくなければなりません。外部からの干渉を受けません。しかし、CI フレームワークでは、トランザクション以外のステートメントの実行に失敗すると、トランザクション全体がロールバックされます。もちろん、プログラマはトランザクションの送信メソッドの戻りについて判断しませんでした。問題でもあります。
問題はすでに非常に明確なので、解決策はあなたにとって非常に簡単であるはずです。
たとえば、trans_start メソッドでは、_trans_status 属性に値を割り当て、それを TRUE に設定し、トランザクション外の問題を無視します。
// トランザクションがネストされている場合、最も外側のトランザクションのみを開始/コミット/ロールバックします
if ($this->_trans_ Depth > 0)
{
$this->_trans_ Depth += 1;
戻る;
}
$this->trans_begin($test_mode);
}
終了:
プログラム作成者のレベルに関わらず、相手の設計意図を理解せずに、やみくもに相手のコード評価を定義することはできません。自分より強い場合は、彼らを盲目的に崇拝することはできません。自分より弱い場合は、無差別に非難することはできません。設計の意図を理解し、他の人の優れた設計アイデアやコーディング スタイルを学ぶことは良い習慣です。 、アルゴリズムの効率性。もちろん、Codeigniter フレームワークは優れています。
昨日 CodeIgniter マニュアルを読んだところですが、CodeIgniter の URL の章でその方法が説明されています:
次のように .htaccess ファイルにルールを追加することで処理されます
RewriteEngine on
RewriteCond $1 !^(index\. php| 画像|ロボット\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
CodeIgniter China - PHP フレームワーク CodeIgniter China コミュニティ
ユーザー マニュアルをクリックすると、ページの上部に「目次」ボタンがあり、非常に充実した中国語マニュアルが開きます。