[DB] RDBMS 淺談
參加 Triton Ho 的 RDBMS 淺談 的一些筆記
1. 為何選擇 RDBMS
- 歷史悠久, 社群支援度良好, 基本上不會有太大的問題
- 比 NoSQL 有更快的發開速度
- 對於一般中小型系統, 效能足夠了
- 更加安全
快速開發
大部分系統 multiple records atomicity 不能避免的需求 (e.g. 把錢從用戶 A 轉到用戶 B、購買虛擬道具)
支援多種資料型態 支援十進制的 numeric, 在計算金錢數值時特別有用
中小型系統(資料量 < 100GB), RDBMS 做報表容易
1. 單純使用 SQL 就可以 (JOIN 與 sub query 就能滿足大部分需求)
2. 常用的報表工具都內建 (AVG、SUM、COUNT)
- 商業系統, 對資料流失度容忍度低
高資料安全性
所有 RDBMS 返回 ‘成功’ 後, 結果的資料改動 除非儲存空間受損, 否則資料永不流失
MongoDB 的 Write Concern 預設是 Acknowledged 意思是資料還沒存到硬碟裡, 就先返回 ok (有安全上的疑慮)
Ref: Acknowledged MongoDB Mode
2. ACID
每家 database 都自稱支持 ACID, 但定義都有所不同 (在 noSQL 世界特別嚴重)
Atomicity
- RDBMS 所有運作都是以 transatciton (後簡稱 tx) 為單位
- 一個 tx 可包含許多的 SQL 指令
- 同一 tx 必須全部被順序執行, 或是全部改動都不被執行
- 當機時, 還沒 commit 的 tx 全被 Rollback
- 當機後, 需要修復資料時, RDBMS 必須以 tx 為單位進行修復
重要性
- 當機是不可避免的, 要確保當掉後不會有數據錯誤
- Atomicity 保證系統數據從一個正確狀態 (consistent state) 移到下一個正確狀態
- NoSQL 沒有 transaction, 需要 9 個步驟的 2 phase commit
Consistency
- Consistency 保證發生錯誤時可以安全回到上一個正確狀態
重要性
- 發生錯誤時直接 Rollback tx 就好, 不用煩惱怎麼把改動還原
- 在 NoSQL 的 2pc, 當機後就需要花時間來復原資料
Isolation
- 保證同一筆資料不會同時被兩個 tx 改動
- Isolation level, 讓該 application 只看到應該看的資料
- 要避免 rece condition, LOCK 是不能避免的, 而 RDBMS 能自動管理 LOCK
重要性
- 沒有 Isolation 的話, 需要自行管理 Lock, 需要額外的 locking 系統
REF: mutex
Durability
- 一旦 Committed 資料改動, 除非儲存空間受損, 否則永不流失
- 前提: 沒有亂改 Linux kernel 與 RDBMS 標準設定
- 即使在資料寫入時斷電, 因發在正寫入的區塊資料流失 RSBMS 也有機制在斷電後復原資料
- High performance + High concurrency + High durability 系統是非常困難設計的
- MongoDB 標準設定是沒有等待 Disk WRITE 的成功寫入, 對資料庫知識不足的使用者會造成當機資料的數據流失
重要性
- 一般商用系統, 大部分的數據都是不能流失的
- 一但斷電了, RDBMS 會依 TX 為單位進行 Data Recovery, 保證資料庫部會停留在不正確的狀態
- 高流量高同時下的檔案讀寫非常非常困難, 若無必要千萬不要自己做
REDO log
- 大部分系統數據改動是 random 的
- 其 Disk WRITE 也會是 Random IO
- 如果每個 tx 都要等待 random io 完成, 效能會慢到不能接受
step1. 用戶改動資料後, TX1 對 page xxxx 發出了 commit 指令, 這時資料還停留在 memory step2. RDBMS 會用 append 的方式將 page xxxx 寫進 redo log1 末端 step3. RDMMS 對 linux 發出 fsync(), 保證資料確實存入硬碟中, 而不是停留在 檔案系統的 cache 裡 step4. page xxxx 確實存入了硬碟中, RDBMS 對 TX1 回應 commit 成功訊息 step5. RDBMS 的 background writer 把 Page 抄回原來位置 step6. RDBMS 持續觀察 REDO log, 確認 data page 儲存好, 便會把 redo log1 刪掉
flexable schema
- RDBMS 可以建立 table 時, 預先建立 col1, col2, col3… 的 string column, 想要增加 record 的 column 時, 隨便挑一個來用
- RDBMS 不是不能 flexable schemam 而是中小型資料庫不應該使用
使用 flexable schema 的典型情況
GEt object from db
switch (object.version) {
case v1: v1_logic(); break;
case v2: v2_logic(); break;
}
- 每多一種 data version 就會多一個 condition
- 除非把所有 v1 的 records 轉換為最新版本,不然 v1_logic() 永遠不能刪除
- 在 ‘每天都很忙’ 的公司裡, v1 很快會變成 ‘傳家之寶’
- 除非是面對 TB 等級的數據,或是真的需要 zero downtime deployment 才需要 flexible schema
一般中小型系統, 允許 15 分鐘 downtime, 在 deployment downtime 裡改動 table schema 更加務實
要為 tables 新增 columns 時, 不要使用 alter table
CTAS: Create table as select
- create tableXnew as select col1, col2 from tableX 然後刪掉 table, 再把 tableXnew 改名成 tableX
CTAS 比 alter table 快很多, 但要小心 foreign key, table privilege, table setting
其他
MVCC -> Oracle/PostgreSQL SXLock -> DB2/MySQL/MSSQL
自己管理 lock 看起來很容易, 但實作起來很難 redis SETNX [key] [value] EX: 10sec [lockname] [] EX: 10sec
Ref: http://redisdoc.com/string/setnx.html
expotenial BackOff With Jitter
master <- slave 做 repica 資料儲存回傳 ok, 兩種可能 1. 只存到 master (async) 2. master、slave 都存 (sync)
SQL 的主表不是從 FROM 的地方看,是從 JOIN 的地方跟 WHERE 的條件判定 execution plan (他會加計算哪個 cost performance 最好, 並做 column statistics(紀錄頻率跟 index) ) Ref: Execution Plan