第九章 數據庫管理

9.1 用戶及權限管理

9.1.1 Greenplum 數據庫邏輯結構

圖9-1

在 gp/pgsql 中,角色(Role)、模式(Schema)、數據庫(DataBase)是三個不同的概念,不同於 Mysql 的 DataBase 等同於 Schema,Oracle 的 Role 等同於 Schema。

在 gp 中:

  1. 一個 database 下可以有多個 schema。schema在 gp 中也叫做 namespace。
  2. Language 在使用前必須創建,一個語言只屬於一個 database
  3. table、view、sequence、function 必須只屬於一個 schema
  4. 一個 filespace 可以有多個 tablespace,一個 tablespace 只屬於一個 filespace,fielspace 與 role 沒有關係
  5. tablespace 與 table 是一對多的關係,一個 schema 下的表可以分佈在多個 tablespace 下
  6. 在圖9-1 中,除了 filespace 之外,其他的權限管理都是通過 role 來實現,在這些層次結構中,用戶必須對上一層有訪問權限,才能夠訪問該層的內容
  7. group 與 role 是一樣的概念,group的語法還能用,但實際上已被廢棄了

9.1.2 Grant 語法(賦權)

創建數據庫語法爲:

CREATE ROLE name [[WITH] option [ ... ]]
where option can be:
    SUPERUSER | NOSUPERUSER 
    | CREATEDB | NOCREATEDB 
    | CREATEROLE | NOCREATEROLE 
    | CREATEEXTTABLE | NOCREATEEXTTABLE
    [ ( attribute='value'[, ...]) ] 
    where attribute and values are:
    type='readable'|'writable'
    protocol='gpfdist'|'http'|'gphdfs'
    | INHERIT | NOINHERIT
    | LOGIN | NOLOGIN
    | CONNECTION LIMIT connlimit
    | [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'password'
    | VALID UNTIL 'timestamp'
    | IN ROLE rolename [, ...]
    | ROLE rolename [,...]
    | ADMIN rolename [,...]
    | RESOURCE QUEUE queue_name

從語法上看,參數配置主要有:

  1. 超級用戶(SUPERUSER):最高用戶權限,不受資源隊列控制,擁有所有的權限,可以對數據庫進行任何操作,一般只有 DBA 可以擁有這個權限
  2. 創建數據庫權限(CREATEDB)
  3. 創建用戶權限(CREATEUSER)
  4. 登錄權限(LOGING):可以指定該用戶登錄的連接數控制
  5. 創建外部表權限(CREATEEXTTABLE):屬性配置中也可以對外部表有更細的權限控制,如只讀、可寫外部表權限等
  6. 用戶繼承(INHERIT):子用戶可以擁有父用戶的所有權限
  7. 資源隊列控制(RESOURCE QUEUE)
  8. 密碼控制(ENCRYPTED):還可以指定密碼以及失效時間

賦權命令 Grant:

GRANT 權限類型 ON Relation(如表、視圖、函數、schema等) TO 用戶或用戶組

9.2 登錄權限控制

客戶端認證是由一個配置文件(通常名爲 pg_hba.conf)控制的,它存放在數據庫集羣的數據目錄中。HBA 是 “Host-Based Authentication”的縮寫,即基於主機的認證,可以限制登錄機器的 IP 段。

9.3 資源隊列即併發控制

資源負載管理是爲了限制系統中活動的 sql 對使用資源的消耗,避免由於 sql 將系統資源(如 CPU、I/O、內存)耗盡而造成系統緩慢或崩潰。資源隊列可以限制活動 sql 的個數,以及 sql 各種消耗的大小。每一個用戶會對應到一個資源隊列中。通過對用戶消耗資源的控制,dba 可以儘量避免系統出現過負載。

資源隊列在 gp 中是如何工作的?

資源調度在系統安裝的時候已經默認打開了,所有的數據庫用戶都必須對應了一個資源對象,如果配置具體的資源隊列,默認的資源隊列是 pg_default。

在 gp 中,資源隊列可以實現如下的限制:

  • 活動的 sql 數,在這個資源隊列下最多能夠運行的 sql 數
  • 能夠消耗的最大內存
  • sql 優先級,與其他隊列的比較,主要限制在 cpu 的資源上
  • sql 的cost 值

圖9-3

(1)內存

如果一個資源隊列中限制了最大使用內存是 2000 MB,同時設置了同時執行的sql 數爲 10 個,那麼每一個 sql 最多使用的內存是 200 MB,同時每個 sql 消耗的內存,不能大於 statement_mem 參數中設置的內存大小。當一個 sql 運行時,這個內存大小就會被分配出來,直到 sql 執行結束後才釋放

(2)CPU

cpu 優先級管理,每一個資源隊列中,都有一個對應的 cpu 優先級。cpu 的優先級有三個登記:

  • abhoc,低優先級
  • reportin,高優先級
  • executive,最高優先級

當系統中有新的 sql 進入的時候,各個 sql 消耗 cpu 的資源會根據其優先級重新評估,如圖9-4:

圖9-4

當 executive 優先級的 sql 進入時,系統會將大部分的資源分配給它,如圖9-5:

圖9-5

(3)語法介紹

並不是所有的 sql 都會被限制在資源隊列中,在默認情況下,select、select into、create table as select 和 declare cursor 會被限制在隊列中。如果將參數 resource_select_only 設置爲 off,那麼 insert、update、delete 語句也會被限制在隊列中。

下面介紹如何創建資源隊列,以及如何使用資源隊列,語法如下:

CREATE RESOURCE QUEUE name WITH (queue_attribute=value [, ...])
where queue_attribute is:
    ACTIVE_STATEMENTS=integer
        [ MAX_COST=float [COST_OVERCOMMIT={TRUE|FALSE}]]
        [ MIN_COST=float]
        [ PRIORITY={MIN|LOW|MEDIUM|HIGH|MAX}]
        [ MEMORY='memory_units']| MAX_COST=float [COST_OVERCOMMIT={TRUE|FLASE}]
        [ ACTIVE_STATEMENTS=integer]
        [ MIN_COST=float]
        [ PRIORITY={MIN|LOW|MEDIUM|HIGH|MAX}]
        [ MEMORY_LIMIT='memory_units']

(1)創建一個隊列只有限制最大的活動sql數:

CREATE RESOURCE QUEUE abhoc WITH (ACTIVE_STATEMENTS=3);

(2)創建一個隊列加上內存限制:

CREATE RESOURCE QUEUE myqueue WITH (ACTIVE_STATEMENTS=20, MEMORY_LIMIT='200MB');

如果想對一個sql進行特殊處理,增加其運行時的內存,那麼可以設置 statement_mem 參數,將它調大:

SET statement_mem='2GB';
select * from my_big_table where column='value' order by id;
RESER statement_mem;

(3)設置最大的cost值:

CREATE RESOURCE QUEUE webuser WITH (MAX_COST=10000.0);

(4)設置 CPU 優先級:

CPU優先級有5個級別:MIN|LOW|MEDIUM|HIGH|MAX,可以根據不同的需求選擇:

ALTER RESOURCE QUEUE ABHOC WITH (PRIORITY=HIGH);

查看配置情況:

SELECT * FROM pg_resqueue_attributes;

查看現有的資源隊列使用情況:

SELECT * FROM pg_resqueue_status;

在 gp_toolkit 中,還有幾個視圖可用於查看資源隊列的使用情況:

\dv gp_toolkit.gp_resq*

創建/修改用戶指定資源隊列:

CREATE ROLE aquery RESOURCE QUEUE abhoc;
ALTER ROLE etl RESOURCE QUEUE abhoc;

修改資源隊列的語法如下,只有超級用戶纔可以修改資源組:

ALTER RESOURCE QUEUE name WITH (queue_attribute=value [, ...] )
where queue_attribute is:
    ACTIVE_STATEMENTS=integer
    MEMORY_LIMIT='memory_units'
    MAX_COST=float
    COST_OVERCOMMIT={TRUE|FALSE}
    MIN_COST=float
    PRIORITY={MIN|LOW|MEDIUM|HIGH|MAX}

9.4 Greenplum 鎖機制

gp 的鎖基本上與 postgresSQL 的鎖是一樣的,但 gp 的鎖機制還不夠完善,在某些場景上可能會出現一些問題。

表9-1

表9-1-2

這集中鎖的衝突如表9-2所示:

表9-2

圖9-7

locktype表示鎖住的內容,主要是transactionid 和 relation。在gp中,master到segment的連接就是一個 transaction,只要一連接就會有這個鎖信息。

relation對應pg_class的oid字段。

gpid不等於-1就是代表每一個segment的鎖信息。

通過 lock 命令可以顯式地將表鎖住,語法如下:

Command: LOCK
Description: lock a table
Syntax:
LOCK [ TABLE ] name  [, ...] [ IN lockmode MODE] [ NOWAIT]
where lockmode is one of :
    ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE

9.5 數據目錄結構

圖9-8是gp主節點(master)的數據目錄結構:

圖9-8

  • base是數據目錄,每個數據庫在這個目錄下,會有一個對應的文件夾
  • global是每一個數據庫公用的數據目錄
  • gpperfmon監控數據庫性能時,存放監控數據的地方
  • pg_changetracking 是 segment 之間主備同步用到的一些原數據信息保存的地方
  • pg_clog 是記錄數據庫事務信息的地方,保存每一個事務id的狀態,這個非常重要,不能丟失,一旦丟失,整個數據庫就基本上不可用了
  • pg_log 是數據庫的日誌信息
  • pg_twophase 是二階段提交的事務信息(二階段提交參閱第7章)
  • pg_xlog 是數據庫重寫日誌保存的地方,其中每個文件固定大小爲64MB,並不斷重複使用
  • gp_dbid 記錄這個數據庫的dbid 以及它對應的 mirror節點的dbid
  • pg_hba.conf 是訪問權限控制文件
  • pg_ident.conf 是 Ident 映射文件
  • PG_VERSION 是 PostgreSQL 的版本號
  • postgresql.conf 是參數配置文件
  • postmaster.opts 是啓動該數據庫的 pg_ctl 命令
  • postmaster.pid 是該數據庫的進程號和數據目錄信息

其中base 下面的文件夾結構爲:

# ls
1 10890 10891 16992 285346

其中一個文件夾代表一個數據庫,文件夾的名字就是數據庫的oid,可以通過 pg_databse查詢其對應關係

9.6 數據文件存儲分佈

下面分別介紹表、索引、序列的文件存儲分佈(外部表和視圖沒有實際的數據,沒有數據文件生成),每一種類型對應數據庫裏面哪些文件

(1)表

一般的堆表只有一個數據文件,如果表中有大字段,會多兩個數據文件:toast表、toast表索引。

大字段:text字段、varchar的大小大於2036的字段。

select oid,relname,reltoastrelid from pg_class where relname='表名';

默認 toast表的名字爲 pg_toast_ + 原表的 relfilenode,索引爲 pg_toast_ + 原表的 relfilenode + _index,例如316696是原表的oid:

# select oid, relname from pg_class where relname ~ '316696';

 oid    |  relname
 -----------------
 316698 | pg_toast_316696
 316699 | pg_toast_316696_index

如果是 Appendonly 表,那麼會多4個文件:pg_aoseg、pg_aovisimap表及其索引對應的數據文件(參閱第6章)

(2)索引

索引文件只有一個,可以通過索引名在pg_class中查找。索引在創建時就分配了32KB 的存儲控件,等到這32 KB用完纔開始擴大。

(3)序列

序列(Sequence)與索引一樣,也只有一個數據文件,在pg_class中對應一條記錄,relfilenode 字段就是文件名。

如果一個表中有字段是 serial 類型的,即一個遞增序列,那麼這個表會自動創建一個序列,也就會多一個數據文件。

9.7 表空間管理

在 gp4.0 之後的版本中,gp加入了文件空間(Filespace)和表空間(Tablespace)的概念。

在系統初始化的時候,只有兩個表空間 pg_default 和 pg_global,這兩個表空間都在 pg_system 這個文件系統下:

select a.spcname, b.fsname from pg_tablespace a ,pg_filespace b where spcfsoid=b.oid;

 spcname    | fsname
 ------------------------
 pg_default | pg_system
 pg_global  | pg_system

pg_global 表空間保存的是各個數據庫之間的通用信息,在 data_directory/global 目錄下,pg_default 表空間保存的是每個數據庫特有的數據,包括數據字典及用戶數據。其中,每一個數據庫都會有一個對應的數據目錄,如果數據庫中的表比較多,或者表分區比較多(每一個分區都相當於一張表),那麼在一個目錄下就會有非常多的文件,文件數太多會給文件系統帶來非常大的壓力。因此,當文件數增長到一定程度的時候,就必須使用表空間,將數據存放到多個目錄下。

在 gp 中,表空間必須創建在文件空間上,默認只有 pg_system 一個文件空間,在這個文件空間上不能再創建其他的表空間。

下面介紹如何創建多一個文件空間:

  1. 爲每一個表空間創建系統目錄,在master 和每一個 segment 上都要創建:

    MASTER:/home/gpadmin/gpdata/master_fspc
    Primary Segment:/home/gpadmin/gpdata/primary_fspc
    Mirror Segment:/home/gpadmin/gpdata/mirror_fspc
    
  2. 運行 gpfilespace 腳本,根據提示輸入文件系統的名字和每個segment的目錄

    $ gpfilespace
    ...
    > fs_test
    ...
    
  3. 之後,會生成一個 gp_filespace_config 文件,這個文件中保存了每個 segment 對應的數據目錄(也可以手動編輯這個文件):

    cat /home/gpadmin/gpdata/gpfilespace_config_20120603_210559
    fielspace:fs_test
    mdw:1:/home/gpadmin/gpdata/master_fspc?gpseg-1
    ...
    

    運行 gpfilespace 創建文件系統:

    $ gpfilespace --config /home/gpadmin/gpdata/gpfilespace_config_20120603_210559
    

    創建好文件系統之後,就可以在上面創建表空間了:

    testDB#= create tablespace tbs_test1 filespace fs_test;
    CREATE TABLESPACE
    

    在表空間創建成功之後,在建表時就可以使用參數,指定表建在哪個表空間下面:

    create table test_01 (id int ,name varchar(200))
    tablespace tbs_test1 distributed by (id);
    

    在filespace 的目錄下,就可以看到剛剛創建的表的數據文件了:

    9-5

    默認都是在 default_tablespace(參數)下面建表,這個參數默認是 pg_default 表空間,可以在配置文件 postgresql.conf 中修改這個參數,或者以下命令:

    set default_tablespace='tbs_test1';
    

    這樣,建的表就在這個表空間下。還可以爲每一個用戶設置不同的表空間,同時必須給表空間賦權:

    testDB=# alter role etl set default_tablespace='tbs_test2';
    ALTER ROLE
    testDB=# grant ALL on tablespace tbs_test2 to etl;
    

    更換表空間,將表 hello1 從表空間tbs_test2 更換到 tbs_test3:

    testDB=# alter table hello1 set tablespace tbs_test3;
    

9.8 小結

本章介紹了數據庫管理的相關內容,以及一些基本的數據庫管理工具。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章