ACID 测试
ACID 表示原子性、一致性、隔离性和持久性。一个运行良好的事务处理系统,必须具备这些标准概念。
原子性
一个事务必须被视为一个不可分割的最小工作单元。
一致性
一个事务中所有语句,要么成功,要么失败。
隔离性
一个事务所做的修改,在最终提交以前,对其他事务是不可见的。
隔离级别
隔离性其实比想象的更复杂。
-
READ UNCOMMITTED(未提交读)
在这个级别中,事务中的修改,即使没有提交,对其他事务也都是可见的。
这种读被称为"脏读"。在实际应用中一般很少使用。
-
READ COMMITTER(提交读)
大多数数据库系统的默认隔离级别都是 READ COMMITTER(但 MYSQL不是)。
即,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。
这个级别有时候也叫做不可重复读(nonrepeatable read),因为两次执行同样的查询,可能会得到不一样的结果。
-
REPEATABLE READ(可重复读)
这个级别解决了脏读的问题。该级别保证了同一个事务中多次读取同样的记录的结果是一致的。
理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom Read)的问题。
所谓幻读,指的是某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。
-
SERIALIZABLE(可串行化)
这是最高的隔离级别。
避免了幻读的问题。
会在读取的每一行数据上加锁,所以可能导致大量的超时和锁争用的问题。
实际应用中也很少用到这个级别。只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑使用这一级别。
隔离级别 | 脏读可能性 | 不可重复读可能性 | 幻读可能性 | 加锁读 |
---|---|---|---|---|
READ UNCOMMITTER | YES | YES | YES | NO |
READ COMMITTER | NO | YES | YES | NO |
REPEATABLE READ | NO | NO | YES | NO |
SERIALIZABLE | NO | NO | NO | YES |
持久性
一旦事务提交,则其所做的修改就会永久保存到数据库中。
死锁问题
死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。
为了解决死锁导致非常慢的查询,数据库系统实现了各种死锁检测和死锁超时的机制。
锁的行为和顺序是和存储引擎相关的,以同样的顺序执行语句,有些引擎会产生死锁,有些则不会。
死锁产生有双重原因:
- 有些是因为真正的数据冲突,这种情况很难避免
- 但有些则完全是由于存储引擎的实现方式导致的
死锁产生后,只有部分或者完全回滚其中的一个事务,才能打破死锁。
事务日志
事务日志可以帮助提供事务的效率。
使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久的硬盘上的事务日志中,而不用每次都将修改的数据持久到硬盘。
所以,修改数据需要写两次磁盘。
MySQL 中的事务
MySQL 提供了两种事务型的存储引擎:InnoDB 和 NDB Cluster。另外还有一些第三方存储引擎,比如 XtraDB 和 PBXT。
MYSQL 采用自动提交的模式。也就是说如果不显式地开启一个事务,则每个查询都被当做一个事务执行提交操作。
可以执行如下命令设置隔离级别:
SET TRANSACTION ISOLATION LEVEL [隔离级别]
在同一事务中,使用多种存储引擎是不可靠的。