不要再选择MySQL了

考虑要选择MySQL?还是选择使用别的数据库吧。已经在用MySQL?迁移。对于每一个建立在MySQL中的成功项目,你可以发现时间会浪费在弥补MySQL上的不足,毫无意义,其成就感根本无法抵消在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)

果然意外,那么至少有一个警告吧:


owen@scratch> SHOW WARNINGS;
+---------+------+--------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'banana' |
+---------+------+--------------------------------------------+
1 row in set (0.03 sec)

由于原文篇幅较长,可以说列数太多MySQL问题,可谓是MySQL问题大全:
https://grimoire.ca/mysql/choose-something-else


[该贴被banq于2016-11-07 18:32修改过]

缺点再多也抵不过 免费+流行。。。。。。。。。。。。