一、MySQL事务介绍

1、事务的四大特性(简称ACID)

· 原子性(atomicity):原子是不可再切分的,所以事务的原子性是指事务开始后的所有操作要么全部执行,要么全部不执行,不应该有部分执行的情况存在。如果事务在执行过程中出错(包含会话断开、服务宕机)会由undo log(记录数据修改前的状态)回滚到事务开始前的状态。

· 一致性(consistency):事务开始前和结束后,完整性约束没有被破坏。比如A向B转账1000,不应存在A扣除1000后而B没有增加的情况。由redo log(记录数据修改后的状态)来保持一致性。可以说原子性、隔离性、持久性都是为了保障一致性而存在的,一致性也是最终目的。

· 隔离性(isolation):同一个时间内只允许一个事务对同一个数据进行处理,不同事务之间彼此不能有干扰。

· 持久性(durability):事务完成后数据应该落盘,能够用久保存,并且不能再rollback回滚。

2、事务控制语句

需要注意事务通常是针对DML语句而言,因为每个DDL都是单独的事务,如果DML中加有DDL会触发自动提交

start transaction | begin ; #放在DML语句的头部

rollback #放在SQL最后,可以回滚所有事务

commit #放在SQL最后代表提交事务

3、事务的自动提交功能

当数据库设置autocommit=1时(默认为1),即便没有加begin语句开启事务,数据库也会自动开启,并且最后自动进行commit。若涉及到交易场景建议关闭事务的自动提交,但需要注意长事务问题。非交易类的场景可以打开该功能。

二、MySQL隔离级别

1、MySQL的4种事务隔离级别

· 读未提交(read uncommitted):最低的隔离级别,在一个事务中可以读取到另一个事务已修改但尚未提交的结果。该隔离级别容易造成脏读、不可重复读、幻读,所以不建议使用。

· 读已提交(read commited):只有事务提交后,其更新结果才可以被其他事务查询。Oracle、SQL Server等大多数数据库系统的默认隔离级别,但并不是MySQL默认的,所以推荐使用该事务隔离级别。该隔离级别解决了RU级别的脏读问题,但还是会出现不可重复读、幻读。

·可重复读(repeatable read):Innodb引擎的默认隔离级别。事务1反复读取同一份数据,其结果应该总是相同的,即便事务2已经修改了数据并提交,但是在事务1中依然不会有变化。该隔离级别解决了脏读、不可重复读以及大部分幻读的发生。

·串行化(serializable):事务串行化处理,不会出现脏读、幻读、不可重复读的问题,隔离级别最高,但会导致大量的锁超时和锁竞争问题,因此性能最差,也不建议使用。

PS:四个隔离级别逐个解决脏读、不可重复读、幻读的问题

2、脏读、不可重复度与幻读

· 脏读:在事务1中查询到的数据是事务2已经修改过但未提交的,一旦事务2发生回滚,那事务1获取到的数据就是无效的

· 不可重复度:在事务1中对一个数据进行多次查询,因为事务2的修改导致事务1得到的结果是不一样的。

· 幻读:在一个事务更新过程中有其他事务抢先更新了数据,导致最终结果和预想不一致。比如事务1对年龄<30的数据进行修改,事务2在事务1提交之前又新增了一个<30的数据,这个时候事务1提交之后会看到依然有一个<30的数据存在,带来修改失败的幻觉。

PS:不可重复读和幻读比较相似,主要区别在于不可重复读是对原来存在的数据做修改,幻读是新增或删除数据

3、MySQL事务隔离级别的设置

#查看事务隔离级别

show global variables like 'tx_isolation';

#在线设置事务隔离级别

set global tx_isolation='READ-COMMITTED'

#永久生效

vi /etc/my.cnf

tx_isolation=READ-COMMITTED'