上一篇我們完成了第一個比較完整的 API,CRUD 五個操作都可以正常使用。
但最後也發現一個問題:
只要把 Server 關掉再重開,剛剛新增的資料就全部不見了。
今天就來看看為什麼會這樣,以及資料庫幫我們解決了什麼問題。
先啟動 Day 16 的程式:
python app.py
用 POST /tasks 新增兩筆資料,再用 GET /tasks 確認:
[
{"id": 1, "name": "洗碗", "completed": false},
{"id": 2, "name": "寫 Day 17", "completed": false}
]
新增完兩筆資料後,GET /tasks 的結果
接著回到終端機,按 Ctrl + C 把 Server 關掉,再重新執行:
python app.py
然後再打開一次 GET /tasks:
[]
重開 Server 之後,GET /tasks 變成空陣列
資料真的不見了。
因為我們的資料是放在這裡:
tasks = []
next_id = 1
這是 Python 的變數。
程式執行的時候,這些變數是放在記憶體(RAM)裡面的。
記憶體的特性是「速度很快,但程式結束就會被清掉」。
所以:
程式啟動 → tasks = []
新增資料 → tasks 裡面有東西
程式關掉 → 記憶體被釋放
程式再啟動 → tasks 又變回 []
每一次重開,都等於從頭開始。
而且不只是我們手動關掉才會這樣,像是程式出錯、更新程式重新部署、伺服器重開機,都會造成同樣的結果。
對一個真的在用的服務來說,這顯然不行。
這是很直覺的想法:把資料寫進一個 tasks.json 或 tasks.txt,程式啟動的時候再讀回來。
這樣確實可以解決「重開就不見」的問題,小專案有時候也真的會這樣做。
但是當資料變多、使用的人變多之後,會遇到不少麻煩:
查資料很麻煩
如果想找「所有還沒完成的作業」,就要自己把整個檔案讀進來,再一筆一筆判斷。
資料有十萬筆的時候,每次查詢都要讀十萬筆。
同時操作會打架
如果有兩個人同時新增作業,兩邊都讀了同一份檔案、各自改完再寫回去,後寫的那個就會蓋掉前面那個,資料就這樣少了一筆。
改到一半失敗怎麼辦
假如寫檔寫到一半程式當掉,檔案可能只寫了一半,整份資料就壞掉了。
資料格式沒有人幫忙把關
今天存成 “completed”: false,明天不小心存成 “completed”: “否”,程式也不會阻止我們。
資料之間的關聯不好處理
例如之後想要「每一筆作業都屬於某一個使用者」,用檔案就要自己想辦法對應。
這些問題不是不能自己解決,只是全部自己寫會非常辛苦。
而這些事情,剛好就是資料庫在幫我們做的。
資料庫(Database)可以先簡單理解成:
一個專門用來保存和管理資料的系統。
它會把資料存在硬碟上,所以程式關掉、電腦重開,資料都還在。
除了「存起來」之外,它還幫我們處理了:
查詢:可以用條件快速找出想要的資料
同時存取:多個人同時操作時,不會互相蓋掉
一致性:一件事情要嘛整個完成,要嘛整個不算數(Transaction)
資料規則:可以規定某個欄位一定要有值、不能重複等等
我們平常講的資料庫,其實大多是在講 DBMS(資料庫管理系統),例如 MySQL、PostgreSQL、SQLite 這些軟體。
大致上可以先分成兩類:
關聯式資料庫(SQL)
資料存在「表格」裡,有明確的欄位。
使用 SQL 這種語言來操作。
例如:SQLite、MySQL、PostgreSQL、SQL Server
非關聯式資料庫(NoSQL)
資料不一定是表格的形式,例如用類似 JSON 的方式存。
例如:MongoDB、Redis
這 30 天我們會使用關聯式資料庫,因為它的概念(表格、欄位、一筆一筆的資料)跟我們前面寫的 API 很好對應,也是後端最常見的起點。
在關聯式資料庫裡,我們這次會使用 SQLite。
原因很簡單:
不用另外安裝資料庫伺服器,Python 本身就內建支援
整個資料庫就是一個檔案(例如 tasks.db),複製、刪除都很方便
學習的時候不會卡在安裝和設定上
SQLite 很適合開發、測試、小型應用。
如果之後是正式上線、很多人同時使用的服務,通常會換成 MySQL 或 PostgreSQL。
好消息是,我們之後會使用 ORM(Day 19 會介紹),換資料庫的時候程式不用整個重寫,改設定就可以了。
資料存在 Python 變數裡 → 在記憶體,程式關掉就不見
改用檔案存 → 可以保存,但查詢、同時操作、資料一致性都要自己處理
資料庫 → 專門負責保存和管理資料,把上面那些麻煩事都處理好了
這次會先使用 SQLite,因為不用安裝、一個檔案就是一個資料庫。
不過既然說關聯式資料庫是用「表格」存資料、用 SQL 來操作,那:
表格長什麼樣子?SQL 又要怎麼寫?
下一篇就來認識 Table、Row、Column,還有最基本的 SELECT 和 INSERT。