一,事务的概念
1.1为什么要有事务
在日常开发中,很多操作需要很多SQL一起配合才能完成,但在执行多个SQL时,就有可能前面那个SQL执行了,后面SQL执行时失败的情况
就比如这两句代码:
update accout set money=money-2000 where name = '阿里巴巴';
update accout set money=money+2000 where name = '四十大盗';
比如第一句代码成功后阿里巴巴的账户上面减少了两千,但第二句代码运行失效,就导致四十大盗账户上没有增加两千,这时就需要事务来操作,将这些打包成一个整体,要么全部不执行,要么执行就全部执行 有效避免部分执行,部分未执行,产生一些中间状态引起的问题。
但要注意这边并非真的没有执行,而是SQL是一条一条执行的,如果后面出问题了,事务就可以让数据库前面的SQL恢复如初,这也叫回滚,是事务的特性之一。
1.2事务流程
1)开启事务:start transaction;
2)执行多条SQL语句;
3)回滚或提交:rollback/commit;
二,事务的基本特性
2.1.原子性
原子性是的核心机制就是回滚,可以将出错的地方恢复如初,而怎么进行这个恢复如初呢,那就需要日志来协助,日志是数据库执行事务时,会记录日志,日志一般是写在硬盘之中,如果事务最终都完全执行,中间没有出现差错,这些日志就不要了。
2.2.一致性
执行事务之前,和执行事务完毕之后,数据得是一致的,不能出现对不上的情况,这也跟回滚是有关的,因为回滚回去的数据是对的上的,也是根据日志记录保证一致性。
2.3.持久性
持久性出现对应的一件事就是数据存储在硬盘上,要注意此处的持久是指不管程序重启还是主机重启,数据仍然存在
2.4.隔离性
隔离性也是最重要的,说的是数据库在并发执行事务时,产生的情况,要一起同时处理,很有可能出现问题,所以这里面涉及三个问题,
1)脏读问题
在这里就是事务A和事务B同时进来处理,形成了并发问题,这是事务A做出了修改,但还没有提交,但事务B这时读取了还没有提交时读取了事务A,事务A觉得修改的不合适进行了回滚,这时就产生了读到的数据和记录的数据不一致的情况,这是的数据是无效的,这就是所谓的‘脏读问题’
解决方案:进行写加锁,也就是我没有提交时你不能去读,这样可以提高隔离性,在执行A的过程中,B就不能执行了,要等待。提高了数据的准确性。
2)不可重复读问题
在这里存在三个事务同时处理,事务A针对数据进行了修改提交,这时事务B在A提交完之后读取,但读取过程中,事务C又针对数据进行了修改,这时事务C和事务B一起并发执行了,这是事务B就读取了不同的数据,在去读一次就出来的结果不一样,这就是‘不可重复读问题’
解决方案:进行读加锁,也就是我在读的过程中,你不能去更改,这里会进一步增强隔离性,降低并发性。
3)幻读问题
事务A修改并提交了数据,这时B在读取数据,比如一个mysql的表数据,这时C没有修改表数据,但在对应的表进行新增数据,这时B再次读取发现有一个多的数据,这就是‘幻读问题’
解决方案:进行串行化,使所有的事务都严格的按照一个一个的方式执行,完全没有并发了,此时执行效率最低,但隔离性是最高的,数据也是最准确的。
4)总结
脏读:事务B读到了事务A还没有提交的数据--->进行写加锁
不可重复读:事务B读到了事务A提交的数据,但事务C更改了数据,导致事务B再次读取得到的数据是不同的-->进行读加锁
幻读问题:事务B在读取的过程中有事务C新增了数据-->进行串行化
三,四个隔离级别
read uncommitted #允许读取其他事务未提交的数据-->脏读+不可重复读+幻读
read committed #只能读取其他事务提交后的数据-->解决了脏读
repeatable read #进行了写和读加锁-->只存在幻读
serializable #所有事务都是串行执行的-->不存上述问题