什么是事务?
事务就是将多个操作组合到一起完成,要么全部成功,要么全部失败,具体到数据库就是一组原子性的SQL查询,事务内的语句要么全部成功,要么全部失败。
转账的例子,小张给小王转账200块,小张这边要减200,小王那边要加200,没有事务的话如果小张减200成功,小王加200失败,那么小张给小王说我明明转账给你了,你却说没搜到,然后两个人就开始掐架了。有事务之后,小王那边加两百失败,那么整个交易是不会成功的,小张的账户也不会少200。
MySQL中通过
START TRANSANTION
来开启事务,通过
COMMIT
来提交事务。事务一旦提交成功,就说明事务内的一组操作全部执行成功。
什么是ACID
ACID是一系列数据库的设计模型,它强调业务数据的可靠性。MySQL 的InnoDB 存储引擎就是使用ACID模型来实现的。所以当异常情况(比如软件奔溃或者硬件出现故障)发生时并不会导致数据出现错误。使用ACID特性时,你不需要重新去造一个轮子来进行数据一致性检验和崩溃后数据恢复。但是当你有一定的软硬件保障措施,并且可以容忍一定数据的丢失,那么可以改变MySQL ACID的设置来提高并发和吞吐量。
- A: atomicity. 原子性
一个事务必须被事务不可分割的最小工作单元,整个操作要么全部成功,要么全部失败。MySQL通过COMMIT
提交事务或发生异常情况时通过ROLLBACK
语句来回滚事务。 - C: consistency. 一致性
数据库总能从一个一致性的状态转换到宁一个一致性的状态。比如转账的例子只要有任何一方发生异常就不会成功提交事务,事务所做的修改也不会持久化到数据库中。 - I: isolation.隔离性
一个事务相对于宁一个事务是隔离的,而隔离的程度室友事务的隔离性决定。的。MySQL通过
SET ISOLATION LEVEL
来设置事务隔离级别。
- D: durability.持久性
一旦事务提交,就会永久的保存到数据库中。
事务隔离级别
- READ UNCOMMITTED(未提交读)
事务中的修改即使没有提交,其他事务也能看见,事务可以读到为提交的数据称为脏读
。 - READ COMMITTED(提交读)
一个事务开始后只能看见已经提交的事务所做的修改。也就是一个事务从开始到提交前所做的所有修改对其他事务都是不可见的。这个时候在事务中执行两次同样的查询可能得到不一样的结果,所以也叫做不可重复读
。 - REPEATABLE READ(可重复读)
是MySQL默认的隔离级别。解决了脏读
的问题,该级别保证了在同一个事务中多次读取同样记录的结果是一样的。理论上该级别存在幻读
的问题。幻读是指事务在读取某个范围的数据时,宁一个事务又在该范围内中插入了新的数据
,当该事务再次读取该范围的数据时会读到。InnoDB通过MVCC解决幻读。 - SERIALIZABLE(串行化)
强制所有事务串行执行,所以并发效率低。
一个金典搞笑的比喻: -
脏读
假如,中午去食堂打饭吃,看到一个座位被同学小Q占上了,就认为这个座位被占去了,就转身去找其他的座位。不料,这个同学小Q起身走了。事实:该同学小Q只是临时坐了一小下,并未“提交”。 -
不重复读
假如,中午去食堂打饭吃,看到一个座位是空的,便屁颠屁颠的去打饭,回来后却发现这个座位却被同学小Q占去了。 -
幻读
假如,中午去食堂打饭吃,看到一个座位是空的,便屁颠屁颠的去打饭,回来后,发现这些座位都还是空的(重复读),窃喜。走到跟前刚准备坐下时,却惊现一个恐龙妹,严重影响食欲。仿佛之前看到的空座位是“幻影”一样。
参考文献:
《高性能MySQL》
https://dev.mysql.com/doc/refman/5.7/en/mysql-acid.html
http://blog.sina.com.cn/jackbillow