この記事では、PHP におけるアトミック操作とファイル ロック フロックの概要 (コード例) を紹介します。一定の参考価値があります。必要な友人は参照してください。お役に立てば幸いです。
php アトミック操作、ファイル ロック フロック、データベース トランザクション
php は、POSIX 標準でサポートされている Unix ロックを継承せず、Linux システム コール フロックのみをカプセル化します (セマフォは効率は劣りますが、ロック機構も使用できるのは当然です。
php スクリプトは fastcgi コンテナーで実行され、fastcgi はマルチプロセスであるため、php プログラムが重要なリソースにアクセスすると、必然的にプログラムの結果が不正確になります。
fastcgi コンテナの問題も考慮する必要があると推定されています
問題の説明: バックエンドをブラッシングするためにハッカーが使用するツール
注文をキャンセルすると返金されます。ハッカーはキャンセルしました注文が同時に行われるため、複数の返金が発生します。
リクエストが 1 つずつ来る場合は、間隔が 100 ミリ秒であっても問題ありません。
PHP の処理プロセスは次のとおりです。返金フラグを読み取り、検索します。返金がないことを確認し、返金してから返金フラグを設定します
問題は、複数のリクエストが同時に到着し、読み上げられた返金サインがすべて返金されていないことです。そのため、複数のリクエストが返金されました
同じphp ファイルが同時に複数回要求されました。
PHP ファイル ロック flock を使用してみましたが、うまくいかなかったので、引き続き C キューを使用しました
C を使用してポートをリッスンし、HTTP パケットを直接受信し、パケットを HTTP 形式で返します。PHP プログラムは、curl を使用して C プログラムにアクセスします。
これはリモートと同等です。
/* ファイルを読み取りおよび書き込みのために開くときは、通常、ファイルにロック メカニズムを追加する必要があります*/
通常、プロセスがファイルからの読み取り操作を要求する場合、共有ロックが必要です。共有ロックは、任意のプロセス間の読み取り操作をサポートできます。共有ロックを使用してファイルを書き込む場合、プロセスはブロックされ、共有ロックのロックが解除されるまで SLEEP 状態に入ります。
通常はプロセス ファイルの書き込み操作に排他ロックを追加します。ファイルがロックされると、ロックが解除されるまで、他のプロセスはファイルにアクセスするときにブロックされます。
ロックされたファイル ハンドルのロックを解除します
<?php $usrinfo = isset($_GET["usrinfo"])?$_GET["usrinfo"]:exit(1); $stinfo = isset($_GET["stinfo"])?$_GET["stinfo"]:exit(1); echo $stinfo; $pid = posix_getpid(); $fp = fopen(“usrinfo.txt”,”a+”); $num = rand(0,100000); flock($fp,LOCK_EX); fwrite($fp,”user:”.$usrinfo.” stinfo:”.$stinfo.”–”.$pid.”–”.$num.”\n”); fwrite($fp,”talking 1 — pid:$pid and num:$num\n”); flock($fp,LOCK_UN); fclose($fp);
例: 複数の記事を削除しますが、そのうちの 1 つは削除されています。ここでエラーが発生したと仮定して、操作全体をロールバックしてエラー メッセージを見つけるにはどうすればよいでしょうか?
データベース トランザクションはアトミック性を保証しますが、エラー情報を見つけることができません。しかし、トランザクションが使用できないシナリオに遭遇した場合はどうすればよいでしょうか?
ロジックを適用して、すべての操作が確実に記録され、成功または失敗が記録されるようにします。途中で問題が発生した場合は、成功をロールバックできます。通常、私たちの削除は偽の削除であるため、非常に簡単です。削除した場合は、記録時に完全な情報を記録する必要があります。
PHP を使用してアトミック操作を実装しますが、PHP 自体はプロセス ロック メカニズムを提供しません。PHP ファイル ロック メカニズムを使用して、ファイルを通じてプロセス ロックをシミュレートしますアトミックな操作を実現するためのロック。
$fp = fopen( LOCK_FILE_PATH, "r" ); if (!$fp) { echo "Failed to open the lock file!"; exit(1);//异常处理 } flock ( $fp, LOCK_EX );
flock ( $fp, LOCK_UN ); fclose ( $fp );
define("LOCK_FILE_PATH", "/tmp/lock"); if( !file_exists(LOCK_FILE_PATH) ){ $fp = fopen( LOCK_FILE_PATH, "w" ); fclose ( $fp ); } $fp = fopen( LOCK_FILE_PATH, "r" ); if (!$fp) { echo "Failed to open the lock file!"; exit(1);//异常处理 } flock ( $fp, LOCK_EX ); //此处添加原子操作代码 flock ( $fp, LOCK_UN ); fclose ( $fp );
アトミック操作に一般的に使用される方法は、データ ロールバックを実装することです。PHP を使用してデータベース ロールバック操作を実装するのは非常に簡単です:
1, データベース接続を確立します
2, mysql_query('BEGIN');トランザクションをオープンします
3, $SQL = "...";
mysql_query($SQL); 対応するデータベース操作を実行します
4, ロールバック条件を決定します:
if(mysql_errno)
{
print mysql_error();
mysql_query('ROLLBACK'); エラーが発生した場合はロールバックします
exit();
}
5、上記の手順 3 と 4 を繰り返すと、プロセスを開始します (データベースの更新に限らず、他の操作を途中で追加できますが、使用するすべてのテーブルがロックされるため、トランザクションに時間がかかりすぎないように注意してください。他のプログラムの使用に影響します)
正しい SQL 更新ステートメントの後に、意図的に間違ったステートメントを記述してロールバックされるかどうかを確認するために、いくつかのステートメントを追加することもできます。
6、ロールバック操作を終了します
mysql_query('COMMIT'); ここに到達できるということは、上記のデータベース操作がすべて正しく、実行のために正式に送信されたことを意味します
これがプロセス全体ですPHP を使用してアトミック操作を実装する場合、データ ロールバック操作をサポートするテーブル構造の確立には特別な注意を払う必要があります。
さらに、ロールバック操作を終了するには、コミット以外にも方法があります。
以上がPHP におけるアトミック操作とファイル ロック フロックの概要 (コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。