几乎每周、有时甚至更为频繁,总有人会问我们为何不采用
MySQL
作为
OpenACS
的
RDBMS
(关系式
数据库
管理
系统
)。
ACS Classic team
(
ArsDigita
)也一再地在他们的论坛上遇到同样的提问。如果
MySQL
对于
Slashdot
来说足够好的话,它也一定能够用于
OpenACS
,不是吗?
不对。
这篇简短的论文将尝试解释为何
MySQL
不仅对
OpenACS
来说是错误的选择,它也不应被用于任何处理关键数据的
系统
。
RDBMS
的目的
RDBMS
的目的是提供一种可靠的永久存储机制,在
ACID
测试中具体表述了这种机制的非常严格的特性。我将直接引用
Philip Greenspun
的精彩解释(以
Oracle
作为
RDBMS
的代表):
原子性(
Atomicity
)
事务的执行结果或者被全部提交、或者被全部回滚(
roll back
)。要么所有的变动都生效,要么就没有变动生效。假定一个用户正在编辑一条注释,
Web
脚本告诉
数据库
“将旧注释值拷贝到审计表中,并用新文本更新活动表”。如果在拷贝之后、更新之前硬盘变满的话,审计表插入就将被回滚。
一致性(
Consistency
)
数据库
从一种有效状态转换到另一种有效状态。仅在服从用户定义的完整性约束时,一个事务才是合法的。不允许非法的事务,而且,如果不能满足某完整性约束的话,该事务会被回滚。例如,假定你定义了一条规则:论坛表中的帖子必须与有效的用户
ID
相关联。然后你雇用了
Joe Novice
来编写管理页面。
Joe
编写了一个删除用户页面,它不会检查删除是否会产生一些无主的论坛帖子。然而像
Oracle
这样的
RDBMS
将会进行检查,并中止任何事务,如果它产生的论坛帖子为已被删除的用户所拥有的话。
隔离性(
Isolation
)
一个事务的结果对于其他事务是不可见的,直到该事务完成为止。例如,假定你有一个显示新用户和他们的照片的页面。按照出版者的要求,在页面中每个用户都有一张面部照片,如果用户没有照片的话就显示一幅表示无照片的图像。在新用户
Jane
在你的站点注册的同时,老用户
Bill
正在查看新用户页面。处理
Jane
的注册的脚本会对若干表进行插入:
users
、
mugshots
、
users_demographics
。如果
Jane
的面部照片很大的话,上述插入可能会需要一些时间。如果
Bill
的查询在
Jane
的事务提交之前开始的话,
Bill
根本不会在他的新用户页面上看到
Jane
,即使在
Jane
的事务中,对某些表的插入已经完成。
持久性(
Durability
)
一旦提交(完成),事务的结果将是永久性的,并能免于未来的
系统
和介质故障。假设你的电子商务
系统
将来自某消费者的定单插入
数据库
表中,并指示
CyberCash
收取该消费者
500
美元的费用。突然间,在你的
服务器
收到
CyberCash
的回复之前,有人绊掉了机器的电源线。在这样的情况下,
Oracle
将不会忘记该定单。而且,如果有
程序
员将咖啡洒进了磁盘驱动器中,安装一个新磁盘,并将事务回复到咖啡泼洒时为止是可能的;数据将显示你曾试图收取某人
500
美元,并且还不清楚在
CyberCash
那里发生了什么。
如果你所要的是快速的裸存储,去使用
文件
系统
。如果你想要在多台机器间进行共享,去使用
NFS
。如果你想要简单的可靠性,以对付过于简单的故障,去使用镜像。想要给它们加上
SQL
接口?去使用
MySQL
。
现在,如果你所要的是这样的数据存储,它能够使你的数据集的若干方面保持恒定,能够对这些数据进行复杂的操作、而永不违反上述的那些约束,能够将多个用户同时进行的局部工作彼此隔离开来,并且能够从任何种类的故障中进行平稳的恢复,那就给你自己找一个真正的
RDBMS
。是的,它会比
MySQL
文件
系统
慢,就像
TCP
比
UDP
慢一样,但它们却提供了更好的服务担保。
MySQL
的现状与未来
构建真正的
RDBMS
是一项艰巨的任务,也许比任何其他
系统
问题都要艰巨。市场上的大多数产品(
Oracle
、
Sybase
、
PostgreSQL
、
Interbase
)已经进行了多年的开发,有些还超过了
10
或
15
年。
MySQL
的开发人员声称他们牺牲了某些特性,以保证更好的性能。尽管这或许是一种追踪非关键数据(比如点击率追踪)的有趣方法,在处理关键数据时,牺牲完全的数据完整性是不可接受的,即使是为了速度也同样如此。
当
MySQL
成熟时,
OpenACS
团队很高兴对其进行距离更近的考察。但是,
MySQL
团队似乎并不理解真正的
ACID
能力的概念和重要性:
MySQL Todo
在一个很长的列表中提到了“事务”,其中包括了诸如“睡眠进程占用
CPU
吗”这样的问题。此外,
MySQL
手册声称
MySQL
将很快通过表锁的使用来实现“原子操作”,但却“
没有回滚
”。这是对术语“原子的”明目张胆的误用:“原子操作”意味着或者所有操作都完成,或者没有操作完成。如果没有回滚能力的话,在一组语句的中间发生的硬件或电力故障将破坏块的原子性。
回滚不只是一种便利的特性,它是可靠的数据存储的关键性基础。
有许多很好的理由使用
MySQL
,但对可靠的、顺从
ACID
的数据存储的需求却并非是其中之一。
更多的细节
l
MySQL
没有子查询。
对于复杂的查询,
MySQL
用户必须执行两次或更多的系列查询,每一次都需要在应用和
数据库
间进行进程间通信或
网络
通信。这显著地降低了MySQL的速度优势。
l
MySQL
没有存储过程。
l
MySQL
没有触发器或外键约束。
l
MySQL
只有表级锁定。
结语
企业级
系统
不会为了速度而牺牲特定的特性。
RDBMS
的
ACID
属性对于任何关键数据来说都是绝对必需品。在非
ACID
顺从的
系统
上运行的关键网站是在自找麻烦。
OpenACS
项目拒绝打破
ACID
测试的重要法则。我们要构建的是企业级的开放源码
Web
工具包。
PostgreSQL
、很快还有
InterBase
将成为这一项目合适的候选RDBMS
。而
MySQL
只是一个有着
SQL
接口的被美化的
文件
系统
。