Cài đặt

các bài viết liên quan tới cài đặt

PostgreSQL 10~ Declarative Partitioning

Lời mở đầu

Partitioning bảng dữ liệu, là chức năng tách dữ liệu vật lý của một bảng dữ liệu lớn sang các bảng nhỏ hơn.
Nhờ phân chia dữ liệu được qua các bảng con nhỏ hơn chức năng được biết đến với những lợi ích như bên dưới.

  • Tăng performance của hệ thống.
    Thay vì truy cập dữ toàn bộ dữ liệu (hay thực hiện scan toàn index), chức năng này chỉ truy cập dữ liệu ở bảng (index) con cần thiết, ngoài ra có thể thực hiện truy vấn song song trên các bảng con nên performance tăng đáng kể nếu có thiết kế thích hợp.
  • Quản lý dễ dàng.
    Đối với dữ liệu thiết kế kiểu INSERT/DELETE diễn ra định kỳ. Bạn có thể xoá dữ liệu bằng DROP bảng con không cần thiết, thay vì thực hiện DELETE và VACUUM.
    Ngoài ra việc migration dữ liệu, backup/restore, hay các thao tác maintenance dữ liệu như VACUUM/REINDEX cũng diễn ra dễ dàng hơn.

PostgreSQL hỗ trợ chức năng Partitioning bảng dữ liệu.
Trước phiên bản 10, PostgreSQL cung cấp chức năng kế thừa (INHERITS) để thực hiện partitioning bảng dữ liệu. Nhưng việc điều hướng dữ liệu đến các bảng con khi INSERT hay UPDATE không diễn ra tự động mà phải sử dụng TRIGGER để thực hiện.

Bài viết này giới thiệu về chức năng partitioning bảng dữ liệu theo kiến trúc mới, chức năng Declarative Partitioning được đưa vào từ phiên bản PostgreSQL 10.

Scale out cho hệ thống PostgreSQL

Trước khi đi vào giới thiệu cụ thể, xin được tóm tắt các kỹ thuật scale out hệ thống của PostgreSQL hiện tại.
Đối với các hệ thống lớn hay các hệ thống dữ liệu có độ lớn tăng dần theo thời gian, việc thiết kế scale out (chia nhỏ dữ liệu thành nhiều phần để dễ quản lý) là một việc quan trọng nếu không muốn xử lý các vấn đề về dung lượng sau vận hành. PostgeSQL cung cấp các chức năng như bên dưới để hỗ trợ scale out hệ thống.

  • Sử dụng TABLESPACE
    Từ các phiên bản cũ TABLESPACE đã được sử dụng như công cụ để phân tán dữ liệu qua nhiều đĩa cứng giảm disk I/O. Nhưng gần đây gần đây nhiều hệ thống chuyển qua sử dụng RAID, nên chức năng này cũng không được sử dụng nhiều
  • Sử dụng các software liên quan
    Sử dụng một số cluster software như PostgreSQL-XL, pacemaker, pgpool-II sử dụng slave node để tham chiếu giảm tải cho master. Hay dùng chức năng load balancer (của pgpool-II),... cũng có thể được coi là một trong các giải pháp scale out. Giải pháp này hơi khó khăn về mặt bảo trì về cấu trúc hệ thống.
  • Cascade Replication
    Là chức năng đưa vào từ phiên bản 9.2 của PostgreSQL, slave node có thể chuyển tiếp đồng bộ sang các node slave mới.Ta có thể sử dụng chức năng này để scale out cho hệ thống. Hạn chế của cấu trúc này là cascade replication chỉ support phi đồng bộ, thời gian phản ánh WAL (transaction log) lên các slave node có thể trễ, nên dữ liệu trên slave không phải lúc nào cũng là mới nhất.
  • Sử dụng postgres_fwd
    Contrib postgres_fwd cho phép PostgreSQL kết nối tới server bên ngoài. PostgreSQL 9.6 hỗ trợ push down, kết quả được sử lý (sort, join, ...) ở remote server trước khi gửi về local. Việc này làm giảm tải rất nhiều cho local server trong các hệ thống lớn.
    Chức năng này trong tương lai được kỳ vọng là tạo thành nền tảng cho chức năng Sharding giống như các RDBMS như mongodb.
  • Partitioning Table
    Chức năng phân tán dữ liệu từ một bảng sang nhiều bảng con để tăng khả năng scale out cho hệ thống. Từ Application chỉ cần chú ý tới bảng dữ liệu cha. Dữ liệu khi INSERT/UPDATE vào bảng cha sẽ được phân tán tới các bảng con. Khi SELECT dữ liệu bảng cha, nhờ chức năng Partitioning dữ liệu các bảng con được tập hợp lại và gửi lại cho bảng cha. Các hệ thống cũ thường sử dụng chức năng này kết hợp với TABLESPACE để scale out hệ thống.

Chức năng Partitioning của PostgreSQL

Chức năng này cũng là một chức năng được được PostgreSQL đưa vào sớm từ phiên bản 8.1. Mặc dù có một số hạn chế overhead do phải thiết dựa trên trigger, nhưng chức năng này cũng được sử dụng rộng dãi cho tới nay. Từ phiên bản 10 PostgreSQL hỗ trợ phương thức partitioning mới, không dựa vào trigger nên có performance tốt và cách sử dụng đơn giản.

Chức năng Partitioning sử dụng kế thừa

Ở các phiên bản trước của PostgreSQL 10, để sử dụng chức năng partitioning. Ta cần các bước tổng quan như sau.

  1. Tạo bảng master
  2. Tạo các bảng con
  3. Tạo TRIGGER cho bảng master

Tạo bảng master

Ta tạo bảng master với các trường cần thiết.
Ở đây ta sử dụng cột range cho chức năng partitioning.

10000 postgres@postgres=# CREATE TABLE parent(id integer, childname text, range bigint);
CREATE TABLE

Tạo các bảng con

Bạn có thể định nghĩa số lượng bảng con tuỳ ý theo thiết kế hệ thống của bạn. Nhưng community khuyến cáo không nên sử dụng quá 100 bảng con.
Ví dụ bên dưới mình tạo 3 bảng con kế thừa bảng master.
Ở đây mình sử dụng ràng buộc CHECK dữ liệu, để bảng con tương ứng chỉ chứa những giá trị cho phép.
Khi tham chiếu dữ liệu bảng cha, PostgreSQL có thể dựa vào ràng buộc CHECK của bảng con để bỏ qua tham chiếu tới các bảng con không cần thiết.

10000 postgres@postgres=# CREATE TABLE child1(check(range <= 99999)) inherits(parent);
CREATE TABLE
10000 postgres@postgres=# CREATE TABLE child2(check(range > 99999 and range <= 199999)) inherits(parent);
CREATE TABLE
10000 postgres@postgres=# CREATE TABLE child3(check(range > 199999)) inherits(parent);
CREATE TABLE
10000 postgres@postgres=#

Tạo TRIGGER cho bảng master

Mặc định khi tạo table con ta đã có thể sử dụng chức năng partitioning để truy suất dữ liệu các bảng con thông qua bảng master. Nhưng để insert dữ liệu tới các bảng con thông qua bảng master ta phải sử dụng chức năng TRIGGER của PostgreSQL.
Ví dụ bên dưới thực hiện:

  • Tạo hàm TRIGGER insert_to_child cho phép kiểm tra dữ liệu INSERT và, thực hiện INSERT vào các bảng con tương ứng mà không thực hiện INSERT trên bảng master (return NULL;).
  • Sử dụng hàm insert_to_child đã định nghĩa để tạo TRIGGER cho bảng master trước khi INSERT dữ liệu.

Ta có thể sử dụng chức năng RULE của PostgreSQL thay vì tạo TRIGGER. RULE có overhead nhiều hơn TRIGGER khi INSERT 1 hàng, nhưng ngược lại khi INSERT một khối lượng lớn dữ liệu (ví dụ như COPY) thì overhead nhỏ hơn TRIGGER.

10000 postgres@postgres=# CREATE OR REPLACE FUNCTION insert_to_child () RETURNS TRIGGER
AS 
$$ 
BEGIN
    IF (NEW.range <= 99999) THEN
        INSERT INTO child1 VALUES (NEW.*);
    ELSIF (NEW.range > 99999 AND NEW.range <= 199999) THEN
        INSERT INTO child2 VALUES (NEW.*);
    ELSIF (NEW.range > 199999) THEN
        INSERT INTO child3 VALUES (NEW.*);
    ELSE
        RAISE EXCEPTION 'out of range';
    END IF;
    RETURN NULL;
END;
$$
LANGUAGE PLPGSQL;
CREATE FUNCTION
10000 postgres@postgres=# CREATE TRIGGER insert_to_child_tg BEFORE INSERT ON parent FOR EACH ROW EXECUTE PROCEDURE insert_to_child();
CREATE TRIGGER

Sau khi tạo được bảng con và TRIGGER cho bảng master. Bảng master sẽ có cấu trúc như bên dưới.

10000 postgres@postgres=# \d+ parent
                                    Table "public.parent"
  Column   |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
-----------+---------+-----------+----------+---------+----------+--------------+-------------
 id        | integer |           |          |         | plain    |              | 
 childname | text    |           |          |         | extended |              | 
 range     | bigint  |           |          |         | plain    |              | 
Triggers:
    insert_to_child_tg BEFORE INSERT ON parent FOR EACH ROW EXECUTE PROCEDURE insert_to_child()
Child tables: child1,
              child2,
              child3

Thực hiện truy vấn

INSERT & SELECT dữ liệu

Ví dụ bên dưới INSERT 3 dòng dữ liệu thông qua bảng master và xác nhận dữ liệu đã được ghi vào các bảng con nhờ TRIGGER đã định nghĩa.

10000 postgres@postgres=# INSERT INTO parent VALUES (1,'a',1), (2,'b',199999), (3,'c',200000);
INSERT 0 0
10000 postgres@postgres=# SELECT * FROM parent ;
 id | childname | range  
----+-----------+--------
  1 | a         |      1
  2 | b         | 199999
  3 | c         | 200000
(3 rows)
10000 postgres@postgres=# SELECT * FROM parent ;
 id | childname | range  
----+-----------+--------
  1 | a         |      1
  2 | b         | 199999
  3 | c         | 200000
(3 rows)

10000 postgres@postgres=# SELECT * FROM child1;
 id | childname | range 
----+-----------+-------
  1 | a         |     1
(1 row)

10000 postgres@postgres=# SELECT * FROM child2;
 id | childname | range  
----+-----------+--------
  2 | b         | 199999
(1 row)

10000 postgres@postgres=# SELECT * FROM child3;
 id | childname | range  
----+-----------+--------
  3 | c         | 200000
(1 row)

Như kết quả EXPLAIN của câu lệnh SELECT bảng master bên dưới. Dữ liệu được tìm kiếm ở các bảng con chứa dữ liệu tương ứng và bảng master.

10000 postgres@postgres=# EXPLAIN (ANALYZE,VERBOSE) SELECT * FROM parent WHERE range IN (1,199999);
                                                   QUERY PLAN                                                   
----------------------------------------------------------------------------------------------------------------
 Append  (cost=0.00..48.37 rows=23 width=44) (actual time=0.028..0.039 rows=2 loops=1)
   ->  Seq Scan on public.parent  (cost=0.00..0.00 rows=1 width=44) (actual time=0.011..0.011 rows=0 loops=1)
         Output: parent.id, parent.childname, parent.range
         Filter: (parent.range = ANY ('{1,199999}'::bigint[]))
   ->  Seq Scan on public.child1  (cost=0.00..24.12 rows=11 width=44) (actual time=0.015..0.016 rows=1 loops=1)
         Output: child1.id, child1.childname, child1.range
         Filter: (child1.range = ANY ('{1,199999}'::bigint[]))
   ->  Seq Scan on public.child2  (cost=0.00..24.12 rows=11 width=44) (actual time=0.008..0.009 rows=1 loops=1)
         Output: child2.id, child2.childname, child2.range
         Filter: (child2.range = ANY ('{1,199999}'::bigint[]))
 Planning Time: 1.433 ms
 Execution Time: 0.082 ms
(12 rows)

10000 postgres@postgres=# show constraint_exclusion ;
 constraint_exclusion 
----------------------
 partition
(1 row)

PostgreSQL bỏ qua tìm kiếm dữ liệu dựa vào ràng buộc CHECK thông qua tham số constraint_exclusion. Nếu tham số này thiết lập là on hoặc partition, PostgreSQL sẽ sử dụng ràng buộc CHECK để bỏ qua tìm kiếm ở bảng con không cần thiết.
Ví dụ bên dưới khi set constraint_exclusion sang off, PostgreSQL scan tất cả các bảng con.

10000 postgres@postgres=# set constraint_exclusion TO off;
SET
10000 postgres@postgres=# EXPLAIN (ANALYZE,VERBOSE) SELECT * FROM parent WHERE range IN (1,199999);
                                                   QUERY PLAN                                                   
----------------------------------------------------------------------------------------------------------------
 Append  (cost=0.00..72.55 rows=34 width=44) (actual time=0.021..0.053 rows=2 loops=1)
   ->  Seq Scan on public.parent  (cost=0.00..0.00 rows=1 width=44) (actual time=0.006..0.006 rows=0 loops=1)
         Output: parent.id, parent.childname, parent.range
         Filter: (parent.range = ANY ('{1,199999}'::bigint[]))
   ->  Seq Scan on public.child1  (cost=0.00..24.12 rows=11 width=44) (actual time=0.013..0.014 rows=1 loops=1)
         Output: child1.id, child1.childname, child1.range
         Filter: (child1.range = ANY ('{1,199999}'::bigint[]))
   ->  Seq Scan on public.child2  (cost=0.00..24.12 rows=11 width=44) (actual time=0.007..0.007 rows=1 loops=1)
         Output: child2.id, child2.childname, child2.range
         Filter: (child2.range = ANY ('{1,199999}'::bigint[]))
   ->  Seq Scan on public.child3  (cost=0.00..24.12 rows=11 width=44) (actual time=0.022..0.022 rows=0 loops=1)
         Output: child3.id, child3.childname, child3.range
         Filter: (child3.range = ANY ('{1,199999}'::bigint[]))
         Rows Removed by Filter: 1
 Planning Time: 0.299 ms
 Execution Time: 0.128 ms
(16 rows)

UPDATE dữ liệu

Như ví dụ bên dưới vì ta chưa tạo TRIGGER khi UPDATE bảng master. Nên dữ liệu UPDATE không nằm trong khoảng của ràng buộc CHECK sẽ gây ra lỗi. Nếu muốn khắc phục lỗi này ta phải định nghĩa thêm TRIGGER thực hiện điều hướng dữ liệu UPDATE tới các bảng con tương ứng.

10000 postgres@postgres=# UPDATE parent SET range = 200000 WHERE range = 1;
ERROR:  new row for relation "child1" violates check constraint "child1_range_check"
DETAIL:  Failing row contains (1, a, 200000).
10000 postgres@postgres=# UPDATE parent SET range = 2 WHERE range = 1;
UPDATE 1
10000 postgres@postgres=# 

Declarative Partitioning (PostgreSQL 10 ~)

Nếu như ta phải thực hiện nhiều thao tác mới sử dụng được chức năng Partitioning sử dụng kế thừa như trên, thì từ phiên bản 10 ta chỉ đơn giản thực hiện các thao tác bên dưới là có thể sử dụng được.

  1. Tạo bảng master với tuỳ chọn partitioning
  2. Tạo bảng con tương ứng cho bảng master

Tạo bảng master Declarative Partitioning

Chức năng Declarative Partitioning hỗ trợ các phương thức partitioning như sau:

  • range (PostgreSQL 10~) Chỉ định phạm vi giá trị cho cột khoá của mỗi bảng con
  • list (PostgreSQL 10~) Chỉ định danh sách giá trị cho cột khoá của mỗi bảng con
  • hash (PostgreSQL 11~)
    Sử dụng hash để chỉ định giá trị cho cột khoá của mỗi bảng con

Ví dụ bên dưới mình sử dụng phương thức range (tương ứng với ví dụ ở chức năng partitioning sử dụng kế thừa).

10000 postgres@postgres=# CREATE TABLE parent_pg10(id integer, name text, range bigint) PARTITION BY RANGE (range);
CREATE TABLE

Tạo bảng con tương ứng cho bảng master

10000 postgres@postgres=# CREATE TABLE child1_pg10 PARTITION OF parent_pg10 FOR VALUES FROM (0) TO (99999) ;
CREATE TABLE
10000 postgres@postgres=# CREATE TABLE child2_pg10 PARTITION OF parent_pg10 FOR VALUES FROM (99999) TO (200000) ;
CREATE TABLE
10000 postgres@postgres=# CREATE TABLE child3_pg10 PARTITION OF parent_pg10 FOR VALUES FROM (200000) TO (9223372036854775807) ;
CREATE TABLE

Sau khi tạo được bảng con. Bảng master sẽ có cấu trúc như bên dưới.

10000 postgres@postgres=# \d+ parent_pg10
                                Table "public.parent_pg10"
 Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
--------+---------+-----------+----------+---------+----------+--------------+-------------
 id     | integer |           |          |         | plain    |              | 
 name   | text    |           |          |         | extended |              | 
 range  | bigint  |           |          |         | plain    |              | 
Partition key: RANGE (range)
Partitions: child1_pg10 FOR VALUES FROM ('0') TO ('99999'),
            child2_pg10 FOR VALUES FROM ('99999') TO ('200000'),
            child3_pg10 FOR VALUES FROM ('200000') TO ('9223372036854775807')

Thực hiện truy vấn

INSERT & SELECT dữ liệu

Ví dụ bên dưới INSERT 3 dòng dữ liệu thông qua bảng master và xác nhận dữ liệu đã được ghi vào các bảng con nhờ chức năng Declarative Partitioning.

10000 postgres@postgres=# INSERT INTO parent_pg10 VALUES (1,'a',1), (2,'b',199999), (3,'c',200000);
INSERT 0 3
10000 postgres@postgres=# SELECT * FROM parent_pg10 ;
 id | name | range  
----+------+--------
  1 | a    |      1
  2 | b    | 199999
  3 | c    | 200000
(3 rows)

10000 postgres@postgres=# SELECT * FROM child1_pg10 ;
 id | name | range 
----+------+-------
  1 | a    |     1
(1 row)

10000 postgres@postgres=# SELECT * FROM child2_pg10 ;
 id | name | range  
----+------+--------
  2 | b    | 199999
(1 row)

10000 postgres@postgres=# SELECT * FROM child3_pg10 ;
 id | name | range  
----+------+--------
  3 | c    | 200000
(1 row)

Như kết quả EXPLAIN của câu lệnh SELECT bảng master bên dưới. Mặc định dữ liệu được tìm kiếm qua các bảng con chứa dữ liệu tương ứng (bảng master không chứa dữ liệu).

10000 postgres@postgres=# EXPLAIN (ANALYZE,VERBOSE) SELECT * FROM parent_pg10 WHERE range IN (1,199999);
                                                     QUERY PLAN                                                      
---------------------------------------------------------------------------------------------------------------------
 Append  (cost=0.00..48.36 rows=22 width=44) (actual time=0.028..0.041 rows=2 loops=1)
   ->  Seq Scan on public.child1_pg10  (cost=0.00..24.12 rows=11 width=44) (actual time=0.027..0.028 rows=1 loops=1)
         Output: child1_pg10.id, child1_pg10.name, child1_pg10.range
         Filter: (child1_pg10.range = ANY ('{1,199999}'::bigint[]))
   ->  Seq Scan on public.child2_pg10  (cost=0.00..24.12 rows=11 width=44) (actual time=0.010..0.010 rows=1 loops=1)
         Output: child2_pg10.id, child2_pg10.name, child2_pg10.range
         Filter: (child2_pg10.range = ANY ('{1,199999}'::bigint[]))
 Planning Time: 1.352 ms
 Execution Time: 0.099 ms
(9 rows)

Cũng giống với chức năng partitioning sử dụng kết thừa. Sau khi set tham số constraint_exclusion sang off, dữ liệu được tìm kiếm trên tất cả các bảng.

Ở phiên bản PostgreSQL 11, PostgreSQL không sử dụng exclusion constraint cho việc loại trừ tìm kiếm dữ liệu bảng con không cần thiết (prunning), nên tham số constraint_exclusion không có hiệu lực, thay vào đó ta sử dụng tham số enable_partition_pruning.

10000 postgres@postgres=# set constraint_exclusion to off;
SET
10000 postgres@postgres=# set constraint_EXPLAIN (ANALYZE,VERBOSE) SELECT * FROM parent_pg10 WHERE range IN (1,199999);
                                                     QUERY PLAN                                                      
---------------------------------------------------------------------------------------------------------------------
 Append  (cost=0.00..26.15 rows=13 width=44) (actual time=0.017..0.046 rows=2 loops=1)
   ->  Seq Scan on public.child1_pg10  (cost=0.00..1.01 rows=1 width=44) (actual time=0.016..0.017 rows=1 loops=1)
         Output: child1_pg10.id, child1_pg10.name, child1_pg10.range
         Filter: (child1_pg10.range = ANY ('{1,199999}'::bigint[]))
   ->  Seq Scan on public.child2_pg10  (cost=0.00..1.01 rows=1 width=44) (actual time=0.007..0.007 rows=1 loops=1)
         Output: child2_pg10.id, child2_pg10.name, child2_pg10.range
         Filter: (child2_pg10.range = ANY ('{1,199999}'::bigint[]))
   ->  Seq Scan on public.child3_pg10  (cost=0.00..24.12 rows=11 width=44) (actual time=0.020..0.020 rows=0 loops=1)
         Output: child3_pg10.id, child3_pg10.name, child3_pg10.range
         Filter: (child3_pg10.range = ANY ('{1,199999}'::bigint[]))
         Rows Removed by Filter: 1
 Planning time: 0.278 ms
 Execution time: 0.090 ms
(13 rows)

UPDATE dữ liệu

  • Ở phiên bản PostgreSQL 10, cũng giống như với partitioning sử dụng kế thừa, câu lệnh UPDATE thất bại nếu dữ liệu mới cho cột key nằm ở partition khác.
10000 postgres@postgres=# UPDATE parent_pg10 SET range = 200001 WHERE range = 1;
ERROR:  new row for relation "child1_pg10" violates partition constraint
DETAIL:  Failing row contains (1, a, 200001).
  • Ở phiên bản PostgreSQL 11, hạn chế bên trên đã được loại bỏ, dữ liệu tự động điều hướng sang partition tương ứng.
11000 postgres@postgres=# UPDATE parent_pg10 SET range = 200001 WHERE range = 1;
UPDATE 1
11000 postgres@postgres=# SELECT * FROM child3_pg10 ;
 id | name | range  
----+------+--------
  3 | c    | 200000
  1 | a    | 200001
(2 rows)

Ở trường hợp dữ liệu đồng thời được update trên một cột key, có thể xảy ra lỗi, vui lòng xem mục hạn chế ở cuối bài viết này.

Performance

Như ví dụ bên dưới. Do có overhead bởi TRIGGER, Performance của INSERT giảm rõ rệt (~10 lần) khi sử dụng phương thức partitioning sử dụng kế thừa.

  • Kết quả EXPLAIN sử dụng phương thức partitioning sử dụng kế thừa.
10000 postgres@postgres=# EXPLAIN (ANALYZE,VERBOSE) INSERT INTO parent SELECT generate_series(1,999999),'CHILD', random()*10000000;
                                                         QUERY PLAN                                                         
----------------------------------------------------------------------------------------------------------------------------
 Insert on public.parent  (cost=0.00..17.52 rows=1000 width=44) (actual time=33340.724..33340.724 rows=0 loops=1)
   ->  Subquery Scan on "*SELECT*"  (cost=0.00..17.52 rows=1000 width=44) (actual time=0.008..1278.986 rows=999999 loops=1)
         Output: "*SELECT*".generate_series, 'CHILD'::text, "*SELECT*"."?column?_1"
         ->  ProjectSet  (cost=0.00..5.02 rows=1000 width=44) (actual time=0.005..692.425 rows=999999 loops=1)
               Output: generate_series(1, 999999), NULL::unknown, (random() * '10000000'::double precision)
               ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=1)
 Planning Time: 0.076 ms
 Trigger insert_to_child_tg: time=31178.106 calls=999999
 Execution Time: 33340.757 ms
(9 rows)
  • Kết quả EXPLAIN sử dụng phương thức Declarative Partitioning.
10000 postgres@postgres=# EXPLAIN (ANALYZE,VERBOSE) INSERT INTO parent_pg10 SELECT generate_series(1,999999),'CHILD', random()*10000000;
                                                        QUERY PLAN                                                         
---------------------------------------------------------------------------------------------------------------------------
 Insert on public.parent_pg10  (cost=0.00..17.52 rows=1000 width=44) (actual time=3814.105..3814.105 rows=0 loops=1)
   ->  Subquery Scan on "*SELECT*"  (cost=0.00..17.52 rows=1000 width=44) (actual time=0.011..646.356 rows=999999 loops=1)
         Output: "*SELECT*".generate_series, 'CHILD'::text, "*SELECT*"."?column?_1"
         ->  ProjectSet  (cost=0.00..5.02 rows=1000 width=44) (actual time=0.007..328.986 rows=999999 loops=1)
               Output: generate_series(1, 999999), NULL::unknown, (random() * '10000000'::double precision)
               ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.002 rows=1 loops=1)
 Planning Time: 0.100 ms
 Execution Time: 3814.203 ms
(8 rows)

Một số hạn chế và chú ý liên quan tới chức năng Declarative Partitioning

  1. Không hỗ trợ Primary Key cho cột khoá
10000 postgres@postgres=# alter table child1_pg10 add primary key (range);
ERROR:  multiple primary keys for table "child1_pg10" are not allowed
  1. Không hỗ trợ khoá ngoại lai
    Không hỗ hợ Primary Key đồng nghĩa với không hỗ trợ khoá ngoại lai tham chiếu tới cột khoá.
10000 postgres@postgres=# create table grand_child(id integer, name text, range bigint references child1(range));
ERROR:  there is no unique constraint matching given keys for referenced table "child1"
  1. Cập nhật dữ liệu sang partition khác (hạn chế ở phiên bản PostgreSQL 10, đã được fixed ở phiên bản 11)
  • Ở phiên bản PostgreSQL 10, Declarative Partitioning không hỗ trợ lệnh UPDATE chuyển dữ liệu từ partition này qua partition khác.
10000 postgres@postgres=# UPDATE parent_pg10 SET range = 200001 WHERE range = 1;
ERROR:  new row for relation "child1_pg10" violates partition constraint
DETAIL:  Failing row contains (1, a, 200001).
  • Phiên bản PostgreSQL 11 đã loại bỏ được hạn chế bên trên, nhưng nếu dữ liệu đang được chuyển qua partition khác, cùng lúc đó có lệnh UPDATE đối với dữ liệu tương ứng sẽ có thể xảy ra lỗi như bên dưới.
11000 postgres@postgres=#* update parent_pg10 SET range = 1000;
ERROR:  tuple to be updated was already moved to another partition due to concurrent update
  1. Không hỗ trợ ON CONFLICT (hạn chế ở phiên bản PostgreSQL 10, đã được fixed ở phiên bản 11)
  • Ở phiên bản 10 Declarative Partitioning không hỗ trợ cấu trúc ON CONFLICT.
10000 postgres@postgres=# insert into parent_pg10 values(1,'a',1) on conflict do nothing;
ERROR:  ON CONFLICT clause is not supported with partitioned tables
  • Hạn chế này đã được fixed tại phiên bản 11.
11000 postgres@postgres=#* into parent_pg10 values(1,'a',1) on conflict do nothing;
INSERT 0 0
  1. TRIGGER mức độ dòng dữ liệu phải được định nghĩa ở bảng con, vì bảng cha không chứa dữ liệu.

  2. Bảng con của một bảng master không thể có cả bảng cố định và bảng tạm thời (temp table).

11000 postgres@postgres=# CREATE temp TABLE child3_pg11 PARTITION OF parent_pg10 FOR VALUES FROM (200000) TO (9223372036854775807) ;
ERROR:  cannot create a temporary relation as partition of permanent relation "parent_pg10"
  1. Không hỗ trợ full cho postgres_fdw (hạn chế ở phiên bản PostgreSQL 10, đã được fixed ở phiên bản 11).

Ta có thể sử dụng chức năng partitioning table kết hợp với postgres_fdw để scale out hệ thống như bên dưới ở phiên bản PostgreSQL 11.
Ở phiên bản 10 có thể cấu hình được hệ thống bên dưới, nhưng hệ thống chưa hỗ trợ hoàn toàn các câu lệnh SQL cho postgres_fdw.
Hệ thống ví dụ bên dưới, sử dụng chức năng partitioning với 2 bảng con, 2 bảng con này tiếp tục được đồng bộ sang các DB install khác thông qua chức năng postgres_fdw.

===========================================
DB install 1:         Bảng master
                           |
                   +- partitioning -+
                   |                |
               bảng con 1      bảng con 2
                   |                |
===================+==postgres_fdw==+======
DB install 2:      |                |
               bảng con 1           |
                   |                |
===================+==postgres_fdw==+======
DB install 3:                       |
                               bảng con 2
                                    |
===========================================

Những thay đổi ở phiên bản PostgreSQL 11

Ở phiên bản PostgreSQL 11, có 3 cải thiện chính như bên dưới.

Faster partition pruning

Ở phiên bản 10 PostgreSQL sử dụng constraint_exclusion để bỏ qua partition không cần thiết. Việc loại bỏ này thực hiện bởi sử dụng giá trị ở WHERE clause rồi so sánh với các metadata của từng partition. Phiên bản 11 không sử dụng constraint_exclusion nữa mà thực hiện tìm kiếm trực tiếp tới partition cần thiết làm tăng performance.

Partition Pruning at Execution Time

Phiên bản 10 thực hiện bỏ qua partition không cần thiết (prunning) ở giai đoạn planning. Nếu chỉ thực hiện ở giai đoạn này, PostgreSQL sẽ không thể thực hiện prunning được những câu lệnh có truy vấn phụ như ví dụ bên dưới.

  • Ở phiên bản 10, PostgreSQL thực hiện scan trên tất cả các bảng con khi biểu thức tìm kiếm là một truy vấn phụ vì truy vấn chưa được thực thi ở giai đoạn planning.
10000 postgres@postgres=# explain (analyze, verbose) select * from parent_pg10 where range = (select id from temp);
                                                        QUERY PLAN                                                         
---------------------------------------------------------------------------------------------------------------------------
 Append  (cost=35.50..19111.50 rows=3 width=18) (actual time=210.733..210.733 rows=0 loops=1)
   InitPlan 1 (returns $0)
     ->  Seq Scan on public.temp  (cost=0.00..35.50 rows=2550 width=4) (actual time=0.006..0.007 rows=1 loops=1)
           Output: temp.id
   ->  Seq Scan on public.child1_pg10  (cost=0.00..192.64 rows=1 width=18) (actual time=3.033..3.033 rows=0 loops=1)
         Output: child1_pg10.id, child1_pg10.name, child1_pg10.range
         Filter: (child1_pg10.range = $0)
         Rows Removed by Filter: 10051
   ->  Seq Scan on public.child2_pg10  (cost=0.00..192.30 rows=1 width=18) (actual time=2.420..2.420 rows=0 loops=1)
         Output: child2_pg10.id, child2_pg10.name, child2_pg10.range
         Filter: (child2_pg10.range = $0)
         Rows Removed by Filter: 10024
   ->  Seq Scan on public.child3_pg10  (cost=0.00..18691.06 rows=1 width=18) (actual time=205.277..205.277 rows=0 loops=1)
         Output: child3_pg10.id, child3_pg10.name, child3_pg10.range
         Filter: (child3_pg10.range = $0)
         Rows Removed by Filter: 979925
 Planning time: 0.287 ms
 Execution time: 210.785 ms
(18 rows)
  • PostgreSQL 11 thực hiện prunning khi thực thi truy vấn. Nên có thể đối ứng cả truy vấn phụ.
11000 postgres@postgres=# explain (analyze, verbose) select * from parent_pg10 where range = (select id from temp);
                                                     QUERY PLAN                                                      
---------------------------------------------------------------------------------------------------------------------
 Append  (cost=35.50..18906.51 rows=3 width=18) (actual time=6.997..6.997 rows=0 loops=1)
   InitPlan 1 (returns $0)
     ->  Seq Scan on public.temp  (cost=0.00..35.50 rows=2550 width=4) (actual time=0.799..0.801 rows=1 loops=1)
           Output: temp.id
   ->  Seq Scan on public.child1_pg10  (cost=0.00..190.64 rows=1 width=18) (actual time=6.157..6.157 rows=0 loops=1)
         Output: child1_pg10.id, child1_pg10.name, child1_pg10.range
         Filter: (child1_pg10.range = $0)
         Rows Removed by Filter: 10051
   ->  Seq Scan on public.child2_pg10  (cost=0.00..189.30 rows=1 width=18) (never executed)
         Output: child2_pg10.id, child2_pg10.name, child2_pg10.range
         Filter: (child2_pg10.range = $0)
   ->  Seq Scan on public.child3_pg10  (cost=0.00..18491.06 rows=1 width=18) (never executed)
         Output: child3_pg10.id, child3_pg10.name, child3_pg10.range
         Filter: (child3_pg10.range = $0)
 Planning Time: 0.377 ms
 Execution Time: 7.052 ms
(16 rows)

Như đã nói ở trên. Do PostgreSQL 10 không sử dụng exclusion constraint để bỏ qua partition không cần thiết, nên tham số constraint_exclusion không có hiệu lực đối với Declarative Partitioning trên phiên bản 11, thay vào đó là parameter enable_partition_pruning (mặc định là on).

Hỗ trợ hash partitioning

Ngoài kiểu range và list ở PostgreSQL 10, PostgreSQL 11 hỗ trợ thêm partitioning kiểu hash.
Thông qua hàm hash của PostgreSQL, dữ liệu INSERT vào cột khoá (cột partitioning) sẽ được điều hướng tới bảng con tương ứng.

Ví dụ:

  • Tạo bảng master
11000 postgres@postgres=# create table parent_hash(id name, child text, hashval text) partition by hash (hashval);
CREATE TABLE
  • Tạo bảng con
    Modulus có thể hiểu là số lượng partition cho bảng master. Remainder là số dư khi chia hash của giá trị INSERT vào cho số Modulus tương ứng.
11000 postgres@postgres=# create table child1_hash partition of parent_hash for values with (modulus 3, remainder 0);
CREATE TABLE
11000 postgres@postgres=# create table child2_hash partition of parent_hash for values with (modulus 3, remainder 1);
CREATE TABLE
11000 postgres@postgres=# create table child3_hash partition of parent_hash for values with (modulus 3, remainder 2);
CREATE TABLE
  • Thực hiện truy vấn
11000 postgres@postgres=# explain (analyze, verbose) insert into parent_hash select generate_series(1,10000000),'child',random()::text;
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Insert on public.parent_hash  (cost=0.00..20.02 rows=1000 width=128) (actual time=66464.827..66464.827 rows=0 loops=1)
   ->  Subquery Scan on "*SELECT*"  (cost=0.00..20.02 rows=1000 width=128) (actual time=0.024..23043.207 rows=10000000 loops=1)
         Output: "*SELECT*".generate_series, 'child'::text, "*SELECT*".random
         ->  ProjectSet  (cost=0.00..5.03 rows=1000 width=68) (actual time=0.018..16336.944 rows=10000000 loops=1)
               Output: generate_series(1, 10000000), NULL::unknown, (random())::text
               ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual time=0.002..0.002 rows=1 loops=1)
 Planning Time: 0.091 ms
 Execution Time: 66466.265 ms
(8 rows)
11000 postgres@postgres=# \d+ parent_hash 
                               Table "public.parent_hash"
 Column  | Type | Collation | Nullable | Default | Storage  | Stats target | Description 
---------+------+-----------+----------+---------+----------+--------------+-------------
 id      | name |           |          |         | plain    |              | 
 child   | text |           |          |         | extended |              | 
 hashval | text |           |          |         | extended |              | 
Partition key: HASH (hashval)
Partitions: child1_hash FOR VALUES WITH (modulus 3, remainder 0),
            child2_hash FOR VALUES WITH (modulus 3, remainder 1),
            child3_hash FOR VALUES WITH (modulus 3, remainder 2)

11000 postgres@postgres=# select count(*) from child1_hash;
  count  
---------
 3332642
(1 row)

11000 postgres@postgres=# select count(*) from child2_hash;
  count  
---------
 3333466
(1 row)

11000 postgres@postgres=# select count(*) from child3_hash;
  count  
---------
 3333892
(1 row)

11000 postgres@postgres=# select count(*) from only parent_hash;
 count 
-------
     0
(1 row)

-- Dữ liệu được tìm kiếm ở bảng tương ứng (public.child1_hash)
11000 postgres@postgres=# explain (analyze, verbose) select * from parent_hash where hashval = '0.413760441355407';
                                                                QUERY PLAN                                                                
------------------------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..74228.30 rows=1 width=88) (actual time=1.003..522.970 rows=1 loops=1)
   Output: child1_hash.id, child1_hash.child, child1_hash.hashval
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Append  (cost=0.00..73228.20 rows=1 width=88) (actual time=342.915..516.902 rows=0 loops=3)
         Worker 0: actual time=514.096..514.096 rows=0 loops=1
         Worker 1: actual time=514.136..514.136 rows=0 loops=1
         ->  Parallel Seq Scan on public.child1_hash  (cost=0.00..73228.19 rows=1 width=88) (actual time=342.908..516.894 rows=0 loops=3)
               Output: child1_hash.id, child1_hash.child, child1_hash.hashval
               Filter: (child1_hash.hashval = '0.413760441355407'::text)
               Rows Removed by Filter: 1110880
               Worker 0: actual time=514.088..514.088 rows=0 loops=1
               Worker 1: actual time=514.127..514.127 rows=0 loops=1
 Planning Time: 1.810 ms
 Execution Time: 526.021 ms
(15 rows)

--chưa hỗ trợ LIKE clause (dữ liệu không được prunning)  
11000 postgres@postgres=# explain (analyze, verbose) select * from parent_hash where hashval like '%41376044135%';
                                                                 QUERY PLAN                                                                 
--------------------------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..220838.95 rows=1002 width=88) (actual time=2.684..1956.412 rows=1 loops=1)
   Output: child2_hash.id, child2_hash.child, child2_hash.hashval
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Append  (cost=0.00..219738.75 rows=417 width=88) (actual time=1298.137..1949.377 rows=0 loops=3)
         Worker 0: actual time=1945.537..1945.537 rows=0 loops=1
         Worker 1: actual time=1946.631..1946.631 rows=0 loops=1
         ->  Parallel Seq Scan on public.child2_hash  (cost=0.00..73259.59 rows=139 width=88) (actual time=655.334..655.334 rows=0 loops=3)
               Output: child2_hash.id, child2_hash.child, child2_hash.hashval
               Filter: (child2_hash.hashval ~~ '%41376044135%'::text)
               Rows Removed by Filter: 1111155
               Worker 0: actual time=9.694..9.694 rows=0 loops=1
               Worker 1: actual time=1946.623..1946.623 rows=0 loops=1
         ->  Parallel Seq Scan on public.child3_hash  (cost=0.00..73248.88 rows=139 width=88) (actual time=968.696..968.696 rows=0 loops=2)
               Output: child3_hash.id, child3_hash.child, child3_hash.hashval
               Filter: (child3_hash.hashval ~~ '%41376044135%'::text)
               Rows Removed by Filter: 1666946
               Worker 0: actual time=1935.832..1935.832 rows=0 loops=1
         ->  Parallel Seq Scan on public.child1_hash  (cost=0.00..73228.19 rows=139 width=88) (actual time=2.242..1944.713 rows=1 loops=1)
               Output: child1_hash.id, child1_hash.child, child1_hash.hashval
               Filter: (child1_hash.hashval ~~ '%41376044135%'::text)
               Rows Removed by Filter: 3332641
 Planning Time: 0.471 ms
 Execution Time: 1961.897 ms
(24 rows)

Kết luận

Cùng với chức năng logical replication, chức năng Declarative Partitioning được đưa vào từ phiên bản PostgreSQL 10 được coi là một bước tiến đáng kể của PostgreSQL.
Chức năng Declarative Partitioning kết hợp với postgres_fdw có thể là nền tảng cho chức năng sharding của PostgreSQL sau này.
Phiên bản 11 khắc phục khá lớn các hạn chế của Declarative Partitioning trong phiên bản 10. Mặc dù vậy cũng cần chú ý các hạn chế còn tồn đọng để thiết kết xử lý sao cho đúng với hệ thống của bạn.  

Quản lý log trên PostgreSQL

Chào các bạn. Bài viết này mình xin giới thiệu thêm về một chức năng cơ bản mà rất cần thiết khi thiết kế sử dụng một cơ sở dữ liệu PostgreSQL cho người sử dụng. Như tiêu đề đã nêu, đó là quản lý log.
Log là một phần không thể thiếu trong việc giải quyết các vấn đề liên quan tới database như phát hiện lock wait, deadlock, tình trạng checkpoint, autovacuum, phát hiện slow query... Thiết kế sao cho log chứa những thông tin hữu ích để giải quyết những vấn đề xảy ra trong lúc hoạt động, và làm sao để việc xuất log không ảnh hưởng nhiều tới hệ thống là một phần không thể thiếu đối với một quản trị viên cơ sở dữ liệu.

Chức năng log của PostgreSQL

Log là chức năng có sẵn của PostgreSQL, ta có thể sử dụng mà không cần cài đặt thêm module nào cả. Chức năng log của PostgreSQL lưu trữ các thao tác, lỗi khi sử dụng, vận hành, ... dưới dạng text, cho phép người dùng có thể quan sát trực tiếp. PostgreSQL có thể thiết kế để xuất log tới syslog(linux) hay event log(windows), mặc định PostgreSQL xuất log bên dưới pg_log bên dưới thư mục cơ sở dữ liệu (nếu tham số logging_collector thiết lập là on). Để quản lý đơn giản hơn thường dữ liệu log được thiết lập để xuất bên dưới thư mục cơ sở dữ liệu. Bài viết này mình cũng đưa ra những ví dụ log từ pg_log bên dưới thư mục cơ sở dữ liệu.

Chú ý khi thiết kế log

Trạng thái xuất log mặc định

Giá trị khởi tạo của tham số logging_collector là off, tức là log messages không được lưu trữ. Nhưng nếu bạn tạo database cluster theo cách bên dưới đây thì giá trị mặc định đối với tham số logging_collector cho database cluster đó là on.

  • Database được tạo ra lúc cài đặt PostgreSQL bằng (EDB) Installer trên môi trường Windows.
  • Database được tạo ra bởi initdb được cài đặt từ rpm từ community.

Chú ý khác với initdb của rpm, database cluster được tạo ra bằng cách chạy trực tiếp lệnh initdb của EDB installer (ít nhất tại thời điểm hiện tại) lại có mặc định logging_collector = off.

Một số chú ý về log của PostgreSQL khi lưu trữ bên dưới thư mục dữ liệu

  • Mặc định log của PostgreSQL tăng không có giới hạn
    Mặc định các tham số log_filenamelog_truncate_on_rotation làm cho log không có cơ chế loại bỏ được log cũ nên dung lượng log sẽ tăng không ngừng theo thời gian. Ta phải thiết kế để tránh tình trạng trên và sao cho phù hợp với yêu cầu hệ thống.
  • Không thể giới hạn được dung lượng xuất log của PostgreSQL
    Như giải thích về tham số log_rotate_size ở bên dưới. Chúng ta không thể giới hạn được dung lượng xuất log của PostgreSQL. Bởi vậy nên cần tính toán thiết kế sao cho lượng log không xuất ra quá nhiều so với mong đợi.

Các tham số liên quan tới log của PostgreSQL

PostgreSQL có rất nhiều paramters liên quan tới log, nội dung giải thích bên dưới mình chỉ tập chung vào các tham số thường được sử dụng trong vận hành và lúc tuning (tinh chỉnh). Cụ thể các tham số đó vui lòng tham khảo ở Document của PostgreSQL.

Các tham số liên quan tới PostgreSQL được chia ra 3 nhóm chính. Mình sẽ đi vào giải thích các tham số trong từng nhóm.

Trong các tham số liên quan tới log, duy có tham số logging_collector khi thay đổi cần restart server(pg_ctl restart) để có hiệu lực. Các paramter khác có thể reload server(pg_ctl reload), hoặc một vài paramter có thể thiết lập trong từng session(bằng cách sử dụng câu lệnh SET).

Nơi xuất log

tên paramter chức năng chú thích
log_destination Tham số chỉ định nơi xuất log.

PostgreSQL có 3 phương pháp chỉ định nơi xuất log, stderr: bên dưới database cluster (pg_log or log) dưới dạng text, csvlog: như stderr nhưng xuất theo định dạng csv, syslog: xuất log ra log hệ thống(linux OS), eventlog: xuất log ra event log trên môi trường Windows. Mặc định giá trị của tham số này là 'stderr'. 

Ta có thể chỉ định nhiều nơi xuất log qua dấu phân cách ",". Ví dụ log_destination = 'stderr, eventlog' # xuất log dạng text vào $PGDATA/log và eventlog trên Windows.

Thực tế để quản lý log dễ dàng hơn tham số này thường được để mặc định.

logging_collector Tham số chỉ định cho phép lưu trữ log vào file hay không.

Mặc định cho là off khi tạo database cluster bằng lệnh initdb. Khi thay đổi giá trị, cần khởi động lại server để có hiệu lực

Tham số này chỉ có hiệu quả khi log_destination là csvlog hay stderr.

log_directory Tham số chỉ định nơi lưu log khi log_destination là stderr hoặc csvlog

Từ phiên bản PostgreSQL 10 mặc định cho tham số này chuyển từ pg_log sang log. Các thư mục này nằm bên dưới thư mục cơ sở dữ liệu.

log_filename Tham số chỉ định tên của file log

Giá trị chỉ định của tham số này giống như chuẩn Open Group's ftrtime. Bạn có thể chỉ định tên file log theo ngày(postgresql-%d.log: thiết lập này sẽ lưu số lượng log file bằng số ngày của tháng là 31), thứ trong tuần(postgresql-%a.log: thiết lập này sẽ lưu trữ số lượng log file bằng số lượng ngày trong tuần là 7),.. Mặc định giá trị cho tham số này là 'postgresql-%Y-%m-%d_%H%M%S.log' tức là tên log file sẽ chứa thời gian tới đơn vị giây. Đồng nghĩa với việc số lượng log file không kiểm soát được, ta nên chỉnh lại tham số này trước khi đưa vào vận hành.

Ví dụ: với thiết lập log_filename = 'postgresql-%a.log'. Trong vận hành ta sẽ có 7 log files(1 log file cho mỗi ngày trong tuần) như bên dưới.

$ ll $PGDATA/log/
total 16
-rw-------. 1 postgres postgres    0 May  4 00:00 postgresql-Fri.log
-rw-------. 1 postgres postgres    0 May  7 00:00 postgresql-Mon.log
-rw-------. 1 postgres postgres 1039 May  5 16:07 postgresql-Sat.log
-rw-------. 1 postgres postgres    0 May  6 00:00 postgresql-Sun.log
-rw-------. 1 postgres postgres  941 May  3 18:39 postgresql-Thu.log
-rw-------. 1 postgres postgres   74 May 11 23:55 postgresql-Tue.log
-rw-------. 1 postgres postgres  718 May 16 06:31 postgresql-Wed.log
log_file_mode Tham số chỉ định quyền tham chiếu tới log file Mặc định là 0600, nghĩa là chỉ có OS user sở hữu server (user dùng để khởi động PostgreSQL) là có thể tham chiếu tới log file.
log_rotation_age Tham số chỉ định rotate log file(ghi sang log file khác khi tới ngưỡng chỉ định) theo thời gian Mặc định là một ngày, tức là cứ sau 1 ngày log file mới sẽ được tạo ra theo định dạng chỉ định trong tham số log_filename.
log_rotation_size Tham số chỉ định rotate log file(ghi sang log file khác khi tới ngưỡng chỉ định) theo kích thước Mặc định là 10MB. Tức là cứ 10MB, sẽ có log file mới được tạo ra theo định dạng trong tham số log_filename. Lưu ý rằng log file mới tạo ra theo định dạng của log_filename, nên chỉ khi tên log file mới được tạo ra quá trình rotate mới xảy ra. Điều này dẫn đến ta không thể kiểm soát được dung lượng log xuất ra
log_truncate_on_rotation Tham số chỉ định có truncate log cũ khi rotation hay không

Mặc định tham số này là off. Tức là không truncate(xóa) log cũ khi rotation thực thi. Nên dung lượng file log sẽ lớn dần theo thời gian. Nếu không có cơ chế backup log cụ thể nào nên để tham số này là on.

Chú ý rằng thời điểm thực hiện rotation dựa vào log_filename(ví dụ khi log_rotation_age=1d, log_filename='postgresql-%d.log' thì rotation sẽ diễn ra vào lúc 0 giờ hằng ngày). Tại thời điểm 0 giờ này nếu PostgreSQL đang dừng hoạt động thì xử lý truncate sẽ không diễn ra khi khởi động PostgreSQL, khi đó PostgreSQL chỉ chèn thêm log messages vào log file hiện tại.

Thời điểm xuất log

tên paramter chức năng chú thích
client_min_mesages Tham số chỉ định mức độ mà log messages sẽ trả về cho phía client(khi chạy các câu lệnh SQL)

Mặc định cho tham số này là NOTICE. Tức là chỉ những messages có mức độ từ NOTICE trở lên(NOTICE, WARNING, ERROR, FATAL, PANIC) mới trả về cho client.

postgres=# set client_min_messages to log;
SET
postgres=# set log_min_duration_statement to 0;
LOG:  duration: 0.103 ms  statement: set log_min_duration_statement to 0;
SET
postgres=# select pg_sleep(1);
LOG:  duration: 1003.193 ms  statement: select pg_sleep(1);
 pg_sleep 
----------
 
(1 row)
log_min_messages Tham số chỉ định mức độ mà log messages sẽ xuất phía server

Mặc định cho tham số này là WARNING. Tức là chỉ những messages có mức độ từ WARNING trở lên(WARNING, ERROR, LOG, FATAL, PANIC) mới được xuất. Tham số này hữu ích khi điều tra vấn đề gì đó xảy ra trên server của bạn.

$ psql
psql (11devel)
Type "help" for help.

postgres=# set log_min_messages to debug5;
SET
postgres=# select count(*) from pg_class;
 count 
-------
   343
(1 row)

postgres=# \q
$ tail -2 $PGDATA/log/postgresql-Wed.log | grep DEBUG
2018-05-16 07:42:50.299 JST [22540] DEBUG:  shmem_exit(-1): 0 on_shmem_exit callbacks to make
2018-05-16 07:42:50.299 JST [22540] DEBUG:  proc_exit(-1): 0 callbacks to make
$ 
log_min_error_statement Tham số chỉ định khi nào sẽ xuất câu lệnh SQL liên quan tới log messages hiện tại

Mặc định cho tham số này là ERROR. Tức là đối với các messages có mức độ từ ERROR trở lên (ERROR, LOG, FATAL, PANIC) khi xuất ra sẽ kèm với câu lệnh SQL tương ứng

postgres=# show log_min_error_statement;
 log_min_error_statement 
-------------------------
 error
(1 row)

postgres=# select testerror;
ERROR:	column "testerror" does not exist
LINE 1: select testerror;
	       ^
postgres=# \q
$ tail -3 $PGDATA/log/postgresql-Wed.log | grep ERROR -A2
2018-05-16 07:45:51.324 JST [22591] ERROR:  column "testerror" does not exist at character 8
2018-05-16 07:45:51.324 JST [22591] STATEMENT:	select testerror;
$ 
log_min_duration_statement Tham số chỉ định sẽ xuất log cho những SQL có thời gian thực thi lớn hơn giá trị chỉ định(đơn vị là mili giây)

Mặc định cho tham số này là -1 tức là sẽ không xuất các câu lệnh SQL đã chạy. Tham số này rất hữu ích cho việc xác định slow query trong PostgreSQL. Ví dụ: nếu thiết lập giá trị là '10s', những SQL nào chạy quá 10s sẽ được xuất ra log

postgres=# set client_min_messages to log;
SET
postgres=# set log_min_duration_statement to 100;
LOG:  duration: 0.103 ms  statement: set log_min_duration_statement to 100;
SET
postgres=# select pg_sleep(1);
LOG:  duration: 1003.193 ms  statement: select pg_sleep(1);
 pg_sleep 
----------
 
(1 row)

Nội dung log

tên paramter chức năng chú thích
log_connections Tham số chỉ định log thông tin khi kết nối.

Mặc định tham số này là off, tức là ko log khi kết nối. Thực tế khi tham số này on thì mỗi lần kết nối dung lượng log cũng không xuất ra nhiều (2 dòng), ta nên để on để phân tích log dễ dàng hơn. Tham số này chỉ chỉ định được trước khi bắt đầu session.

$ psql -c "show log_connections"
 log_connections 
-----------------
 on
(1 row)

$ tail $PGDATA/log/postgresql-Wed.log | grep -A1 "connection received"
2018-05-16 07:51:12.137 JST [22714] LOG:  connection received: host=[local]
2018-05-16 07:51:12.138 JST [22714] LOG:  connection authorized: user=postgres database=postgres
log_disconnections Tham số chỉ định log thông tin khi dữ liệu ngừng kết nối

Mặc định tham số này là off. Giống như log_connections, tham số này cũng nên thiết lập on để phân tích log dễ dàng hơn.

$ psql -c "show log_disconnections"
 log_disconnections 
--------------------
 on
(1 row)

$ tail -1 $PGDATA/log/postgresql-Wed.log
2018-05-16 07:53:49.485 JST [22754] LOG:  disconnection: session time: 0:00:00.003 user=postgres database=postgres host=[local]
log_error_verbosity Tham số chỉ định lượng log chi tiết xuất ra cho mỗi messages Giá trị có thể thiết lập là, TERSE, DEFAULT, và VERBOSE. Ở thiết lập TERSE, những thông tin DETAIL, HINT, QUERY và CONTEXT không được xuất. VERBOSE ngoài việc xuất những thông tin này ra, vị trí dòng code, tên hàm, tên file source code cũng được hiện thị. Những hệ thống có workload nhỏ có thể thiết lập lên VERBOSE để phân tích log dễ dàng hơn
log_duration Tham số cho phép xuất thời gian đã thực thi của mỗi câu lệnh SQL

Mặc định tham số này là off và chỉ có super user mới thay đổi được

postgres=# set log_duration to on;
SET
postgres=# set client_min_messages to log;
LOG:  duration: 0.075 ms
SET
postgres=# select pg_sleep(1);
LOG:  duration: 1002.341 ms
 pg_sleep 
----------
 
(1 row)

postgres=# 
log_line_prefix Tham số chỉ định tiền tố cho mỗi log messages

Tham số này có thể chỉ định theo ký tự % cho các thông tin khác nhau, cụ thể bạn có thể xem tại đây. Từ phiên bản 10 mặc định cho tham số này là '%m [%p] ', tức là thông tin về thời gian bao gồm cả mili giây(%m) và ID của tiến trình thực hiện log(%p). Thông thường để phân tích log khi có sự cố, ta thường thêm các thông tin như %d: truy cập cơ sở dữ liệu nào, %h: truy cập từ IP address nào, %u: truy cập bằng user nào, %x: trong transaction ID nào.

[postgres@localhost ~]$ psql -c "show log_line_prefix"
		     log_line_prefix			 
---------------------------------------------------------
 [%m host:%h database:%d user:%u PID:%p TransactionID:%x] 
(1 row)

[postgres@localhost ~]$ tail -1 $PGDATA/log/postgresql-Wed.log
[2018-05-16 07:57:33.815 JST host:[local] database:postgres user:postgres PID:22817 TransactionID:0] LOG:  disconnection: session time: 0:00:00.003 user=postgres database=postgres host=[local]
[postgres@localhost ~]$ 
log_statement Tham số cho phép log các lệnh SQL thực thi theo từng chủng loại chỉ định

Giá trị cho phép là off(mặc định), ddl: các câu lệnh SQL liên quan tới định nghĩa (CREATE, ALTER, DROP), mod: các câu lệnh SQL liên quan tới thay đổi dữ liệu(INSERT, UPDATE, DELETE, TRUNCATE,...), all: tất cả các câu lệnh SQL. Lưu ý thiết lập all cho tham số này có ý nghĩa tương tự như thiết lập tham số log_min_duration_statement = 0, nhưng log_min_duration_statement xuất các câu lệnh SQL khi đã thực thi xong còn log_statement log khi câu lệnh vừa được chạy(có thể chưa hoặc kết thúc). Tùy vào yêu cầu về mornitoring hệ thống, ta có thể kết hợp tham số này với log_duration hoặc chỉ sử dụng log_min_duration_statement để theo dõi các câu lệnh SQL thực thi

postgres=# set log_statement to 'ddl';
SET
postgres=# set client_min_messages to log;
SET
postgres=# create table testtbl(id integer);
LOG:  statement: create table testtbl(id integer);
CREATE TABLE
postgres=# insert into testtbl values(1);
INSERT 0 1
postgres=# drop table testtbl ;
LOG:  statement: drop table testtbl ;
DROP TABLE
postgres=#
log_temp_files Cho phép log khi có file tạm xuất ra tùy thuộc vào dung lượng file chỉ định

Đối với xử lý như hashjoin hay sort, PostgreSQL sử dụng bộ nhớ chỉ định trong tham số work_mem(cho mỗi process) để chứa dữ liệu tạm thời. Khi dữ liệu tạm thời vượt quá work_mem, PostgreSQL sẽ thực hiện sort/hashjoin trên đĩa cứng. Khi dung lượng file tạm sử dụng cho sort/hashjoin trên đĩa cứng lớn hơn log_temp_files, logger process sẽ xuất thông tin đó ra log file.

postgres=# set log_temp_files to 0;
SET
postgres=# set work_mem to 64;
SET
postgres=# show work_mem ;
 work_mem 
----------
 64kB
(1 row)

postgres=# explain analyze select * from pg_class order by relname desc;
						  QUERY PLAN					    
	   
----------------------------------------------------------------------------------------------------
-----------
 Sort  (cost=75.31..76.17 rows=342 width=262) (actual time=0.636..0.720 rows=343 loops=1)
   Sort Key: relname DESC
   Sort Method: external merge	Disk: 64kB
   ->  Seq Scan on pg_class  (cost=0.00..15.42 rows=342 width=262) (actual time=0.010..0.067 rows=34
3 loops=1)
 Planning Time: 0.862 ms
 Execution Time: 1.025 ms
(6 rows)

postgres=# \! tail -2 $PGDATA/log/postgresql-Wed.log
2018-05-16 08:10:36.530 JST [23134] LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp23134.0", size 65536
2018-05-16 08:10:36.530 JST [23134] STATEMENT:	explain analyze select * from pg_class order by relname desc;
postgres=# 
log_checkpoints Cho phép log thông tin CHECKPOINT khi chức năng này thực thi Mặc định cho tham số này là off. Tham số này cần thiết khi tinh chỉnh hệ thống liên quan tới bộ nhớ đệm và tần xuất lưu lượng mỗi CHECKPOINT. Bạn có thể tham khảm thêm ở bài viết checkpoint
log_lock_waits Tham số chỉ định xuất log liên quan khi lock wait cho session đó vượt quá thời gian chỉ định trong deadlock_timeout Mặc định cho tham số này là off. Nếu on PostgreSQL sẽ xuất log liên quan cho phiên đó khi quá thời gian deadlock_timeout(mặc định 1 giây) mà chưa thực thi được lock. Trong các hệ thống có work load (bạn có thể hiểu là tần xuất thực thi SQL) lớn, tham số này rất hữu ích cho việc tìm hiểu nguyên nhân slow query do lock wait hoặc phát hiện deadlock. Bạn có thể tham khảo thêm ở bài viết về lock

Cách cấu hình setting files trên PostgreSQL

Lời mở đầu

Chào các bạn, chắc hẳn lúc mới đầu sử dụng PostgreSQL bạn đã có lúc tự hỏi phải thiết lập cấu hình từ file cấu hình nào, PostgreSQL có những file cấu hình gì. Làm như thế nào để cấu hình,.. Bài viết này sẽ cố gắng đưa ra cách nhìn tổng quan về setting files, cách thiết lập, và một số point khi thiết lập.

PostgreSQL setting files

Tới phiên bản PostgreSQL 10, PostgreSQL có những file settings như bên dưới.

PostgreSQL 10 có nhiều thay đổi về file name, parameter name,... But may mắn là tên file setting thì không có thay đổi.


DangnoMacBook-Pro:~ bocap$ ll $PGDATA | grep conf
-rw-------   1 bocap  wheel   4469 Nov  1 20:42 pg_hba.conf
-rw-------   1 bocap  wheel   1636 Sep 10 23:19 pg_ident.conf
-rw-------   1 bocap  wheel     88 Sep 10 23:19 postgresql.auto.conf
-rw-------   1 bocap  wheel  22321 Nov  1 20:45 postgresql.conf
DangnoMacBook-Pro:~ bocap$ 

File Setting Mục đích sử dụng Cách phản ảnh
pg_hba.conf File cấu hình xác thực cho PostgreSQL server. Chỉ những host được cấu hình cho phép từ file này mới được phép xác thực tới server. File này cũng cấu hình phương pháp xác thực tới server. Ví dụ: trust(không xác thực password), password(plain text password), md5(xác thực bằng password được hash md5), ident(sử dụng xác thực thông qua OS user), ... reload
pg_ident.conf File cấu hình mapping cho OS user với PostgreSQL trong trong phương pháp xác thực reload
postgresql.auto.conf Được thêm vào PostgreSQL 9.4, file này có nội dung được ghi vào khi thực hiện lệnh ALTER SYSTEM để thay đổi parameters. Khuyến cáo là không nên chỉnh sửa trực tiếp file này. reload, restart
postgresql.conf File cấu hình chính của PostgreSQL Server. reload, restart
recovery.conf sử dụng khi restore dữ liệu từ basebackup hoặc dùng trong cấu hình standby restart

Như trên có 2 cách phản ảnh parameters sau khi đã config(thay đổi giá trị paramter).

  • Reload là cách làm cho các process đọc lại file config mà không làm ảnh hưởng tới Application.

DangnoMacBook-Pro:~ bocap$ pg_ctl reload
server signaled
LOG:  received SIGHUP, reloading configuration files
LOG:  parameter "archive_command" removed from configuration file, reset to default
DangnoMacBook-Pro:~ bocap$ 

  • Restart là hình thức phản ảnh parameters bằng cách khởi động lại server. Cách này làm toàn bộ connections bị disconnect, nên phải khởi động lại Application. Nên nếu không cần thiết thì không dùng cách này.

DangnoMacBook-Pro:~ bocap$ pg_ctl restart 
waiting for server to shut down....LOG:  received fast shutdown request
LOG:  aborting any active transactions
LOG:  autovacuum launcher shutting down
LOG:  shutting down
LOG:  database system is shut down
 done
server stopped
server starting
DangnoMacBook-Pro:~ bocap$ 


pg_hba.conf

File cấu hình này có phản ảnh sau khi config bằng cách reload mà không cần restart server. Đương nhiên là restart thì các parameters này cũng được phản ảnh.


DangnoMacBook-Pro:~ bocap$ grep "^local " $PGDATA/pg_hba.conf
local   all             all                                     md5
DangnoMacBook-Pro:~ bocap$ pg_ctl reload
server signaled
LOG:  received SIGHUP, reloading configuration files
DangnoMacBook-Pro:~ bocap$ psql -c "select 1"
 ?column? 
----------
        1
(1 row)

DangnoMacBook-Pro:~ bocap$ 
DangnoMacBook-Pro:~ bocap$ grep "^local " $PGDATA/pg_hba.conf
local   all             all                                     reject
DangnoMacBook-Pro:~ bocap$ pg_ctl reload
server signaled
LOG:  received SIGHUP, reloading configuration files
DangnoMacBook-Pro:~ bocap$ psql -c "select 1"
FATAL:  pg_hba.conf rejects connection for host "[local]", user "postgres", database "postgres"
psql: FATAL:  pg_hba.conf rejects connection for host "[local]", user "postgres", database "postgres"
DangnoMacBook-Pro:~ bocap$ 

pg_ident.conf

Cũng như pg_hba.conf, nội dung file này cũng được phản ảnh sau khi reload server.

postgresql.auto.conf

Nội dung file này được phản ảnh sau khi reload server, nhưng giống như postgresql.conf có một số paramters chỉ được phản ảnh sau khi restart server. Như ví dụ bên dưới, mình thay đổi 2 parameters log_disconnections và max_connections, but chỉ có log_disconnections là thay đổi được. Còn parameter max_connections thì cần restart server mới thay đổi được.


DangnoMacBook-Pro:~ bocap$ psql
psql (9.6.5)
Type "help" for help.

postgres=#  alter system reset all;
ALTER SYSTEM
postgres=# \! cat $PGDATA/postgresql.auto.conf
# Do not edit this file manually!
# It will be overwritten by ALTER SYSTEM command.
postgres=# show max_connections ;
 max_connections 
-----------------
 20
(1 row)

postgres=# show log_disconnections ;
 log_disconnections 
--------------------
 off
(1 row)

postgres=# alter system set max_connections to 15;
ALTER SYSTEM
postgres=# alter system set log_disconnections to on;
ALTER SYSTEM
postgres=# show log_disconnections ;
 log_disconnections 
--------------------
 off
(1 row)

postgres=# show max_connections ;
 max_connections 
-----------------
 20
(1 row)

postgres=# \q


DangnoMacBook-Pro:~ bocap$ pg_ctl reload
server signaled
LOG:  received SIGHUP, reloading configuration files
LOG:  parameter "max_connections" cannot be changed without restarting the server
LOG:  parameter "log_disconnections" changed to "on"
LOG:  configuration file "/usr/local/pgsql/pg9605/data/postgresql.auto.conf" contains errors; unaffected changes were applied
DangnoMacBook-Pro:~ bocap$ psql
psql (9.6.5)
Type "help" for help.

postgres=# show log_disconnections ;
 log_disconnections 
--------------------
 on
(1 row)

postgres=# show max_connections ;
 max_connections 
-----------------
 20
(1 row)

postgres=# \! cat $PGDATA/postgresql.auto.conf
# Do not edit this file manually!
# It will be overwritten by ALTER SYSTEM command.
max_connections = '15'
log_disconnections = 'on'
postgres=# \q
LOG:  disconnection: session time: 0:00:33.338 user=postgres database=postgres host=[local]
DangnoMacBook-Pro:~ bocap$ 

Parameter max_connections được thay đổi sau khi server restart.


DangnoMacBook-Pro:~ bocap$ pg_ctl restart
waiting for server to shut down....LOG:  received fast shutdown request
LOG:  aborting any active transactions
LOG:  autovacuum launcher shutting down
LOG:  shutting down
LOG:  database system is shut down
 done
server stopped
server starting
DangnoMacBook-Pro:~ bocap$ LOG:  database system was shut down at 2017-11-04 22:53:11 JST
LOG:  MultiXact member wraparound protections are now enabled
LOG:  autovacuum launcher started
LOG:  database system is ready to accept connections

DangnoMacBook-Pro:~ bocap$ psql
psql (9.6.5)
Type "help" for help.

postgres=# show max_connections ;
 max_connections 
-----------------
 15
(1 row)

postgres=# 

postgresql.conf

Giống như postgresql.auto.conf, cách phản của postgresql.conf cũng như vậy.
Ở postgresql.conf và postgresql.auto.conf các parameters dưới đây cần restart server để phản ánh sau khi config.


postgres=# select name,context from pg_settings where context = 'postmaster';
                name                 |  context   
-------------------------------------+------------
 allow_system_table_mods             | postmaster
 archive_mode                        | postmaster
 autovacuum_freeze_max_age           | postmaster
 autovacuum_max_workers              | postmaster
 autovacuum_multixact_freeze_max_age | postmaster
 bonjour                             | postmaster
 bonjour_name                        | postmaster
 cluster_name                        | postmaster
 config_file                         | postmaster
 data_directory                      | postmaster
 dynamic_shared_memory_type          | postmaster
 event_source                        | postmaster
 external_pid_file                   | postmaster
 hba_file                            | postmaster
 hot_standby                         | postmaster
 huge_pages                          | postmaster
 ident_file                          | postmaster
 listen_addresses                    | postmaster
 logging_collector                   | postmaster
 max_connections                     | postmaster
 max_files_per_process               | postmaster
 max_locks_per_transaction           | postmaster
 max_pred_locks_per_transaction      | postmaster
 max_prepared_transactions           | postmaster
 max_replication_slots               | postmaster
 max_wal_senders                     | postmaster
 max_worker_processes                | postmaster
 old_snapshot_threshold              | postmaster
 port                                | postmaster
 shared_buffers                      | postmaster
 shared_preload_libraries            | postmaster
 ssl                                 | postmaster
 ssl_ca_file                         | postmaster
 ssl_cert_file                       | postmaster
 ssl_ciphers                         | postmaster
 ssl_crl_file                        | postmaster
 ssl_ecdh_curve                      | postmaster
 ssl_key_file                        | postmaster
 ssl_prefer_server_ciphers           | postmaster
 superuser_reserved_connections      | postmaster
 track_activity_query_size           | postmaster
 track_commit_timestamp              | postmaster
 unix_socket_directories             | postmaster
 unix_socket_group                   | postmaster
 unix_socket_permissions             | postmaster
 wal_buffers                         | postmaster
 wal_level                           | postmaster
 wal_log_hints                       | postmaster
(48 rows)

recovery.conf

Khi server start nếu thư mục dữ liệu tồn tại file recovery.conf PostgreSQL sẽ đọc file này và thực hiện quá trình recovery như trong file recovery.conf chỉ định.
Ví dụ bên dưới mình tạo một standby và thiết lập recovery.conf để khi standby server khi khởi động trước hết sẽ restore archive log từ "/mnt/archivedir/".


DangnoMacBook-Pro:~ bocap$ pg_basebackup -h localhost -R -x -D $PGDATA.sby
LOG:  disconnection: session time: 0:00:01.258 user=postgres database= host=::1 port=63760
DangnoMacBook-Pro:~ bocap$ echo port=9606 >> $PGDATA.sby/postgresql.conf
DangnoMacBook-Pro:~ bocap$ cat >> $PGDATA.sby/recovery.conf  restore_command = 'cp /mnt/archivedir/%f "%p"'
> EOF
DangnoMacBook-Pro:~ bocap$ pg_ctl start -D $PGDATA.sby
server starting
DangnoMacBook-Pro:~ bocap$ LOG:  database system was interrupted; last known up at 2017-11-04 23:10:05 JST
LOG:  entering standby mode
LOG:  restored log file "00000001000000040000007F" from archive
LOG:  redo starts at 4/7F000060
LOG:  consistent recovery state reached at 4/7F000130
cp: /mnt/archivedir/000000010000000400000080: No such file or directory
LOG:  started streaming WAL from primary at 4/80000000 on timeline 1

DangnoMacBook-Pro:~ bocap$

Cấu trúc thư mục dữ liệu PostgreSQL

Thư mục dữ liệu PostgreSQL

Để chạy một câu lệnh SQL, tạo bảng dữ liệu, hay lưu trữ dữ liệu PostgreSQL cũng như các RDBMS khác chúng ta cần một thư mục chứa dữ liệu, PostgreSQL gọi đó là database cluster. Sau khi cài đặt PostgreSQL, database cluster được tạo ra bởi lệnh initdb. Nếu bạn cài đặt qua installer trên Windows, database cluster sẽ tự động được tạo ra trong quá trình cài đặt. Sau khi tạo một database cluster, ta có thể khởi động database cluster này lên và thực hiện các câu truy vấn tuỳ ý.

Các database cluster phân biệt bởi parameter port (postgresql.conf). Ta có thể cài đặt nhiều database cluster trên một hệ điều hành bằng cách đặt port khác nhau cho mỗi database cluster.

Tạo thư mục dữ liệu

Để tạo một thư mục dữ liệu PostgreSQL (database cluster) ta sử dụng câu lệnh initdb.


DangnoMacBook-Pro:postgresql-9.6.5 bocap$ initdb --no-locale -E utf8 -D /usr/local/pgsql/pg9600/data
The files belonging to this database system will be owned by user "bocap".
This user must also own the server process.

The database cluster will be initialized with locale "C".
The default text search configuration will be set to "english".

Data page checksums are disabled.

creating directory /usr/local/pgsql/pg9600/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    pg_ctl -D /usr/local/pgsql/pg9600/data -l logfile start

DangnoMacBook-Pro:postgresql-9.6.5 bocap$ 

Lệnh initdb nhiều options bạn có thể kiểm tra bằng option --help. Ví dụ trên mình sử dụng các options thông dụng như bên dưới.

  • --no-locale: Không sử dụng locale, hay locale C. Tạo database cluster với option này, khi sắp xếp dữ liệu (ORDER BY), PostgreSQL sẽ không so sánh qua ký tự alphabet mà so sánh trực tiếp qua character code, tăng performance.
  • -E hay --encoding: Chỉ định encoding cho database cluster.
  • -D: thư mục cơ sở dữ liệu.

Khởi động server từ thư mục dữ liệu đã tạo.Ví dụ dưới mình sử dụng port 9605 cho database cluster này.


DangnoMacBook-Pro:postgresql-9.6.5 bocap$ echo port=9605 >> /usr/local/pgsql/pg9600/data/postgresql.conf
DangnoMacBook-Pro:postgresql-9.6.5 bocap$ pg_ctl start
server starting
DangnoMacBook-Pro:postgresql-9.6.5 bocap$ LOG:  database system was shut down at 2017-09-10 23:19:54 JST
LOG:  MultiXact member wraparound protections are now enabled
LOG:  autovacuum launcher started
LOG:  database system is ready to accept connections

Kiểm tra kết nối. Nếu không chỉ định User khi tạo database cluster (tùy chọn -U cho initdb). Mặc định User được tạo ra cho database cluster  là User của OS chạy câu lệnh initdb, nên ví dụ dưới mình tạo lại user postgres cho database cluster (mình để mặc định biến môi trường PGUSER là 'postgres' nên có lỗi User không tồn tại khi truy nhập).


DangnoMacBook-Pro:postgresql-9.6.5 bocap$ psql
FATAL:  role "postgres" does not exist
psql: FATAL:  role "postgres" does not exist
DangnoMacBook-Pro:postgresql-9.6.5 bocap$ psql -U bocap -c "create user postgres password 'postgres'"
CREATE ROLE
DangnoMacBook-Pro:postgresql-9.6.5 bocap$ psql
psql (9.6.5)
Type "help" for help.

postgres=> \q
DangnoMacBook-Pro:postgresql-9.6.5 bocap$


Cấu trúc thư mục PostgreSQL

Sau khi khởi động PostgreSQL 1 database cluster sẽ có cấu trúc như bên dưới.

Phiên bản PostgreSQL-10 sắp tới sẽ hơi khác ví dụ thư mục log pg_log (khi thiết lập lưu trữ log logging_colector = on) sẽ trở thành log, thư mục transaction log pg_xlog sẽ trở thành pg_wal, etc.


DangnoMacBook-Pro:postgresql-9.6.5 bocap$ ll $PGDATA
total 104
-rw-------   1 bocap  wheel      4 Sep 10 23:19 PG_VERSION
drwx------   5 bocap  wheel    170 Sep 10 23:19 base
drwx------  55 bocap  wheel   1870 Sep 10 23:31 global
drwx------   3 bocap  wheel    102 Sep 10 23:19 pg_clog
drwx------   2 bocap  wheel     68 Sep 10 23:19 pg_commit_ts
drwx------   2 bocap  wheel     68 Sep 10 23:19 pg_dynshmem
-rw-------   1 bocap  wheel   4477 Sep 10 23:19 pg_hba.conf
-rw-------   1 bocap  wheel   1636 Sep 10 23:19 pg_ident.conf
drwx------   4 bocap  wheel    136 Sep 10 23:19 pg_logical
drwx------   4 bocap  wheel    136 Sep 10 23:19 pg_multixact
drwx------   3 bocap  wheel    102 Sep 10 23:31 pg_notify
drwx------   2 bocap  wheel     68 Sep 10 23:19 pg_replslot
drwx------   2 bocap  wheel     68 Sep 10 23:19 pg_serial
drwx------   2 bocap  wheel     68 Sep 10 23:19 pg_snapshots
drwx------   2 bocap  wheel     68 Sep 10 23:31 pg_stat
drwx------   4 bocap  wheel    136 Sep 10 23:31 pg_stat_tmp
drwx------   3 bocap  wheel    102 Sep 10 23:19 pg_subtrans
drwx------   2 bocap  wheel     68 Sep 10 23:19 pg_tblspc
drwx------   2 bocap  wheel     68 Sep 10 23:19 pg_twophase
drwx------   4 bocap  wheel    136 Sep 10 23:19 pg_xlog
-rw-------   1 bocap  wheel     88 Sep 10 23:19 postgresql.auto.conf
-rw-------   1 bocap  wheel  22267 Sep 10 23:20 postgresql.conf
-rw-------   1 bocap  wheel     37 Sep 10 23:31 postmaster.opts
-rw-------   1 bocap  wheel     86 Sep 10 23:31 postmaster.pid
DangnoMacBook-Pro:postgresql-9.6.5 bocap$ 

Nội dung các files trong 1 thư mục dữ liệu PostgreSQL (PGDATA)

Folder/files Nội dung
PG_VERSION

File chứa nội dung phiên bản PostgreSQL hiện tại
ví dụ:


DangnoMacBook-Pro:postgresql-9.6.5 bocap$ cat $PGDATA/PG_VERSION
9.6

base Thư mục con chứa dữ liệu của các database trong database cluster. Trong thư mục này chứa các thư mục con nữa cho mỗi database. Tên thư mục đặt theo oid của database tương ứng.

ví dụ:


DangnoMacBook-Pro:postgresql-9.6.5 bocap$ ll $PGDATA/base
total 0
drwx------  270 bocap  wheel  9180 Sep 10 23:19 1
drwx------  270 bocap  wheel  9180 Sep 10 23:19 12668
drwx------  271 bocap  wheel  9214 Sep 10 23:32 12669
DangnoMacBook-Pro:postgresql-9.6.5 bocap$ psql
psql (9.6.5)
Type "help" for help.

postgres=>; select oid, datname from pg_database;
  oid  |  datname  
-------+-----------
 12669 | postgres
     1 | template1
 12668 | template0
(3 rows)

postgres=>; 

global Thư mục con chứa các bảng sử dụng nội bộ trong PostgreSQL (system catalog). Ví dụ như catalog chứa thông tin về database pg_database.
pg_commit_ts Thư mục con chứa thông tin về trạng thái commit của dữ liệu timestamp.
pg_clog Thư mục con chứa thông tin về trạng thái commit của transaction trên database cluster hiện tại. Mỗi bit dữ liệu chứa thông tin trạng thái cho một transaction. offset của file trong thư mục này tương ứng với transaction ID, vì vậy PostgreSQL có thể xem thông tin trạng thái transaction thông qua offset đó.
pg_dynshmem Thư mục con chứa các file sử dụng dynamic shared memory.
pg_logical Thư mục con chứa trạng thái dữ liệu sử dụng trong chức năng logical decoding (chức năng decoding dữ liệu từ WAL).
pg_multixact Thư mục con chứa dữ liệu trạng thái multitransaction (sử dụng cho locks mức độ dòng dữ liệu).
pg_notify Thư mục con chứa dữ liệu về chức năng LISTEN/NOTIFY.
pg_replslot Thư mục con chứa dữ liệu về replication slot
pg_serial Thư mục con chứa thông tin về các transaction commited ở mức độ phân li serializable.
pg_snapshots Thư mục con chứa thông tin về các snapshots đã xuất.
pg_stat Thư mục con chứa các files thông tin thống kê về PostgreSQL đang được sử dụng hiện tại.
pg_stat_tmp Thư mục con chứa các files thông tin thống kê về PostgreSQL tạm thời, chưa được đưa vào sử dụng.
pg_subtrans Thư mục con chứa dữ liệu về các subtransaction (khi sử dụng SAVEPOINT).
pg_tblspc Thư mục con chứa thông tin symbolic links tới các tablespaces. khi tạo 1 TABLESPACE để chứa dữ liệu bên ngoài database cluster, PostgreSQL sẽ tạo một symbolic links tới thư mục tạo từ TABLESPACE trong thư mục này.
pg_twophase Thư mục con chứa các tập tin trạng thái cho các prepared transactions.
pg_xlog Thư mục con chứa thông tin về WAL files. Phiên bản PostgreSQL 10, thư mục này chuyển thành pg_wal.
postgresql.auto.conf File chứa thông tin về các cấu hình tham số thiết lập bởi lệnh ALTER SYSTEM.
postmaster.opts A file recording the command-line options the server was last started with. File này chứa thông tin về các tuỳ chọn lần cuối của lệnh khởi động PostgreSQL.
ví dụ: 

DangnoMacBook-Pro:postgresql-9.6.5 bocap$ cat /usr/local/pgsql/pg9600/data/postmaster.opts 
/usr/local/pgsql/pg9600/bin/postgres

postmaster.pid File này tạo ra khi khởi động PostgreSQL và mất đi khi shutdown PostgreSQL. File chứa thông tin về PID của postmaster process, đường dẫn thư mục dữ liệu, thời gian khởi động, số hiệu port, đường dẫn Unix-domain socket (là trống trên môi trường Windows), giá trị hiệu lực đầu tiên chỉ định trong tham số listen_address và segment ID shared memory (tạo lúc khởi động PostgreSQL).

Cài đặt PostgreSQL

Cài đặt PostgreSQL trên môi trường Linux

Cài đặt PostgreSQL trên môi trường linux thông thường có 2 cách. Build từ source hoặc cài đặt qua packages(rpm) có sẵn từ community. Binary từ 2 cách cài đặt này có một vài điểm nhỏ khác nhau trong file setting sau khi tạo data cluster. Ví dụ như logging_collector(xuất log qua file) mặc định on trên rpm và off khi build. Cài đặt qua source thì dễ tùy chỉnh các options bằng cách configure -> build lại.

Cài đặt qua source

  1. Download source
    Tất cả các phiên bản của PostgreSQL có thể download từ trang chủ. Chọn version bạn muốn dùng cho hệ thống của bạn. Khuyến cáo bạn nên chọn rivision mới nhất vì các chỉnh sửa giữa các revision hầu hết chỉ là bug fix.

  2. Cài đặt
    Sau khi giải nén bạn chạy lệnh ./configure với các options tùy thích. Bạn có thể xem ý nghĩa các options qua lệnh ./configure --help. Tiếp đó bạn dùng lệnh make và make install để cài đặt. Chú ý user chạy lệnh make install phải có quyền write thư mục bạn muốn cài đặt (option --prefix).

    
    [postgres@localhost src]$ ls postgresql-9.6.3.tar.gz
    postgresql-9.6.3.tar.gz
    [postgres@localhost src]$ tar xfz postgresql-9.6.3.tar.gz
    [postgres@localhost src]$ cd postgresql-9.6.3/
    [postgres@localhost postgresql-9.6.3]$ sudo mkdir -p /usr/local/pgsql/pg9603
    [sudo] password for postgres:
    [postgres@localhost postgresql-9.6.3]$ sudo chown postgres:postgres /usr/local/pgsql/pg9603
    [postgres@localhost postgresql-9.6.3]$ ./configure --prefix=/usr/local/pgsql/pg9603 --enable-debug \
     > /dev/null
    configure: WARNING:
    *** Without Bison you will not be able to build PostgreSQL from Git nor
    *** change any of the parser definition files. You can obtain Bison from
    *** a GNU mirror site. (If you are using the official distribution of
    *** PostgreSQL then you do not need to worry about this, because the Bison
    *** output is pre-generated.)
    configure: WARNING:
    *** Without Flex you will not be able to build PostgreSQL from Git nor
    *** change any of the scanner definition files. You can obtain Flex from
    *** a GNU mirror site. (If you are using the official distribution of
    *** PostgreSQL then you do not need to worry about this because the Flex
    *** output is pre-generated.)
    [postgres@localhost postgresql-9.6.3]$ make -j 4 > /dev/null
    [postgres@localhost postgresql-9.6.3]$ make install > /dev/null
    [postgres@localhost postgresql-9.6.3]$ ll /usr/local/pgsql/pg9603/
    total 16
    drwxrwxr-x. 2 postgres postgres 4096 Apr 12 23:05 bin
    drwxrwxr-x. 6 postgres postgres 4096 Apr 12 23:05 include
    drwxrwxr-x. 4 postgres postgres 4096 Apr 12 23:05 lib
    drwxrwxr-x. 6 postgres postgres 4096 Apr 12 23:05 share
    [postgres@localhost postgresql-9.6.3]$
    
    

    Tùy chỉnh configure đã sử dụng:

    Tùy chọn ý nghĩa
    --prefix đường dẫn thư mục cài đặt
    --enable-debug cho phép debug

    Lưu ý:

  • PostgreSQL không cho phép khởi động bằng user root, bạn nên cài đặt bằng user thường.

  • Nếu môi trường thiếu packages readline-devel và zlib-devel, lúc chạy ./configure sẽ có lỗi. Bạn nên cài 2 packages và configure lại.

  • Manual của PostgreSQL viết là sử dụng gmake thay vì make, nhưng môi trường Linux gmake được link tới make.

    
    $ ll /usr/bin/gmake
    lrwxrwxrwx. 1 root root 4 Nov 20 09:41 /usr/bin/gmake -> make
    
    
  1. Tạo database cluster
    Cài đặt xong PostgreSQL bạn có thể tạo database cluster (nơi chứa dữ liệu cho PostgreSQL) bằng lệnh initdb.

    
     [postgres@localhost postgresql-9.6.3]$ /usr/local/pgsql/pg9603/bin/initdb -D /usr/local/pgsql/pg9603/data \
     --no-locale -E utf8
     The files belonging to this database system will be owned by user "postgres".
     This user must also own the server process.
     The database cluster will be initialized with locale "C".
     The default text search configuration will be set to "english".
     Data page checksums are disabled.
     creating directory /usr/local/pgsql/pg9603/data ... ok
     creating subdirectories ... ok
     selecting default max_connections ... 100
     selecting default shared_buffers ... 128MB
     selecting dynamic shared memory implementation ... posix
     creating configuration files ... ok
     running bootstrap script ... ok
     performing post-bootstrap initialization ... ok
     syncing data to disk ... ok
     WARNING: enabling "trust" authentication for local connections
     You can change this by editing pg_hba.conf or using the option -A, or
     --auth-local and --auth-host, the next time you run initdb.
     Success. You can now start the database server using:
     /usr/local/pgsql/pg9603/bin/pg_ctl -D /usr/local/pgsql/pg9603/data -l logfile start
     [postgres@localhost postgresql-9.6.3]$ ll /usr/local/pgsql/pg9603/data
     total 48
     drwx------. 5 postgres postgres 38 Apr 12 23:43 base
     drwx------. 2 postgres postgres 4096 Apr 12 23:43 global
     drwx------. 2 postgres postgres 17 Apr 12 23:43 pg_clog
     drwx------. 2 postgres postgres 6 Apr 12 23:43 pg_commit_ts
     drwx------. 2 postgres postgres 6 Apr 12 23:43 pg_dynshmem
     -rw-------. 1 postgres postgres 4468 Apr 12 23:43 pg_hba.conf
     -rw-------. 1 postgres postgres 1636 Apr 12 23:43 pg_ident.conf
     drwx------. 4 postgres postgres 37 Apr 12 23:43 pg_logical
     drwx------. 4 postgres postgres 34 Apr 12 23:43 pg_multixact
     drwx------. 2 postgres postgres 17 Apr 12 23:43 pg_notify
     drwx------. 2 postgres postgres 6 Apr 12 23:43 pg_replslot
     drwx------. 2 postgres postgres 6 Apr 12 23:43 pg_serial
     drwx------. 2 postgres postgres 6 Apr 12 23:43 pg_snapshots
     drwx------. 2 postgres postgres 6 Apr 12 23:43 pg_stat
     drwx------. 2 postgres postgres 6 Apr 12 23:43 pg_stat_tmp
     drwx------. 2 postgres postgres 17 Apr 12 23:43 pg_subtrans
     drwx------. 2 postgres postgres 6 Apr 12 23:43 pg_tblspc
     drwx------. 2 postgres postgres 6 Apr 12 23:43 pg_twophase
     -rw-------. 1 postgres postgres 4 Apr 12 23:43 PG_VERSION
     drwx------. 3 postgres postgres 58 Apr 12 23:43 pg_xlog
     -rw-------. 1 postgres postgres 88 Apr 12 23:43 postgresql.auto.conf
     -rw-------. 1 postgres postgres 22204 Apr 12 23:43 postgresql.conf
     [postgres@localhost postgresql-9.6.3]$
    
    

    Tùy chỉnh initdb đã sử dụng:

    Tùy chọn ý nghĩa
    -D đường dẫn thư mục database cluster
    --no-locale sử dụng locale C cho database cluster
    -E utf8 sử dụng server encoding thông dụng utf8

Cài đặt qua packages(rpm)

  1. Cài đặt từ yum reporitory
    Bạn có thể download reporitory RPMs tương ứng ở đây, sau khi cài đặt dùng lệnh yum để cài đặt packages cần thiết. Ở ví dụ bên dưới, mình đã install 4 packages thông dụng của PostgreSQL. Sau khi cài đặt bạn có thể tạo database cluster bằng lệnh initdb.

    
     [root@localhost src]# wget https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg-redhat96-9.6-3.noarch.rpm
     --2017-05-21 22:26:49-- https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg-redhat96-9.6-3.noarch.rpm
     Resolving download.postgresql.org (download.postgresql.org)... 174.143.35.246, 204.145.124.244, 217.196.149.55, ...
     Connecting to download.postgresql.org (download.postgresql.org)|174.143.35.246|:443... connected.
     HTTP request sent, awaiting response... 200 OK
     Length: 4816 (4.7K) [application/x-redhat-package-manager]
     Saving to: 'pgdg-redhat96-9.6-3.noarch.rpm'
     100%[===================================================================================================================================================================================================>] 4,816 --.-K/s in 0.005s
     2017-05-21 22:26:50 (902 KB/s) - 'pgdg-redhat96-9.6-3.noarch.rpm'saved [4816/4816]
     [root@localhost src]# rpm -ivh pgdg-redhat96-9.6-3.noarch.rpm
     Preparing... ################################# [100%]
     Updating / installing...
     1:pgdg-redhat96-9.6-3 ################################# [100%]
     [root@localhost src]# yum search postgresql96
     Loaded plugins: fastestmirror, langpacks
     pgdg96 | 4.1 kB 00:00:00
     (1/2): pgdg96/7/x86_64/group_gz | 249 B 00:00:01
     (2/2): pgdg96/7/x86_64/primary_db | 137 kB 00:00:01
     Loading mirror speeds from cached hostfile
     * base: ftp.riken.jp
     * extras: ftp.riken.jp
     * updates: ftp.riken.jp
     ========================================================================================================= N/S matched: postgresql96 =========================================================================================================
     postgresql96-debuginfo.x86_64 : Debug information for package postgresql96
     postgresql96-tcl-debuginfo.x86_64 : Debug information for package postgresql96-tcl
     postgresql96.x86_64 : PostgreSQL client programs and libraries
     postgresql96-contrib.x86_64 : Contributed source and binaries distributed with PostgreSQL
     postgresql96-devel.x86_64 : PostgreSQL development header files and libraries
     postgresql96-docs.x86_64 : Extra documentation for PostgreSQL
     postgresql96-libs.x86_64 : The shared libraries required for any PostgreSQL clients
     postgresql96-odbc.x86_64 : PostgreSQL ODBC driver
     postgresql96-plperl.x86_64 : The Perl procedural language for PostgreSQL
     postgresql96-plpython.x86_64 : The Python procedural language for PostgreSQL
     postgresql96-pltcl.x86_64 : The Tcl procedural language for PostgreSQL
     postgresql96-server.x86_64 : The programs needed to create and run a PostgreSQL server
     postgresql96-tcl.x86_64 : A Tcl client library for PostgreSQL
     postgresql96-test.x86_64 : The test suite distributed with PostgreSQL
     Name and summary matches only, use "search all" for everything.
     [root@localhost src]# yum install postgresql96.x86_64 postgresql96-contrib.x86_64 postgresql96-libs.x86_64 postgresql96-server.x86_64
     Loaded plugins: fastestmirror, langpacks
     Loading mirror speeds from cached hostfile
     * base: ftp.riken.jp
     * extras: ftp.riken.jp
     * updates: ftp.riken.jp
     Resolving Dependencies
     --> Running transaction check
     ---> Package postgresql96.x86_64 0:9.6.3-1PGDG.rhel7 will be installed
     ---> Package postgresql96-contrib.x86_64 0:9.6.3-1PGDG.rhel7 will be installed
     ---> Package postgresql96-libs.x86_64 0:9.6.3-1PGDG.rhel7 will be installed
     ---> Package postgresql96-server.x86_64 0:9.6.3-1PGDG.rhel7 will be installed
     --> Finished Dependency Resolution
     Dependencies Resolved
     =============================================================================================================================================================================================================================================
     Package Arch Version Repository Size
     =============================================================================================================================================================================================================================================
     Installing:
     postgresql96 x86_64 9.6.3-1PGDG.rhel7 pgdg96 1.3 M
     postgresql96-contrib x86_64 9.6.3-1PGDG.rhel7 pgdg96 563 k
     postgresql96-libs x86_64 9.6.3-1PGDG.rhel7 pgdg96 310 k
     postgresql96-server x86_64 9.6.3-1PGDG.rhel7 pgdg96 4.3 M
     Transaction Summary
     =============================================================================================================================================================================================================================================
     Install 4 Packages
     Total download size: 6.5 M
     Installed size: 28 M
     Is this ok [y/d/N]: y
     Downloading packages:
     (1/4): postgresql96-contrib-9.6.3-1PGDG.rhel7.x86_64.rpm | 563 kB 00:00:03
     (2/4): postgresql96-libs-9.6.3-1PGDG.rhel7.x86_64.rpm | 310 kB 00:00:00
     (3/4): postgresql96-9.6.3-1PGDG.rhel7.x86_64.rpm | 1.3 MB 00:00:05
     (4/4): postgresql96-server-9.6.3-1PGDG.rhel7.x86_64.rpm | 4.3 MB 00:00:05
     ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     Total 686 kB/s | 6.5 MB 00:00:09
     Running transaction check
     Running transaction test
     Transaction test succeeded
     Running transaction
     Warning: RPMDB altered outside of yum.
     Installing : postgresql96-libs-9.6.3-1PGDG.rhel7.x86_64 1/4
     Installing : postgresql96-9.6.3-1PGDG.rhel7.x86_64 2/4
     Installing : postgresql96-contrib-9.6.3-1PGDG.rhel7.x86_64 3/4
     Installing : postgresql96-server-9.6.3-1PGDG.rhel7.x86_64 4/4
     Verifying : postgresql96-contrib-9.6.3-1PGDG.rhel7.x86_64 1/4
     Verifying : postgresql96-libs-9.6.3-1PGDG.rhel7.x86_64 2/4
     Verifying : postgresql96-server-9.6.3-1PGDG.rhel7.x86_64 3/4
     Verifying : postgresql96-9.6.3-1PGDG.rhel7.x86_64 4/4
     Installed:
     postgresql96.x86_64 0:9.6.3-1PGDG.rhel7 postgresql96-contrib.x86_64 0:9.6.3-1PGDG.rhel7 postgresql96-libs.x86_64 0:9.6.3-1PGDG.rhel7 postgresql96-server.x86_64 0:9.6.3-1PGDG.rhel7
     Complete!
     [root@localhost src]#
     [root@localhost src]# ls /usr/pgsql-9.6/
     bin doc lib share
     root@localhost src]# ls /usr/pgsql-9.6/bin/
     clusterdb createuser dropuser pg_archivecleanup pg_config pg_dump pg_receivexlog pg_restore pg_test_fsync pg_xlogdump postgresql96-setup reindexdb
     createdb dropdb initdb pg_basebackup pg_controldata pg_dumpall pg_recvlogical pg_rewind pg_test_timing postgres postmaster vacuumdb
     createlang droplang oid2name pgbench pg_ctl pg_isready pg_resetxlog pg_standby pg_upgrade postgresql96-check-db-dir psql vacuumlo
     [root@localhost src]#
    
    
  2. Cài đặt qua rpm
    Nếu môi trường cài đặt của bạn không thể connect ra internet bên ngoài. Bạn có thể download packages trực tiếp từ máy có kết nối tới internet từ đây. Sau đó cài đặt packages bằng lệnh rpm. Chú ý nếu cài đặt packages qua rpm, do quan hệ phụ thuộc giữa các package bạn phải cài đặt trước một số packages cần thiết.

    
     [root@localhost src]# rpm -qa | grep postgresql
     [root@localhost src]# (wget https://yum.postgresql.org/9.6/redhat/rhel-7-x86_64/postgresql96-9.6.3-1PGDG.rhel7.x86_64.rpm https://yum.postgresql.org/9.6/redhat/rhel-7-x86_64/postgresql96-contrib-9.6.3-1PGDG.rhel7.x86_64.rpm https://yum.postgresql.org/9.6/redhat/rhel-7-x86_64/postgresql96-libs-9.6.3-1PGDG.rhel7.x86_64.rpm https://yum.postgresql.org/9.6/redhat/rhel-7-x86_64/postgresql96-server-9.6.3-1PGDG.rhel7.x86_64.rpm ) > /dev/null 2>&1
     [root@localhost src]# echo $?
     0
     [root@localhost src]# ls
     pgdg-redhat96-9.6-3.noarch.rpm postgresql96-9.6.3-1PGDG.rhel7.x86_64.rpm postgresql96-contrib-9.6.3-1PGDG.rhel7.x86_64.rpm postgresql96-libs-9.6.3-1PGDG.rhel7.x86_64.rpm postgresql96-server-9.6.3-1PGDG.rhel7.x86_64.rpm
     [root@localhost src]# ls
     pgdg-redhat96-9.6-3.noarch.rpm postgresql96-9.6.3-1PGDG.rhel7.x86_64.rpm postgresql96-contrib-9.6.3-1PGDG.rhel7.x86_64.rpm postgresql96-libs-9.6.3-1PGDG.rhel7.x86_64.rpm postgresql96-server-9.6.3-1PGDG.rhel7.x86_64.rpm
     [root@localhost src]# rpm -ivh postgresql96-9.6.3-1PGDG.rhel7.x86_64.rpm postgresql96-contrib-9.6.3-1PGDG.rhel7.x86_64.rpm postgresql96-libs-9.6.3-1PGDG.rhel7.x86_64.rpm postgresql96-server-9.6.3-1PGDG.rhel7.x86_64.rpm
     Preparing... ################################# [100%]
     Updating / installing...
     1:postgresql96-libs-9.6.3-1PGDG.rhe################################# [ 25%]
     2:postgresql96-9.6.3-1PGDG.rhel7 ################################# [ 50%]
     3:postgresql96-contrib-9.6.3-1PGDG.################################# [ 75%]
     4:postgresql96-server-9.6.3-1PGDG.r################################# [100%]
     [root@localhost src]# ls /usr/pgsql-9.6/
     bin doc lib share
     [root@localhost src]# ls /usr/pgsql-9.6/bin
     clusterdb createuser dropuser pg_archivecleanup pg_config pg_dump pg_receivexlog pg_restore pg_test_fsync pg_xlogdump postgresql96-setup reindexdb
     createdb dropdb initdb pg_basebackup pg_controldata pg_dumpall pg_recvlogical pg_rewind pg_test_timing postgres postmaster vacuumdb
     createlang droplang oid2name pgbench pg_ctl pg_isready pg_resetxlog pg_standby pg_upgrade postgresql96-check-db-dir psql vacuumlo
     [root@localhost src]#
    
    

Cài đặt PostgreSQL trên môi trường Windows và MacOS

Bạn có thể download installer cho Windows ở đây, và cho MacOS ở đây và cài đặt theo winzard của installer. Trên cả 2 môi trường này đều có thể build từ source, nếu có nhu cầu bạn có thể tham khảo manual và build.

Đăng kí nhận RSS - Cài đặt