一个事务就是一个完整的业务逻辑。举例:A向B转账10000,即A减去10000,B加上10000。这个操作是一个最小的工作单元,必须一起成功或失败。
只有DML语句才有事务的说法,因为只有insert、update、delete才是对数据进行增删改。而一旦对数据进行操作,必须考虑安全问题。事务本质是批量的DML语句,同时成功或者失败。
事务包括四个特性:(1)原子性:事务是最小的工作单元;(2)一致性:同一事务中所有操作必须同时成功或者失败;(3)隔离性:A事务和B事务之间有一定的隔离,如两个事务同时操作一张表;(4)持久性:事务最终结束的保障。
一、事务的实现
在事务执行过程中,每一条事务都会记录到InnoDB提供的日志中,既可以提交事务,也可以回滚事务。
提交事务:清空事务性活动的日志文件,将数据永久储存到数据库表中。标志着事务的结束,并且是成功结束。
回滚事务:也要清空事务性活动的日志文件,将之前的操作全部撤销,标志着事务的失败结束。
提交和回滚事务:commit、rollback;
rollback只能回滚到上一次的提交点,由于mysql有自动提交机制,运行一行就会提交,所以需要手动关闭它的自动提交:
start transaction;
二、事务隔离级别
隔离级别有四个:
读未提交:read uncommitted(最低的隔离级别)
// 事务A可读到事务B未提交的数据。存在脏读现象。这种隔离级别是理论的。
读已提交:read committed
//事务A只能读取到事务B已提交的数据。解决了脏读现象。不可重复读取数据(可能A事务刚开始读到3条,下一次就读到4条)。该级别是oracle默认的隔离级别,读到的数据很真实。
可重复读:repeatable read
//事务A开启之后,读取到B的数据都是一样的,即使B事务提交新的。解决了不可重复读的问题,可能会出现幻影问题,数据不够真实。
序列化读:serializable(最高的隔离级别)
// 效率最低,各个事务需要排队执行,不能并发,每次读到的数据都是最真实的。
演示:
//查看隔离级别:
select @@transaction_isolation;
//设置隔离级别,需要设置后关闭并重新进入数据库
set global transaction isolation level 隔离级别;
演示结果:在read uncommitted的隔离级别下,事务B只要执行了对表的操作,事务A都可以读取到表的改动。而在read committed的隔离级别下,只有事务B执行了commit,之前的所有操作上传到数据库中的表,事务A才能读取到这些操作。
在repeatable read的隔离级别下,事务A中读到的结果总是跟它第一次读到的结果一样,不管事务B怎么进行提交。除非事务A进行提交,A才会新读到数据。
在serializable级别下,事务A如果对表进行了操作,事务B对同一张表进行操作就会卡住不动,除非事务A提交或回滚结束事务。