- Q1. PG có khả năng lưu vào bộ nhớ cache / hâm nóng mối quan hệ không?
- Quý 2. Có thể quay lại trạng thái trước của bộ nhớ cache ở nơi nó đã được để trước khi tắt máy chủ cơ sở dữ liệu vì bảo trì không?
Trong các bản phát hành trước đó của PostgreSQL, không có cơ hội làm nóng mối quan hệ hoặc lưu trữ trạng thái bộ nhớ cache, nhưng từ PostgreSQL 9.4 trở đi, mỗi truy vấn trên (Q1, Q2) được giải quyết bằng hai mô-đun đóng góp pg_prewarm và pg_hibernator . Mặc dù thực tế là chúng rất khác biệt về mặt thực tế, tuy nhiên, sự kết hợp này dường như cực kỳ khả thi và hữu ích trong tương lai cho DBA. Tóm lại về những người đóng góp:
pg_prewarm Contrib (Tác giả:Robert Haas), cung cấp khả năng tải dữ liệu quan hệ vào bộ đệm đệm hệ điều hành hoặc bộ đệm đệm PG. Nó có chức năng của số khối đầu tiên hoặc cuối cùng để làm ấm trước. (Lưu ý:Nó không có biện pháp bảo vệ đặc biệt đối với dữ liệu đã được làm ấm trước khỏi việc loại bỏ bộ nhớ cache và cũng như nếu phiên bản cơ sở dữ liệu được khởi động lại sau đó cần làm ấm lại trên các mối quan hệ).
pg_hibernator Contrib (Tác giả:Gurjeet Singh), cung cấp khả năng tự động lưu danh sách nội dung bộ đệm được chia sẻ vào đĩa khi tắt cơ sở dữ liệu và tự động khôi phục bộ đệm khi khởi động cơ sở dữ liệu, giống như lưu / khôi phục ảnh chụp nhanh của shared_buffers. Nó sử dụng mô-đun PG 9.3 để đăng ký “quy trình chạy nền” và tạo ra hai quy trình “Trình tiết kiệm bộ đệm”, “Trình đọc bộ đệm” để lưu / khôi phục. Thật thú vị, với một chút hack, pg_hibernator cũng có thể cho phép nô lệ dự phòng bắt đầu phục vụ các truy vấn với tốc độ tối đa với cùng nội dung của chính, bạn sẽ thấy điều đó sau một phút :).
Cuối cùng, chúng tôi cần pg_buffercache để xem nội dung hiện tại của shared_buffers PostgreSQL. Mô-đun này giúp hiểu được phần trăm bộ đệm được chiếm bởi một mối quan hệ.
Hãy phát huy tác dụng của tất cả những đóng góp này và xem cách họ phục vụ mục đích của hai câu hỏi (Q1, Q2). Tôi sẽ sử dụng bảng 'foo' có kích thước 885MB trên máy ảo cục bộ của tôi, cùng với truy vấn pg_buffercache tiêu chuẩn.
SELECT c.relname,
count(*) AS buffers
FROM pg_class c
INNER JOIN pg_buffercache b ON b.relfilenode=c.relfilenode AND c.relname='foo'
INNER JOIN pg_database d ON (b.reldatabase=d.oid AND d.datname=current_database())
GROUP BY c.relname
ORDER BY 2 DESC LIMIT 10;
Cách sử dụng pg_prewarm Contrib và làm ấm bảng "foo".
postgres=# create extension pg_prewarm;
CREATE EXTENSION
postgres=# dt+
List of relations
Schema | Name | Type | Owner | Size | Description
--------+------+-------+----------+--------+-------------
public | foo | table | postgres | 885 MB |
(1 row)
postgres=# select pg_prewarm('foo');
pg_prewarm
------------
113278
(1 row)
--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)
Cách sử dụng pg_prewarm rất đơn giản và dễ hiểu với đầu ra của các khối được làm ấm trong shared_buffers cho quan hệ 'foo'. Từ pg_buffercache đầu ra truy vấn, chúng tôi có thể đánh giá rằng có 113278 (113278 * 8/1024 =884MB) kích thước khối 8KB của quan hệ ‘foo’ khớp với đầu ra pg_prewarm. Tại đây, nếu máy chủ Postgres khởi động lại vì lý do nào đó, bộ đệm shared_buffers trống và DBA cần phải khởi động lại để quay lại giai đoạn ấm trước đây. Đối với một bàn duy nhất, việc làm ấm lại luôn đơn giản, ngoại trừ một nhóm các bàn, sự phiền toái của nó.
Tại thời điểm này, chúng ta có thể sử dụng tính năng đóng góp của pg_hibernator vì nó có tính linh hoạt trong việc lưu nội dung của shared_buffer và khôi phục lại khi khởi động. Hãy cùng nhau bật pg_hibernator / pg_prewarm và chạy một bài tập tương tự bằng cách chỉ cần bao gồm một bước khởi động lại và xem trạng thái bộ nhớ cache có trở lại như cũ hay không. Tôi sẽ không đề cập đến việc cài đặt pg_hibernator, vì trên git nó được mô tả rất tốt, tuy nhiên, tôi sẽ chuyển trực tiếp đến phần triển khai và khởi động máy chủ với pg_hibernator.
postgres 24623 1 0 02:06 pts/4 00:00:00 /usr/local/pgpatch/pg/bin/postgres -D /usr/local/pgpatch/pg/data_10407
postgres 24627 24623 0 02:06 ? 00:00:00 postgres: logger process
postgres 24631 24623 0 02:06 ? 00:00:00 postgres: checkpointer process
postgres 24632 24623 0 02:06 ? 00:00:00 postgres: writer process
postgres 24633 24623 0 02:06 ? 00:00:00 postgres: wal writer process
postgres 24634 24623 0 02:06 ? 00:00:00 postgres: autovacuum launcher process
postgres 24635 24623 0 02:06 ? 00:00:00 postgres: archiver process
postgres 24636 24623 0 02:06 ? 00:00:00 postgres: stats collector process
postgres 24637 24623 0 02:06 ? 00:00:00 postgres: bgworker: Buffer Saver
postgres 24638 24623 11 02:06 ? 00:00:01 postgres: bgworker: Block Reader 2
In database server logs at startup time:
-bash-4.1$ more postgresql-2014-06-02_083033.log
LOG: database system was shut down at 2014-06-02 08:13:00 PDT
LOG: starting background worker process "Buffer Saver"
LOG: database system is ready to accept connections
LOG: autovacuum launcher started
Kể từ lần đầu tiên pg_hibernator được phát, bạn có thể thấy hai quá trình và cũng ghi nhật ký với một số thông tin liên quan đến việc bắt đầu “Buffer Saver”. Bây giờ, hãy để quan hệ ‘foo’ báo động trước và khởi động lại máy chủ, sau đó kiểm tra trạng thái bộ đệm xem pg_hibernator đã lấp đầy bộ đệm trở lại vị trí ban đầu hay chưa.
-bash-4.1$ psql -p 10407
psql (9.4beta1)
Type "help" for help.
postgres=# select pg_prewarm('foo');
pg_prewarm
------------
113278
(1 row)
--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)
postgres=# q
-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch/pg/data_10407 stop
waiting for server to shut down.... done
server stopped
-bash-4.1$ ls -l $PGDATA/pg_hibernator/
total 12
-rw------- 1 postgres postgres 160 Jun 3 01:41 1.global.save
-rw------- 1 postgres postgres 915 Jun 3 01:41 2.postgres.save
-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch/pg/data_10407 start
server starting
Chúng tôi đã khởi động lại máy chủ cơ sở dữ liệu, hãy kiểm tra nhật ký
-bash-4.1$ more postgresql-2014-06-03_020601.log
LOG: database system was shut down at 2014-06-03 02:05:57 PDT
LOG: starting background worker process "Buffer Saver"
LOG: database system is ready to accept connections
LOG: autovacuum launcher started
LOG: registering background worker "Block Reader 2"
LOG: starting background worker process "Block Reader 2"
LOG: Block Reader 2: restored 113433 blocks
LOG: Block Reader 2: all blocks read successfully
LOG: worker process: Block Reader 2 (PID 24638) exited with exit code 1
LOG: unregistering background worker "Block Reader 2"
LOG: registering background worker "Block Reader 1"
LOG: starting background worker process "Block Reader 1"
LOG: Block Reader 1: restored 20 blocks
LOG: Block Reader 1: all blocks read successfully
LOG: worker process: Block Reader 1 (PID 24664) exited with exit code 1
LOG: unregistering background worker "Block Reader 1"
Vì vậy, “Buffer Reader” đã khôi phục các khối 113433 + 20, trong đó 113278 thuộc quan hệ ‘foo’. Tuyệt vời, hãy kết nối và xem.
-bash-4.1$ psql -p 10407
psql (9.4beta1)
Type "help" for help.
--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)
Tuyệt vời… pg_hibernator đã khôi phục lại trạng thái ấm của bộ nhớ cache mà không có sự can thiệp của DBA.
Một điều tốt nữa về pg_hibernator, một chế độ chờ mới được tạo có thể có cùng nội dung bộ đệm được chia sẻ với chế độ chính, do đó chế độ chờ có thể bắt đầu phục vụ các truy vấn ở tốc độ tối đa. Để thực hiện bài tập này, trong khi sao lưu thư mục $ PGDATA, tôi đã chuyển SIGTERM sang quy trình “Buffer Saver” để nó ghi nội dung shared_buffers trạng thái hiện tại vào đĩa (thư mục $ PGDATA / pg_hibernator) và sau đó thiết lập ở chế độ chờ.
postgres 24637 24623 0 02:06 ? 00:00:00 postgres: bgworker: Buffer Saver
postgres 24653 15179 0 02:06 ? 00:00:01 postgres: wal receiver process streaming 1/6A000A10
postgres 24654 24623 0 02:06 ? 00:00:00 postgres: wal sender process postgres ::1(65011) streaming 1/6A000A10
Sau khi thiết lập, nô lệ của tôi bắt đầu với cùng một nội dung của
chính-bash-4.1$ psql -p 10477
psql (9.4beta1)
Type "help" for help.
postgres=# select pg_is_in_recovery();
pg_is_in_recovery
-------------------
t
(1 row)
--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)
Cảm ơn cả hai tác giả vì một tiện ích mở rộng tuyệt vời về bộ nhớ đệm.