事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
举个例子,去银行转账的操作就是一个事务,比如A要转1000块给B,但是B的账户出了些问题导致转账失败,那么A拿出来的1000块钱可不能凭空消失啊,所以要将事务进行回滚(可以理解成初始化),回到刚开始的状态,也就是把拿出来的1000块钱再重新塞回去即可。
默认在MySQL中使用DML语句时是自动提交事务操作的。
事务操作
1.查看事务是否自动提交
select @@autocommit
查询结果为1就是自动提交,也可以通过set的方式改为0变成手动提交。
2.开启一个事务
start transaction
后面跟上你要执行的一个代码块,如果报错了,执行回滚操作即可(后面会介绍)
3.执行操作
commit
在autocommit = 0或你开启了一个事务的时候,你执行的语句都不会自动提交,要手动执行以下commit指令才可以生效。
4.回滚操作
rollback
发现报错或者其他事故,使用这条语句进行回滚,可以理解成撤消。但是这个撤消必须在commit生效前才可以回滚,就像盆里的水,倒出去了想要撤消拿回来可就难了。
事务的四大特性
原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
事务的并发问题
脏读:一个事务读到另外一个事务还没有提交的数据。
不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
幻读:一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了“幻影”。
按照博主的理解,实际上就是AB两个事务的commit时机不同导致的上述问题。那么该怎么解决呢?
事务隔离级别
首先我们来了解一下事务的隔离级别:
表中的√表示这个问题会出现,×则表示不会出现。其中Repeatable Read是MySQL的默认隔离级别,而Oracle的默认隔离级别是Read uncommitted。
查看事务隔离级别
select @@transaction_isolation
设置事务隔离级别
set session transaction isolation level read uncommitted
这里是将事务的隔离级别变成了read uncommitted,这里的session代表的是当前会话的隔离级别,如果想要全局都改变的话,可以使用global,即把session替换为global。
注意:数据的隔离级别越高,安全性越好,但是性能越低。
至于脏读、不可重复读、幻读的问题,内容比较多,之后有精力再开一个新的专题详细介绍吧。
至此数据库的事务内容也结束了,阶段性成果++!