1.什么是事务?
1.1事务使用的场景
在我们的生活中,我们通常会遇到银行转账这样的场景:
若要把张三的前给李四转100,则需要两个sql操作
(1)把张三的余额-100;
(2)给李四的余额加上100;
在这个操作中,可能会出现极端的操作(若给张三的余额-100,此时程序崩溃了,此时张三的余额为900,李四的余额为500)。事务就是为了结局这种问题的。
1.2事务的概念
事务就是把若干个SQL语句给打包成一个整体,要么全部执行完,要不就一个都不执行,哪怕执行一半,中间出现差错了,数据库也能保证把已经改动过的数据给自动还原成最初的样子。这里的清理还原操作称为"回滚" roll back。
2.事务的(ACID)特性
2.1 ACID特性
- 原子性(最核心的特性)
事务是数据库的逻辑工作单位,事务中包括的诸操作,要么都做,要么都不做。 - 一致性
事务执行完毕之后,数据仍然是合理的(程序员手动定义的 约束) - 持久性
事务执行完毕之后,数据就存在磁盘上了,哪怕重启主机,数据也仍然存在。 - 事务的隔离性
一个事务的执行不能被其他的事务干扰。即一个事务的内部操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能相互干扰。
2.2 mysql并发执行事务可能产生的问题
- 脏读
一个事务A在修改数据,另外一个事务B直接就读取A正在修改的数据。此时B就读到了一个脏数据。因为此时B读到的数据很可能就在A的后续操作中又进行了修改,相当于B读到的数据只是一个“中间的状态”,读到这个中间的数据,就是脏数据,这个动作,就叫脏读。
并发:事务A在修改数据,事务B直接读取事务A正在修改的数据就是“并发”的关系,事务A修改数据和事务B读取数据完全是不确定的,先后顺序没有任何限制。
解决脏读的问题:给写操作加锁。 - 不可重复读
事务A修改数据然后提交,提交完毕后事务B开始读取数据。事务B中包含了很多次的读操作。如果事务B两次读操作得到的结果不一样,就是不可重复读。不一样的原因就是事务A虽然把数据已经提交了,但是可能又执行了一次事务A,又把这个数据给修改了。
事务B第一次读到的数据是事务A提交的,第二次读到的数据是事务A又提交了一次。
解决不可重复读:给读操作也加所。 - 幻读
事务B正在读取数据,事务A插入了新的数据(或者删除了某个数据),事务B两次读取的数据集的个数发生了变化。
解决幻读:串行化:彻底的让事务之间串行执行,此时就没有涉及任何的并发的事情了,必须要第一个执行完,再执行第二个,第三个。
2.3 mysql中事务的隔离级别
一共有四种隔离级别:
- read uncommitted 没有做出任何隔离行的限制,三个问题都存在,执行效率最高。
- read committed 相当于进行了写加锁,并发程度降低了,隔离级别就提高了,此时脏读问题解决了,不可重复读和幻读仍然存在。
- repeatable read相当于读加锁,并发程度又降低了,隔离级别又提高了,此时脏读和不可重复读解决了。幻读仍然存在(mysql的默认隔离级别)。
- Serializable 串行化,并发程度最低,隔离级别最高,此时脏读,不可重复读,幻读都消失了,执行效率最低的方式。