1.3 事物
事物就是一组原子性的SQL查询。事务内的语句,要么全部执行成功,要么全部执行失败。
从jane的支票账户转移200美元到她的储蓄账户,至少3个步骤:
1.检查支票账户的余额高于200美元
2.从支票账户余额减去200美元
3.在储蓄账户余额中增加200美元
ACID:
原子性(atomaticity)
一致性(consistency):数据库总是从一个一致性状态转换到另外一个一致性的状态。
隔离性(isolation):通常来说,一个事物所做的修改该在最终提交以前,对其他事物是不可见的。这里有隔离级别(Isolation level)的讨论。
持久性(durability):一旦事物提交,则其所做的修改就会永久保存到数据库中。
1.3.1 隔离级别
较低级别的隔离通常可以执行更高的并发,系统的开销也更低。
READ UNCOMMITTED(读未提交)
在这个级别,事物中的修改,即使没有提交,对其他事物也是可见的。事物可以读取未提交的数据,这也被称为脏读(Dirty Read).这个级别会导致很多问题,从性能上来说,READ UNCOMMITTED不会比其他的级别好太多,但却缺乏其他级别的很多好处,在实际应用中一般很少使用。
READ COMMITTED(读已提交)
一个事物开始时,只能“看见”已经提交的事物所做的修改。换句话说,一个事物从开始直到提交之前,所做的任何修改对其他事物都是不可见的。这个级别有时候不可重复读(nonrepeatable read),因为在
同一个事物
中两次执行同样的查询,可能会得到不一样的结果。
REPEATABLE READ(可重复读)
REPEATABLE READ解决了脏读的问题。该级别保证了在同一个事物中多次读取同样的记录的结果是一致的。当时用该隔离级别时,在事物执行期间会锁定该事物以任何方式引用的所有行。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom row).第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行。幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC)解决了幻读的问题。
可重复读是MySQL的默认食物隔离级别。
SERIALIZABLE(串行化)
最高的隔离级别,它通过强制事物串行化执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。也就是没有并发。