mysql事务
mysql的InnoDB引擎支持事务,它用COMMIT、SAVEPOINT及ROLLBACK支持事务处理。
事务就是一个原子性操作,一个完整的业务逻辑。
事务的特点是四点,简称ACID。原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
一、事务的情景举例
试想一下下面的情景:
A向B转了100元,那么
A的账户-100
B的账户+100
这就是一个完整的业务逻辑。对于在mysql中就是两个update语句,它们要么同时成功,要么同时失败,是不可再分的。
二、事务是DML语句专有的
只有DML语句才有事务这么一说,其它语句与事务无关。
DML语句指的是数据操纵语句,包括update、insert、delete;而DDL语句指的是数据定义语句,包括创建数据库中的各种对象——表、视图、索引、同义词、聚簇等。
只要你的操作涉及到数据的增删改,那就意味着一定要考虑安全问题。
三、事务的开始和结束
InnoDB存储引擎中,提供了一组用于记录事务性活动的日志文件。当事务的执行过程中,每一条DML语句都会记录到这个日志文件里。如果COMMIT提交的话,日志文件就会被清空。
- 开启事务:start transaction;
- 提交事务:commit;
- 回滚事务:rollback;
有案例如下:
在初始状态下,某张表中没有任何rows的。
// 1.开始事务
start transaction;
// 2.写DML语句
insert ...
insert ...
这里我们如果进行select语句查看表中数据时,会发现表中已经存有了数据;此时如果选择执行
// 3.回滚事务
rollback;
再次查询表中数据,会发现数据已经没了。
如果你执行
// 3.提交事务
commit;
在已经提交了的情况下,你再使用rollback,也无法使得数据还原到事务前的状态。
注意,在没有start transaction的情况下,你直接输入DML语句,就相当于是被commit了的事务,只不过它是被默认执行的;此时你执行rollback不会有任何用。
这种自动提交实际上是不符合我们的开发习惯的,因为一个业务通常是需要多条DML语句执行才能完成的,为了保证数据的安全,必须要求同时成功之后再提交,所以不能执行一条就提交一条。
四、事务的隔离级别
重点说下事务的隔离性(isolation)。
事务和事务之间的隔离级别主要有4个级别。
- 1.读未提交:read uncommitted,事务A可以读到事务B未提交的数据。存在的问题是脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。这种隔离级别基本没有数据库会用。
- 2.读已提交:read committed,事务A可以读到事务B已提交的数据。这种隔离级别解决了脏读的现象。存在的问题是不可重复读取数据:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。这也是oracle数据库的默认隔离级别。
- 3.可重复读:repeatable read,事务A开启之后,不管是多久,每一次在事务A中读取到的数据都是一致的。即使事务B将数据已经修改,并且提交了,事务A读取到的数据还是没有发生改变。它存在的问题是可能会出现幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。这是mysql的默认隔离级别。
- 4.序列化(串行化):serializable,所有的事务都是串行处理的,这样牺牲了效率。
隔离级别以此从低到高。