Stan Blog

學習過程中的一些記錄

[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)

3NF (第三正規化

SQL 的主表不是從 FROM 的地方看,是從 JOIN 的地方跟 WHERE 的條件判定 execution plan (他會加計算哪個 cost performance 最好, 並做 column statistics(紀錄頻率跟 index) ) Ref: Execution Plan

Scaling Out

Comments

comments powered by Disqus