autovacuum

VACUUM

VACUUM và chức năng autovacuum

Tại sao PostgreSQL cần VACUUM ?

  1. Dung lượng đĩa cứng có thể full
    Khác với các RDBMS khác (như MySQL), khi người dùng chạy lệnh DELETE hay UPDATE, PostgreSQL không xoá dữ liệu cũ đi luôn mà chỉ đánh dấu "đó là dữ liệu đã bị xoá".
    Nên nếu liên tục INSERT/DELETE hoặc UPDATE dữ liệu mà không có cơ chế xoá dữ liệu dư thừa thì dung lượng ổ cứng tăng dẫn đến full.

  2. Lỗi (dữ liệu bị vô hiệu) khi Wraparound Transaction ID
    PostgreSQL sử dụng 32 bit Transaction ID (XID) để quản lý transaction(1). Mỗi một record dữ liệu đều có thông tin về XID. Khi dữ liệu được tham chiếu PostgreSQL sử dụng thông tin XID này so sánh với XID hiện tại để đánh giá dữ liệu này có hữu hiệu không. Dữ liệu đang tham chiếu có XID lớn hơn XID hiện tại là dữ liệu không hữu hiệu. Khi sử dụng hết 32 bit XID (khoảng 4 tỷ transactions), để sử dụng tiếp XID sẽ được reset về ban đầu (0). Nếu không có cơ chế chỉnh lại XID trong data thì mỗi lần reset XID, dữ liệu hiện tại sẽ trống trơn (dữ liệu hiện tại luôn có XID lớn hơn XID đã reset (0)).

Một trong những chức năng của VACUUM là quyết những vấn đề như trên.

(1) transaction(Giao dịch cơ sở dữ liệu): Định nghĩa từ wikipedia: Giao dịch cơ sở dữ liệu (database transaction) là đơn vị tương tác của một hệ quản lý cơ sở dữ liệu hoặc các hệ tương tự, mỗi giao dịch được xử lý một cách nhất quán và tin cậy mà không phụ thuộc vào các giao dịch khác. Một hệ cơ sở dữ liệu lý tưởng sẽ phải bảo đảm toàn bộ các tính chất ACID cho mỗi giao dịch. Trên thực tế, các tính chất này thường được nới lỏng để giúp việc thực thi đạt hiệu quả hơn.

PostgreSQL không thực hiện xóa dữ liệu ngay sau khi DELETE hoặc UPDATE nhằm giải quyết vấn đề cùng một lúc nhiều người sử dụng truy cập một vùng dữ liệu (PostgreSQL gọi cơ chế đó là Multiversion Concurrency Control hay MVCC). Theo thông tin gần đây từ cộng đồng PostgreSQL, từ phiên bản 12(?) PostgreSQL có thể bỏ chức năng VACUUM nhờ sử dụng cơ chế lưu trữ zheap.

VACUUM thực hiện những công việc gì

  • Lấy lại dữ liệu dư thừa để tái sử dụng
  • Cập nhật thông tin thống kê (statistics)
  • Giải quyết vấn đề dữ liệu bị vô hiệu khi Wraparound Transaction ID

Lấy lại dữ liệu dư thừa

Như trên, PostgreSQL chưa xoá dữ liệu cũ khi thực hiện thao tác DELETE/UPDATE. Khi VACUUM, những dữ liệu dư thừa đó sẽ được lấy lại và vị trí dư thừa sẽ được cập nhật lại trong bảng vị trí trống (Free Space Map(FSM)). Ngoài ra những block dữ liệu đã được VACUUM sẽ được đánh dấu là đã VACUUM trên bảng khả thị (Visibility Map(VM)), khi UPDATE/DELETE dữ bảng khả thị sẽ cập nhật lại trạng thái là cần VACUUM.

Free Space Map(FSM): Mỗi bảng dữ liệu (hoặc index) tồn tại tương ứng một FSM. FSM chứa thông tin các vị trí trống trong file dữ liệu. Khi dữ liệu mới được ghi PostgreSQL sẽ nhìn vị trí trống từ FSM trước, việc này giảm thiểu truy cập trực tiếp (sinh I/O disk) vào file dữ liệu. File FSM nằm cùng vị trí với file dữ liệu và có tên = file_dữ_liệu_fsm (như ví dụ dưới).
Visibility Map(VM): Mỗi bảng dữ liệu tồn tại tương ứng một visibility map (VM). Một block dữ liệu tương ứng với 1 bit trên VM. VACUUM xem trước thông tin VM của bảng dữ liệu, và chỉ thực hiện trên những block cần được VACUUM. File VM nằm cùng vị trí với file dữ liệu và có tên = file_dữ_liệu_vm (như ví dụ dưới).


testdb=# create table testtbl(id integer);
CREATE TABLE
testdb=# insert into testtbl select generate_series(1,100);
INSERT 0 100
testdb=# delete from testtbl where id < 90;
DELETE 89
testdb=# checkpoint;
CHECKPOINT
testdb=# \! ls -l $PGDATA/base/16384/24576*
-rw------- 1 bocap staff 8192 Jun 24 18:19 /Users/bocap/Downloads/pg94/data/base/16384/24576
-rw------- 1 bocap staff 24576 Jun 24 18:19 /Users/bocap/Downloads/pg94/data/base/16384/24576_fsm
-rw------- 1 bocap staff 8192 Jun 24 18:19 /Users/bocap/Downloads/pg94/data/base/16384/24576_vm

Cập nhật lại thông tin thống kê

Một số bạn lầm tưởng rằng chỉ có chức năng ANALYZE mới cập nhật lại thông tin thống kê dùng bởi planner, nhưng thực tế VACUUM cũng cập nhật thông tin này. Cụ thể là relpages và reltuples trong system catalog pg_class. Do vậy nên có thể nói VACUUM cũng ảnh hưởng tới việc chọn plan thực thi.


postgres=# select relpages,reltuples from pg_class where relname = 'testtbl';
 relpages | reltuples 
----------+-----------
        0 |         0
(1 row)

postgres=# insert into testtbl select generate_series(1,10),random()::text;
INSERT 0 10
postgres=# select relpages,reltuples from pg_class where relname = 'testtbl';
 relpages | reltuples 
----------+-----------
        0 |         0
(1 row)

postgres=# vacuum testtbl;
VACUUM
postgres=# select relpages,reltuples from pg_class where relname = 'testtbl';
 relpages | reltuples 
----------+-----------
        1 |        10
(1 row)

autovacuum

autovacuum là chức năng tự động thực thi VACUUM hoặc ANALYZE khi cần thiết. Chức năng này hoạt động khi tham số autovacuumtrack_counts thiết lập là on. Cả 2 tham số này đều mặc định là on nên autovacuum sẽ tự động hoạt động khi khởi động PostgreSQL. Khi tham số autovacuum là on. Sau khi khởi động PostgreSQL process "autovacuum launcher process" sẽ đảm nhận việc này.


BocapnoMacBook-Pro:postgres bocap$ ps -ef | grep autovacuum | grep  -v grep
501  3169  3164   0 13Aug17 ??         0:03.13 postgres: autovacuum launcher process


Launcher process cứ mỗi autovacuum_naptime sẽ kiểm tra thông tin thống kê, nếu thấy bảng nào cần thiết VACUUM hoặc ANALYZE, launcher process sẽ khởi động các worker processes để thực hiện việc VACUUM hoặc ANALYZE. Số lượng process autovacuum worker hoạt động trong cùng một thời điểm được giới hạn bởi tham số autovacuum_max_workers (mặc định là 3).


BocapnoMacBook-Pro:postgres bocap$ ps -ef | grep autovacuum | grep  -v grep
  501 26490 26484   0  1:14AM ??         0:00.01 postgres: autovacuum launcher process   
  501 26618 26484   0  1:16AM ??         0:00.03 postgres: autovacuum worker process   postgres

Điều kiện cần thiết cho bảng được VACUUM hoặc ANALYZE bởi autovacuum như bên dưới.

Ví dụ: số lượng dòng là 1000, thì mặc định khi số dòng bị xoá hoặc update lớn hơn 0.2*1000 + 50 = 250 bảng sẽ tự động được VACUUM

Ví dụ: số lượng dòng là 1000, thì mặc định khi số dòng bị xoá, update hoặc insert lớn hơn 0.1*1000 + 50 = 250 bảng sẽ tự động được ANALYZE

Khi chạy một câu truy vấn, thông tin thống kê cần phải chính xác để planner chọn đúng plan tối ưu nhất. autovacuum thực thi việc cập nhật thông tin này, nhưng vì một số lý do nào đó (ví dụ: đối tượng bảng đang bị lock trong transaction khác) , autovacuum không thực thi được tốt. Vì vậy, khi thấy câu truy vấn chạy chậm, nên kiểm tra thông tin thống kê xem ANALYZE, VACUUM đã được thực hiện tốt chưa thông qua view pg_stat_all_tables, và thực hiện  VACUUM ANALYZE  cũng là một giải pháp

Ngoài ra để  process autovacuum không ảnh hưởng tới hệ thống, việc thiết lập autovacuum = off và chạy VACUUM ANALYZE thủ công vào thời điểm thích hợp cũng được sử dụng nhiều

Giám sát hoạt động autovacuum

Để biết đối tượng bảng có được VACUUM, ANALYZE hợp lý không ta có thể xem thông qua view pg_stat_all_tables.

-- ví dụ bên dưới cho thấy bảng testtbl đã được:
-- vacuum thủ công vào lúc: 2017-08-26 23:50:28
-- autovacuum vào lúc: 2017-08-27 01:16:04 
-- autoanalyze vào lúc: 2017-08-27 01:16:04

postgres=# select last_vacuum,last_autovacuum,last_analyze,last_autoanalyze from pg_stat_all_tables where relid = (select oid from pg_class where relname = 'testtbl');
          last_vacuum          |        last_autovacuum        | last_analyze |       last_autoanalyze        
-------------------------------+-------------------------------+--------------+-------------------------------
 2017-08-26 23:50:28.025241+09 | 2017-08-27 01:16:04.664297+09 |              | 2017-08-27 01:16:04.665366+09
(1 row)

Ngoài ra, ta có thể theo dõi tình trạng hoạt động của autovacuum thông qua việc thiết lập tham số log_autovacuum_min_duration = 0 (log tất cả các hoạt động autovacuum).

Ví dụ:


2017-08-27 01:16:04.664 JST [26618] LOG:  automatic vacuum of table "postgres.public.testtbl": index scans: 0
	pages: 1276 removed, 0 remain, 0 skipped due to pins, 0 skipped frozen
	tuples: 100000 removed, 0 remain, 0 are dead but not yet removable, oldest xmin: 579
	buffer usage: 3851 hits, 0 misses, 0 dirtied
	avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
	system usage: CPU: user: 0.02 s, system: 0.00 s, elapsed: 0.28 s
2017-08-27 01:16:04.665 JST [26618] LOG:  automatic analyze of table "postgres.public.testtbl" system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s

 

Cấu trúc processes của PostgreSQL

Cấu trúc processes của PostgreSQL

Khác với một số RDBMS khác sử dụng thread để xử lý, PostgreSQL sử dụng mỗi process cho những chức năng riêng biệt. Sau khi khởi tạo database và khởi động server, PostgreSQL sẽ có những processes như bên dưới.


[postgres@ip-172-31-31-242 ~]$ ps -ef | grep `head -1 $PGDATA/postmaster.pid    
postgres 17397     1  0 Apr11 pts/3    00:06:44 /usr/pgsql-9.6/bin/postgres    
postgres 17398 17397  0 Apr11 ?        00:00:33 postgres: logger process     
postgres 17400 17397  0 Apr11 ?        00:00:18 postgres: checkpointer process    
postgres 17401 17397  0 Apr11 ?        00:01:24 postgres: writer process     
postgres 17402 17397  0 Apr11 ?        00:01:31 postgres: wal writer process    
postgres 17403 17397  0 Apr11 ?        00:06:13 postgres: autovacuum launcher process    
postgres 17404 17397  0 Apr11 ?        00:11:30 postgres: stats collector process    
postgres  7205 17397  0 03:23 ?        00:00:00 postgres: postgres postgres [local] idle    

Cấu trúc tổng quan của các Processes có thể hiểu như bên dưới.

PostgreSQL processes


Postmaster Process


postgres 17397     1  0 Apr11 pts/3    00:06:44 /usr/pgsql-9.6/bin/postgres    

Là process khởi tạo đầu tiên sau khi server khởi động. Process này đảm nhiệm việc khởi động hoặc dừng các process khác nếu cần hoặc có yêu cầu. Sau khi khởi động Postmaster sẽ khởi động các processes thường trực như bên dưới để PostgreSQL server có thể hoạt động.

  • logger process
  • checkpointer process
  • writer process
  • wal writer process
  • autovacuum launcher process (process này không khởi động khi parameter autovacuum = off)
  • stats collector process

 Tiếp đó Postmaster sẽ thực hiện vòng lặp của mình, nếu có yêu cầu kết nối thoả mãn yêu cầu authenticate, hoặc khởi động các tiến trình thường trực khi bị lỗi. Khi có yêu cầu shutdown từ người dùng (pg_ctl stop), Postmaster sẽ gửi các signal tương ứng tới từng server processes.

logger process


postgres 17400 17397  0 Apr11 ?        00:00:18 postgres: logger process    

Process này đảm nhiệm việc ghi log của PostgreSQL.

checkpointer process


postgres 17400 17397  0 Apr11 ?        00:00:18 postgres: checkpointer process    

Process này chủ yếu giữ vai trò thực hiện checkpoint (đồng bộ dữ liệu từ bộ nhớ đệm xuống vùng lưu trữ) khi cần thiết.

writer process


postgres 17401 17397  0 Apr11 ?        00:01:24 postgres: writer process     

Hay còn gọi là background writer process, process này kết hợp với checkpointer process để đảm bảo việc ghi dữ liệu từ bộ đệm xuống vùng lưu trữ. Thông thường khi checkpoint không hoạt động, process này sẽ ghi từng chút một dữ liệu xuống vùng lưu trữ. Để hiểu thêm về background writer process xin vui lòng tham khảo ở manual tại đây.

wal writer process


postgres 17402 17397  0 Apr11 ?        00:01:31 postgres: wal writer process    

Đảm nhiệm việc đồng bộ WAL từ bộ nhớ đệm xuống vùng lưu trữ. Thông thường WAL sẽ được ghi từ bộ đệm xuống vùng lưu trữ khi transaction được commit. Nếu dữ liệu đệm của WAL trên bộ nhớ đệm vượt quá parameter wal_buffers dữ liệu WAL trên vùng nhớ đệm sẽ tự động ghi xuống vùng lưu trữ dữ liệu thông qua process này.

autovacuum launcher process


postgres 17403 17397  0 Apr11 ?        00:06:13 postgres: autovacuum launcher process    

Process này thường trú khi paramter autovacuum = on. Proccess này thực hiện chức năng tự động lấy vùng dữ liệu dư thừa sau khi DELETE hoặc UPDATE dữ liệu. Vui lòng thảo khảo bài viết về VACUUM để biết thêm về VACUUM. Process này khởi động các VACUUM worker processes sau mỗi autovacuum_naptime. Các VACUUM worker processes sẽ thực hiện việc VACUUM dữ liệu trên các database.

stats collector process


postgres 17404 17397  0 Apr11 ?        00:11:30 postgres: stats collector process    

Process này thực hiện vai trò lưu trữ các thông tin thống kê hoạt động của PostgreSQL và cập nhật vào các system catalog (thông tin nội bộ của PostgreSQL hiện diện bởi các bảng hoặc view pg_stat_*).

Server Process


postgres  7205 17397  0 03:23 ?        00:00:00 postgres: postgres postgres [local] idle    

Là các processes được sinh ra khi có yêu cầu từ phía client (aplication). Client gửi yêu cầu (bằng cách chạy các connection API) tới server, phía server sẽ sử dụng thông tin authentication (user, password, database, host) từ client để xem user này có được truy cập vào database không. Nếu được, Postmaster sẽ tạo một server process (bằng API fork()) cho client, từ đó client có thể chạy được các câu truy vấn, ... thông qua server process được tạo.

Một số processes không thường trực

Các processes không thường trực của PostgreSQL
Processes Chức năng
archiver process Thực hiện chức năng backup archive log (WAL). Process này khởi động khi parameter archive_mode = on.
startup process Process này thường trực ở Standby node, thực hiện chức năng phản ảnh dữ liệu WAL nhận được từ Master.
wal receiver process Thường trực ở standby. Sau khi khởi động process này kết nối tới Master node và tạo kết nối replication.
wal sender process postgres Thường trực ở Master khi có Standby (hoặc pg_basebackup) kết nối tới. Số lượng process wal sender bằng với số lượng wal receive + pg_basebackup kết nối tới.
bgworker: logical replication launcher [PostgreSQL 10] Process sử dụng cho chức năng logical replication. 
Đăng kí nhận RSS - autovacuum