ホームページ  >  記事  >  バックエンド開発  >  CodeIgniter フレームワークにおけるデータベース トランザクション処理の設計上の欠陥と解決策、codeigniter Framework_PHP チュートリアル

CodeIgniter フレームワークにおけるデータベース トランザクション処理の設計上の欠陥と解決策、codeigniter Framework_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-13 10:22:13888ブラウズ

CodeIgniter フレームワークのデータベース トランザクション処理設計の欠陥と解決策、CodeIgniter フレームワーク

原因:

当社のオンライン ビジネスの 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 属性があります。

コードをコピーします コードは次のとおりです:

//systemdatabaseDB_driver.php
var $trans_strict = TRUE;
var $_trans_ Depth = 0;
var $_trans_status = TRUE; // ロールバックが発生するかどうかを決定するためにトランザクションで使用されます
; var $cache_on = FALSE;

同時に、このクラスのクエリメソッドにこの属性を割り当てるためのコードがあります。ファイルの306行目と307行目を参照してください

コードをコピーします コードは次のとおりです:

// トランザクションが使用されている場合、これによりロールバックがトリガーされます
$this->_trans_status = FALSE;

トランザクション処理を使用する場合、この属性がロールバックの判定条件になるというコメントもここにあります。

520 行目のトランザクション送信メソッド trans_complete のコードは次のとおりです。

コードをコピーします コードは次のとおりです:

/**
 * 取引を完了します
 *
 * @access public
 * @return bool
 */
関数trans_complete()
{
if ( ! $this->trans_enabled)
{
FALSE を返します;
}

// トランザクションがネストされている場合、最も外側のトランザクションのみを開始/コミット/ロールバックします
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 パケット キャプチャ分析の結果でした。

コードをコピーします コードは次のとおりです:

22:54:08.380085 write(9, "_ 22:54:08.380089 read(9, ": 22:54:08.381791 write(9, "21 22:54:08.381891 read(9, "7 22:54:08.382186 ポーリング([{fd=9, events=POLLIN|POLLPRI}], 1, 0) = 0
22:54:08.382258 write(9, "v 22:54:08.382343 read(9, "7 22:54:08.382631 ポーリング([{fd=9, events=POLLIN|POLLPRI}], 1, 0) = 0
22:54:08.382703 write(9, "22 22:54:08.401954 write(9, "v 22:54:08.402043 read(9, "7 22:54:08.417773 write(9, "v 22:54:08.417872 read(9, "7 22:54:08.418256 write(9, "[ 22:54:08.418363 read(9, "0 22:54:08.430212 write(9, "v 22:54:08.430314 read(9, "7 22:54:08.430698 write(9, "B 22:54:08.430814 read(9, "0 22:54:08.432130 write(9, "v 22:54:08.432231 read(9, "7 22:54:08.432602 write(9, "244 22:54:08.432743 read(9, "0 22:54:08.433517 write(9, "v 22:54:08.433620 read(9, "7 22:54:08.433954 write(9, "t 22:54:08.434041 read(9, "7 22:54:08.434914 write(9, "v 22:54:08.434999 read(9, "7 22:54:08.435342 write(9, "21 22:54:08.435430 read(9, "7 22:54:08.436923 write(9, "1


22:54:08.380085 に更新 SQL ステートメント コマンドが送信され、返された結果が 22:54:08.380089 に読み取られ、フィールド「cfc4n_user_lock」が存在しないことがわかります。 22:54:08.381791 22:54:08.382703 と 22:54:08.382703 の 2 つの時点で、PHP は「自動コミット」の停止と「トランザクション処理の開始」命令を送信し、22:54:08.433954 で PHP は「トランザクションのロールバック」命令。

上記のコード分析により、「UPDATE `cfc4n_user_info` SET `cfc4n_user_lock` = 1 WHERE `cfc4n_user_id` = '6154' AND `cfc4n_user_lock` = 0」という SQL 実行エラーにより、$_trans_status 属性がFALSE に設定すると、コードがトランザクションをコミットしたときに、trans_complete() メソッドによって判断され、「前のトランザクション処理」 (詳細は後述) で SQL ステートメントの実行に失敗したとみなされます。トランザクションをコミットせずにロールバックすることが決定されました。

「前のトランザクション処理」について説明したばかりですが、理解できない人もいるかもしれません。コードに戻って、trans_complete メソッドの 542 ~ 545 行目も見てみましょう。



コードをコピーします

コードは次のとおりです:


// 厳密モードで実行していない場合は、リセットします
// _trans_status フラグにより​​、後続のトランザクション グループ
// 許可されます
if ($this->trans_strict === FALSE)
{
$this->_trans_status = TRUE;
}

CIを設定した設計者が、同一スクリプト内に複数のトランザクションが存在する場合、トランザクション間の関係が重要となるためにCIを設定していることもコメントから容易に理解できます。ここでの trans_strict 属性はスイッチです。 trans_strict が false の場合、非厳密モードになります。これは、複数のトランザクション間の関係は重要ではなく、相互に影響を与えないことを意味します。現在のトランザクションに実行に失敗した SQL ステートメントがありますが、影響はありません。 _trans_status は TRUE に設定されます。
これが非常に思慮深い考察であることは疑いの余地がありません。ビジネスがより厳密なコードで実行されるように、複数のトランザクション間の関係が考慮されます。

ただし、私たちのコードでは、間違った SQL ステートメントがトランザクション内ではなく、トランザクション処理の外で実行されます。トランザクションの理解によれば、トランザクション外の SQL はトランザクション内の SQL よりも重要であることが明確にわかります。トランザクション外の SQL は間違っていてもかまいませんが、トランザクション内の SQL は正しくなければなりません。外部からの干渉を受けません。しかし、CI フレームワークでは、トランザクション以外のステートメントの実行に失敗すると、トランザクション全体がロールバックされます。もちろん、プログラマはトランザクションの送信メソッドの戻りについて判断しませんでした。問題でもあります。

問題はすでに非常に明確なので、解決策はあなたにとって非常に簡単であるはずです。
たとえば、trans_start メソッドでは、_trans_status 属性に値を割り当て、それを TRUE に設定し、トランザクション外の問題を無視します。

コードをコピーします コードは次のとおりです:

関数 trans_start($test_mode = FALSE)
{
if ($this->trans_strict === FALSE)
{
$this->_trans_status = TRUE; //トランザクション処理を開始するときに、この属性の値を TRUE にリセットします
}
//2012/05/01 18:00 CI 中国語コミュニティのネチズン http://codeigniter.org.cn/forums/space-uid-5721.html による修正後の修正は、trans_strict 属性を追加して、同様にreset_trans_status。
if ( ! $this->trans_enabled)
{
FALSE を返します;
}

// トランザクションがネストされている場合、最も外側のトランザクションのみを開始/コミット/ロールバックします
if ($this->_trans_ Depth > 0)
{
$this->_trans_ Depth += 1;
戻る;
}

$this->trans_begin($test_mode);
}

終了:

プログラム作成者のレベルに関わらず、相手の設計意図を理解せずに、やみくもに相手のコード評価を定義することはできません。自分より強い場合は、彼らを盲目的に崇拝することはできません。自分より弱い場合は、無差別に非難することはできません。設計の意図を理解し、他の人の優れた設計アイデアやコーディング スタイルを学ぶことは良い習慣です。 、アルゴリズムの効率性。もちろん、Codeigniter フレームワークは優れています。

PHP CodeIgniterフレームワークの場合

昨日 CodeIgniter マニュアルを読んだところですが、CodeIgniter の URL の章でその方法が説明されています:

次のように .htaccess ファイルにルールを追加することで処理されます

RewriteEngine on

RewriteCond $1 !^(index\. php| 画像|ロボット\.txt)

RewriteRule ^(.*)$ /index.php/$1 [L]

codeigniter フレームワークの関連学習資料 (マニュアル、書籍、チュートリアルなど)

CodeIgniter China - PHP フレームワーク CodeIgniter China コミュニティ

ユーザー マニュアルをクリックすると、ページの上部に「目次」ボタンがあり、非常に充実した中国語マニュアルが開きます。

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/848800.html技術記事 CodeIgniter フレームワークの原因である、CodeIgniter フレームワークのデータベース トランザクション処理の設計上の欠陥と解決策: 当社のオンライン ビジネスの 1 つでは、古いバージョンの CodeIgniter フレームワークが使用されています。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。