postgresqlでの読み取り中の書き込み:スキャンダル、陰謀、調査

postgresqlリクエストの監視についてはすでに話しました 、その瞬間、postgresqlがさまざまなサーバーリソースでどのように機能するかを完全に理解したように思えました。







postgresリクエストに関する統計を絶えず作業することで、いくつかの異常に気づき始めました。 私は理解するようになりましたが、同時に、postgresのソースコードの理解しやすさを改めて賞賛しました)







katの下で、postgresqlの明白でない動作についての短い話。







「ダーティ」ページを選択します



つまり、SELECTを実行すると、postgresがディスクに書き込む一部のレコードが変更されます。











まず、トランザクションの整合性を確保するためにpostgresで使用されるMVCCメカニズムの簡単な説明から始めます。







データベース内のすべての変更はトランザクション中に発生し、各トランザクションには識別番号txid(int32)があります。







Postgresは、いわゆるタプル(タプル)の形式でテーブルデータを操作します。 タプルは、テーブル内の特定の行のデータと、このデータに関連付けられているメタデータを直接運びます。









画像:www.interdb.jp







xminは、このタプルが作成したトランザクション番号です

xmax-このタプルを削除済みとしてマークしたトランザクション番号









SELECTを実行すると、テーブルからデータを直接検索して選択することに加えて、可視性チェックも実行されます。







非常に単純化された、条件が満たされた場合、txid1という番号のトランザクションはこのtuplを「見る」。







xmin < txid1 < xmax
      
      





ただし、タプルの変更はすぐに発生し、トランザクションには長い時間がかかる可能性があるため、可視性チェック中に、xmin、xmax番号のトランザクションが完了している場合、どのステータスで完了しているかを確認する必要があります。 Postgresは、各トランザクションの現在の状態に関する情報をCLOG(コミットログ)に保存します。







CLOGで多数のトランザクションのステータスをチェックすることはリソースによって非常にコストがかかるため、開発者はこの情報をtuplaのヘッダーに直接「キャッシュ」することを決定しました。 つまり、たとえば、xminが完了したことをSELECTが認識すると、いわゆるヒントビット(トランザクション状態xminおよびxmaxが書き込まれる情報マスクの上の構造)に保存されます。







読書中にダミーの変更はどのように発生するのか、私たちは理解しましたが、「ページ」が何であり、なぜ「ダーティ」であるのかを覚えておく必要があります)







実際、メモリ内およびディスク上のデータの処理は、ほとんどの場合、大きなブロックよりも効率的です。 postgresのこのようなブロックは「ページ」であり、一定数の青写真とそれらに関するメタ情報が含まれています。 少なくとも1つのページタプルを変更すると、そのすべてが「ダーティ」としてマークされます。つまり、ディスク上の状態が異なり、同期する必要があります。 さらに、データベースプロセスの異常終了後にデータの整合性を復元できるように、ほとんどの場合、変更もWALに書き込まれます。







SELECTはディスクへの同期書き込みを引き起こす可能性があります



ご存じのように、pg内のデータの処理はすべてバッファキャッシュを介して行われます。必要なデータが存在しない場合、postgresは(OSページキャッシュを使用して)ディスクからデータを読み取り、キャッシュに入れます。







同時に、キャッシュに場所がない場合、最も要求の少ないページがキャッシュからプッシュされます。 最後に、プリエンプティブな候補ページが汚れている場合は、同時にディスクに書き込む必要があります。







FrozenTransactionId



記事の冒頭で、postgresのトランザクションカウンターは32ビットである、つまり20億トランザクションごとにリセットされることを説明しました。







トランザクションカウンターのリセット時に可視性チェックがカボチャにならないように、特別なプロセスがあります-ラップアラウンドバキューム。









バージョン9.4より前では、このプロセスはダミーのxminを特別な値FrozenTransactionId = 2に置き換えました。 この番号のトランザクションは、他のトランザクションよりも古いと見なされました。 9.4では、xminが「フリーズ」されていることを示すフラグがタプルに追加され、xmin自体は変更されません。







最も注意深い場合:特別な定数BootstrapTransactionId = 1があり、これも他のすべてのトランザクションよりも古いです)







合計



(奇妙な)(フィリピンの意見では)postgres動作のほとんどの場合、パフォーマンスの最適化が原因です。







postgresをいじくり回していると、素晴らしい本「The Internals of PostgreSQL 」を見つけました。








All Articles