一、概念
事务指的是一组操作的集合,它是一个不可分割的工作单元,它会把整个集合中的所有操作作为一个整体一起向系统提交或者撤销操作的请求,也就是这些操作要么同时成功,要么同时失败。
事务通常用于在需要操作多条记录或多张表的情况下,为了避免在执行过程中出现异常行为导致数据一致性被破坏,这时候我们就需要开启事务。
比如我们的银行转账的问题:
a转账给b,a的银行账户减少100,而b的银行账户要增加100,这一组操作必须在一个事务范围内,要么同时成功,要么都失败。如果没有使用事务的情况,如果a在转账给b后,抛出了异常,那么a的银行账户金额减少了,但是b的银行账号并没有增加,这就会产生问题。
二、事务相关操作
1.查看事务统计方式
语法:
SELECT @@autocommit;
其中值1表示自动提交事务,0表示手动提交事务。
2.设置事务提交方式
语法:
SET @@autocommit = 0; # 设置为手动提交事务
SET @@autocommit = 1; # 设置为自动提交事务
3.提交事务
我们把事务提交方式修改为手动提交之后,我们需要每次执行SQL之后手动提交事务,否则SQL语句不生效。
语法:
COMMIT;
我们设置默认的测试数据如下所示:
我们修改ID为3的金额,但现在我们的事务提交方式是手动的,所以不会修改数据。
我们在应该执行SQL语句之间,手动加上COMMIT语句,手动提交事务。
最后我们刷新数据,发现金额已经被修改了。
4.回滚事务
当我们执行事务的过程中碰到了异常导致系统终止,可以使用rollback让事务回滚,恢复到事务开始执行之前的状态。
SQL语句:
update t_employee set money=money+100 WHERE id=3;
update t_employee set money=money-100 WHERE id=6;
ROLLBACK;
执行SQL语句之后,我们刷新数据表,发现并没有修改数据表,我们的回滚操作生效了。
5.开启事务
我们除了可以以关闭自动提交事务,然后手动commit的方式控制事务以外,还可以通过在SQL开始执行之前,先执行START TRANSACTION; 或 BEGIN; 然后执行SQL,最后commit的方式控制事务。
语法:
START TRANSACTION; 或 BEGIN;
SQL语句:
#开启事务
start TRANSACTION;
#执行sql
update t_employee set money=money+100 WHERE id=3;
update t_employee set money=money-100 WHERE id=6;
#提交事务
commit;
执行SQL语句之后我们发现数据被修改成功了。
三、事务的四个特性
原子性:事务是不可分割的操作单元,要么同时成功,要么同时失败。
一致性:事务完成时,必须使所有数据都保存一致状态。
隔离性:各个事务之间的操作是互相独立的,不受外部的影响。
持久性:事务一旦提交或回滚,它对数据库的数据改变就是永久的。
四、事务并发产生的问题
多个事务同时操作某一张表的时候,有可能会产生一些问题。
脏读:一个事务读到另一个事务没有提交的数据。
不可重复读:一个事务先后读取同一条记录,在第一次读取之后,另一个事务提交了对整个记录的修改,第二次读取获取到的记录就不一样。这种两次读取的数据不同,称为不可重复读。
幻读:一个事务按照条件查询数据时,没有查询到对应的数据,但是这个时候另一个事务提交了对应的数据,这个时候我们再插入数据的时候,却发现了这个数据已经存在,这种情况就好像出现了幻影,我们称这种行为为幻读。
五、事务的隔离级别
为了解决事务并发产生的问题,我们在数据库中引入了事务隔离级别。
常见的事务隔离级别如下图所示:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
Read uncommitted(读未统计) | 会 | 会 | 会 |
Read committed(读已提交) | 不会 | 会 | 会 |
Repeatable Read(可重复读) | 不会 | 不会 | 会 |
Serializable(串行) | 不会 | 不会 | 不会 |
MySQL的默认隔离级别是Repeatable Read,可能会产生幻读的问题。
查看事务隔离级别:
select @@TRANSACTION_ISOLATION;
设置事务隔离级别语法:
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED |
READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
SQL语句:
#设置事务隔离级别为串行化
set session TRANSACTION ISOLATION level SERIALIZABLE;
#查看事务隔离级别
select @@TRANSACTION_ISOLATION;