autovacuum程序----資料架構師的PostgreSQL修煉
阿新 • • 發佈:2019-01-05
1. 檢查autovacuum程序
- sherrywangs-MacBook-Pro:data postgres$ ps -fu postgres |grep autov
- 502 3199 3192 0 Sun08PM ?? 0:00.27 postgres: autovacuum launcher process
這是一個可選程序預設在postgresql.conf中,autovacuum = on。
2. 理解vacuum
當從表中刪除某些記錄時,PostgreSQL並不會立即從資料檔案中刪除這些記錄,他們會被標記為刪除。
當更新某些記錄時,粗略看起來,像是執行了一次刪除和一次插入操作;老版本的記錄仍然留在系統中。
為什麼這麼做呢?
因為有一些正活躍的事務,希望看到它之前的資料。
這就是經典的MVCC(Multiversion Concurrent Control)技術,目的是提高併發度,讀操作不會阻塞寫操作,寫操作也不會阻止讀操作。
這樣會引入一個新問題,一段時間之後,有些死記錄變得無關緊要,因為已經沒有事務再想要檢視這些已經標記為刪除的記錄。
vacuum操作將對死記錄的空間進行標識,進而可以在表內重用,該操作不需要鎖定資料表。
vacuum full操作還會對死記錄進行移除,該操作需要表上的一個排它鎖。
3. vacuum實驗
3.1 建立新的資料庫vac和表myt,並檢視所佔磁碟空間
建立新資料庫vac:
- postgres=# create database vac;
- CREATE DATABASE
用oid2name那麼檢視vac的oid:
- postgres=# \! oid2name
- Password:
- All databases:
- Oid Database Name Tablespace
- ----------------------------------
- 12669 postgres pg_default
- 12668 template0 pg_default
-
1 template1 pg_default
- 16393 vac pg_default
連線到資料庫vac:
- postgres=# \c vac
- You are now connected to database "vac" as user "postgres".
建立表myt:
- vac=# create table myt(id integer);
- CREATE TABLE
表myt在磁碟上的檔名:
- vac=# select pg_relation_filepath('myt');
- pg_relation_filepath
- ----------------------
- base/16393/16397
- (1 row)
表myt所佔磁碟空間為0:
- M121313CPG3QD:16393 postgres$ ls -l /PostgreSQL/9.6/data/base/16393/16397*
- -rw------- 1 postgres daemon 0 Sep 13 18:28 /PostgreSQL/9.6/data/base/16393/16397
可以用更便捷的方法查詢表myt所佔磁碟空間:
- vac=# select pg_total_relation_size('myt');
- pg_total_relation_size
- ------------------------
- 0
- (1 row)
向表myt插入100000行資料,檢視myt所佔用的磁碟空間:
- vac=# insert into myt select generate_series(1,100000);
- INSERT 0 100000
- vac=# select pg_total_relation_size('myt');
- pg_total_relation_size
- ------------------------
- 3653632
- (1 row)
- M121313CPG3QD:16393 postgres$ ls -l /PostgreSQL/9.6/data/base/16393/16397*
- -rw------- 1 postgres daemon 3629056 Sep 13 18:47 /PostgreSQL/9.6/data/base/16393/16397
- -rw------- 1 postgres daemon 24576 Sep 13 18:46 /PostgreSQL/9.6/data/base/16393/16397_fsm
刪除表myt中的一部分資料,檢視myt所佔用的磁碟空間:
- vac=# delete from myt where id>5 and id<10000;
- DELETE 9994
- vac=# delete from myt where id>5 and id<100000;
- DELETE 90000
- vac=# select pg_total_relation_size('myt');
- pg_total_relation_size
- ------------------------
- 3653632
- (1 row)
- M121313CPG3QD:16393 postgres$ ls -l /PostgreSQL/9.6/data/base/16393/16397*
- -rw------- 1 postgres daemon 3629056 Sep 13 18:51 /PostgreSQL/9.6/data/base/16393/16397
- -rw------- 1 postgres daemon 24576 Sep 13 18:46 /PostgreSQL/9.6/data/base/16393/16397_fsm
可以看到,刪除了9994行資料後,表myt所佔用的空間沒有減小。
vacuum myt,檢視myt所佔用的磁碟空間:
- vac=# vacuum myt ;
- VACUUM
- vac=# select pg_total_relation_size('myt');
- pg_total_relation_size
- ------------------------
- 3661824
- (1 row)
- M121313CPG3QD:16393 postgres$ ls -l /PostgreSQL/9.6/data/base/16393/16397*
- -rw------- 1 postgres daemon 3629056 Sep 13 18:51 /PostgreSQL/9.6/data/base/16393/16397
- -rw------- 1 postgres daemon 24576 Sep 13 18:46 /PostgreSQL/9.6/data/base/16393/16397_fsm
- -rw------- 1 postgres daemon 8192 Sep 13 18:52 /PostgreSQL/9.6/data/base/16393/16397_vm
可以看到myt所佔用磁碟空間沒有顯著減小。
另外發現新增加了一個16397_vm的檔案,看來這個字尾_vm的檔案和vacuum有關。
vacuum full myt,檢視myt所佔用的磁碟空間:
- vac=# vacuum full myt ;
- VACUUM
- vac=# select pg_total_relation_size('myt');
- pg_total_relation_size
- ------------------------
- 8192
- (1 row)
- vac=# select pg_relation_filepath('myt');
- pg_relation_filepath
- ----------------------
- base/16393/16400
- (1 row)
- M121313CPG3QD:16393 postgres$ ls -l /PostgreSQL/9.6/data/base/16393/16400*
- -rw------- 1 postgres daemon 8192 Sep 13 18:56 /PostgreSQL/9.6/data/base/16393/16400
可以發現,原來myt對應檔案16397內容被移動到新檔案16400,16397被清空,後續16397會被刪除。