ホームページ >バックエンド開発 >PHPチュートリアル >PHP におけるアトミック操作とファイル ロック フロックの概要 (コード例)

PHP におけるアトミック操作とファイル ロック フロックの概要 (コード例)

不言
不言転載
2019-01-28 10:00:482858ブラウズ

この記事では、PHP におけるアトミック操作とファイル ロック フロックの概要 (コード例) を紹介します。一定の参考価値があります。必要な友人は参照してください。お役に立てば幸いです。

php アトミック操作、ファイル ロック フロック、データベース トランザクション

php は、POSIX 標準でサポートされている Unix ロックを継承せず、Linux システム コール フロックのみをカプセル化します (セマフォは効率は劣りますが、ロック機構も使用できるのは当然です。
php スクリプトは fastcgi コンテナーで実行され、fastcgi はマルチプロセスであるため、php プログラムが重要なリソースにアクセスすると、必然的にプログラムの結果が不正確になります。
fastcgi コンテナの問題も考慮する必要があると推定されています

問題の説明: バックエンドをブラッシングするためにハッカーが使用するツール
注文をキャンセルすると返金されます。ハッカーはキャンセルしました注文が同時に行われるため、複数の返金が発生します。
リクエストが 1 つずつ来る場合は、間隔が 100 ミリ秒であっても問題ありません。

PHP の処理プロセスは次のとおりです。返金フラグを読み取り、検索します。返金がないことを確認し、返金してから返金フラグを設定します
問題は、複数のリクエストが同時に到着し、読み上げられた返金サインがすべて返金されていないことです。そのため、複数のリクエストが返金されました
同じphp ファイルが同時に複数回要求されました。

PHP ファイル ロック flock を使用してみましたが、うまくいかなかったので、引き続き C キューを使用しました
C を使用してポートをリッスンし、HTTP パケットを直接受信し、パケットを HTTP 形式で返します。PHP プログラムは、curl を使用して C プログラムにアクセスします。
これはリモートと同等です。

#多くの場合、特に PHP コードが特定のリソースに対して読み書きできる場合、PHP コードの並列能力は考慮されません。ただし、これは、PHP のすべての操作がアトミックでトランザクション的で並列化可能であることを意味するものではありません。 PHP スクリプトは fastcgi コンテナーで実行され、fastcgi はマルチプロセスであるため、PHP プログラムが重要なリソースにアクセスすると、必然的にプログラムの結果が不正確になります。

この問題の解決策は、ロック機構を使用することです。 PHP は、レコード ロック fcntl、スレッド ロックなど、POSIX 標準でサポートされている Unix ロックを継承せず、Linux システム コール flock (セマフォもロックとして使用できます)、flock の形式でカプセル化するだけです。 ($fp,$type)、$fp はファイル ハンドル、$type は次のとおりです:

/* ファイルを読み取りおよび書き込みのために開くときは、通常、ファイルにロック メカニズムを追加する必要があります*/

1. LOCK_SH 共有ロック :

通常、プロセスがファイルからの読み取り操作を要求する場合、共有ロックが必要です。共有ロックは、任意のプロセス間の読み取り操作をサポートできます。共有ロックを使用してファイルを書き込む場合、プロセスはブロックされ、共有ロックのロックが解除されるまで SLEEP 状態に入ります。

2. LOCK_EX 排他ロック:

通常はプロセス ファイルの書き込み操作に排他ロックを追加します。ファイルがロックされると、ロックが解除されるまで、他のプロセスはファイルにアクセスするときにブロックされます。

3. LOCK_UN ロック解除:

ロックされたファイル ハンドルのロックを解除します

このロック方法は、ロックされたプログラム ブロックの原子性を確かに保証できますが、同時に、ロックされたプログラム ブロックの原子性も犠牲にします。したがって、効率を高めるために、実際のプログラムでは、プログラムのロック コードとロック解除コードの間に埋め込むプログラム ロジック (特に排他ロック) をできるだけ少なくして、プログラムができるだけ早くロック解除されるようにする必要があります。

最後に、ロック機構を追加した後でプログラムを接続します。

<?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 自体はプロセス ロック メカニズムを提供しません。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 のアトミック操作が実装され、競合が回避されます。

php アトミック操作と mysql アトミック操作

アトミック操作に一般的に使用される方法は、データ ロールバックを実装することです。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 サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。