不要再選擇MySQL了
資料庫是填補從單純的儲存到複雜和有趣的資料處理之間的角色;MySQL壞在希望兼顧這不同的極端任務。而真正的應用都是介於兩極之間,結果會遭遇MySQL這種定位帶來的不匹配痛苦:
1.MySQL在儲存方面不行
2.MySQL在資料處理儲存方面也是不行
3.MySQL的設計就不行
這篇文章是受到PHP: A Fractal of Bad Design.啟發,如果對MySQL粉有所冒犯,請原諒。
原文見:
The Codex » Do Not Pass This Way Again,大意如下:
儲存方面
儲存應該有四個屬性:
1.從應用程式中獲取資料並儲存他們。
2.保持資料的安全性,防止損失或意外變化。
3.嚮應用程式提供儲存的資料。
4.給管理員有效的管理工具
MySQL在儲存上存在下面問題:
1.隱式轉換(特別是來自於或從字串型別的轉換)可以修改MySQL的行為。許多隱式轉換保持沉默(沒有警告,沒有診斷),設計上更可能是讓開發人員完全沒有注意這些,直至令人驚訝的事情發生。
2.違反輸出型別基本約束(範圍、長度)的轉換經常強行挾持資料而不是失敗放棄。有時這會引發一個警告,你的應用程式檢查這些?這種行為是與許多型別的系統(像PHP和遠端像Perl)非常類似。
3.轉換行為取決於每一個連線配置值(sql_mode),有大量可能狀態,使其從手工測試到程式碼或從工具到工具之間遷移時難以實現預期一致性。
4.MySQL推薦使用UTF-8,但是預設是Latin-1,MySQL 5.5的utf8只有3個位元組BMP,雖然支援4個位元組utf-8,但是需要設定字符集卻是utf8mb4,這種特殊方式讓人困惑。
在MySQL這些編碼的實現細節,如UTF8 3位元組的限制,往往會洩露到客戶端應用程式。不適合MySQL理解的儲存編碼的資料將被轉化,預設或截斷或更換。
5.TIMESTAMP 型別透過儲存值在一個時區(UTC)中試圖做得更聰明,但它做得太少,很難說MySQL對你的資料幫助你做了正確的事。
foo <'2012-04-01 09:00:00'的結果還取決於你查詢時是什麼時候,除非你非常小心你的連線時區。DATETIME 的時間並不能和TIMESTAMP處理得到的時間相同。
儲存資料
對意外情況發生:像大多數磁碟備份儲存系統,MySQL是用磁碟和檔案系統的資料作為資料儲存體。MySQL的映象或硬體容錯方面並沒有如Oracle ASM提供額外的功能。然而,與許多其他系統共享存在限制。
使用InnoDB儲存引擎時(從MySQL 5.5設為預設),MySQL維護頁校驗以便來檢測潛在的儲存導致的中斷。然而,許多第三方的應用軟體,以及從可以使用MyISAM的早期MySQL版本升級的使用者,會在正常關機下經常損壞的資料檔案。
....
此外,一些明顯無害的功能可能會導致備份或副本與原始資料庫無法同步,可見在預設配置中的下面這些語句功能:
1.AUTO_INCREMENT 和 UPDATE .
2.AUTO_INCREMENT 和 INSERT (有時 驚奇)
3.觸發器Triggers.
4.User-defined (native) 原生函式
5.儲存過程SQL
6.DELETE ... LIMIT 和 UPDATE ... LIMIT語句,
7.INSERT ... ON DUPLICATE KEY UPDATE
8.LOAD DATA 批次載入資料
獲取資料
大部分符合預期正常工作。MySQL主要儲存儲存資料的時候做魔術,而不是獲取時。然而,在獲取返回資料之前,有一些東西是透過隱式變換儲存的:
下面展示查詢並不能和儲存預期的一致:
owen@scratch> CREATE TABLE account ( -> accountid INTEGER -> AUTO_INCREMENT -> PRIMARY KEY, -> discountid INTEGER -> ); Query OK, 0 rows affected (0.54 sec) owen@scratch> INSERT INTO account -> (discountid) -> VALUES -> (0), -> (1), -> (2); Query OK, 3 rows affected (0.03 sec) Records: 3 Duplicates: 0 Warnings: 0 owen@scratch> SELECT * -> FROM account -> WHERE discountid = 'banana'; +-----------+------------+ | accountid | discountid | +-----------+------------+ | 1 | 0 | +-----------+------------+ 1 row in set, 1 warning (0.05 sec) <p class="indent"> |
果然意外,那麼至少有一個警告吧:
owen@scratch> SHOW WARNINGS; +---------+------+--------------------------------------------+ | Level | Code | Message | +---------+------+--------------------------------------------+ | Warning | 1292 | Truncated incorrect DOUBLE value: 'banana' | +---------+------+--------------------------------------------+ 1 row in set (0.03 sec) <p class="indent"> |
由於原文篇幅較長,可以說列數太多MySQL問題,可謂是MySQL問題大全:
https://grimoire.ca/mysql/choose-something-else
[該貼被banq於2016-11-07 18:32修改過]
相關文章
- ⚠ | 不要再使用 markdown 主題了!
- 不要再問我MVC、MVP、MVVM了MVCMVPMVVM
- 我選擇了MySQL和SpringData JPAMySqlSpring
- 【漫畫】不要再問我快速排序了排序
- 不要再爭論程式碼風格了!
- 不要再問我跨域的問題了跨域
- 我為什麼放棄MySQL?選擇了MongoDBMySqlMongoDB
- 你們不要再吵了! Java只有值傳遞..Java
- [技術討論]拜託,不要再本本主義了
- mysql 行格式選擇_Mysql 行格式MySql
- 面試官,不要再問我“Java GC垃圾回收機制”了面試JavaGC
- 不要再問我Java程式是怎麼執行的了!Java
- 不要再學 JSP 了,學 SpringBoot + Thymeleaf + Vue吧JSSpring BootVue
- Python!請不要再亂搞 Linux 發行版了PythonLinux
- 不要再勸導菜鳥程式猿使用vim或者Emacs了Mac
- 拜託,不要再幫黑客來猜我的密碼了黑客密碼
- 別再瞎找專案了,公眾號依舊是你不二選擇
- 不要再滿世界搜linux命令了,我給你整理到一塊了Linux
- 不要再滿世界搜linux命令了,我給你整理到一塊了。Linux
- 淺談邏輯選擇器 -- 父選擇器它來了!
- 不要再說你不會了——網路效能問題排查思路
- 不要再使用JS框架了JS框架
- Mysql學習版本的選擇MySql
- mysql 貨幣型別 選擇MySql型別
- 單親媽媽生意失敗,再選一次她為什麼選擇了同城拓客專案?
- 不要再問我跨域的問題了,這篇文章全搞定!跨域
- 千萬不要再這樣建立集合了!極容易記憶體洩露!記憶體洩露
- 馬雲:實體店不要再恨我了 阿里投資實體零售阿里
- 不要再寫出不能在 Python 4 中執行的程式了Python
- mysql 為什麼很多網際網路公司選擇了讀可提交MySql
- MySQL索引選擇及規則整理MySql索引
- 如何選擇mysql的儲存引擎MySql儲存引擎
- MySQL字首索引和索引選擇性MySql索引
- mysql聯合索引的選擇性MySql索引
- 選擇最穩定的MySQL版本MySql
- 選擇或者放棄MySQL的理由MySql
- 初入職場的小夥伴請注意,這 8 個坑不要再踩了
- Babel配置不要再“複製貼上”了,帶你自己配一個BabelBabel