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 」を見つけました。



Source: https://habr.com/ru/post/J324494/


All Articles