事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
二、有关事务操作MySQL中的事务是默认的自动提交的,我们可以手动的去关闭 或者开启事务
#查看事务是否自动提交 select @@autocommit; # 等于1 默认自动提交 #设置事务提交方式 set @@autocommit = 0; # 关闭自动提交事务 #也可以直接设置开启事务 start transaction ; #或着 begin ; #提交事务 如果业务操作正常完成就提交事务 commit ; #回滚事务 如果业务操作在执行过程中出现异常 回滚事务保证事务的完整性和正确性 rollback ;三、事务的四大特性(ACID)
原子性(Atomicity) : 事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
一致性 (Consistency) : 事务完成时,必须使所有的数据都保持一致状态。
隔离性(Isolation) : 数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
持久性(Durability) : 事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
四、并发事务问题 1、脏读一个事务读到另一个事务还没有提交的事务。
2、不可重复读一个事务先后读取同一条记录,但两次读取的数据不同。
3、幻读一个事务在按照条件查询数据时,没有这条数据,但是在插入数据时却又发现有这条数据已经存在,好像出现了“幻觉”。
五、事务的隔离级别 1、读未提交(Read uncommitted)可能出现:脏读、不可重复读、幻读;隔离级别最差,性能最高。
2、读已提交(Read committed)可能出现:不可重复读、幻读。
3、可重复读(Repeatable Read(mysql的默认隔离级别))可能出现:幻读。
4、串行化(Serializable)上述并发问题都可解决,隔离级别最高,但是性能最差。
#查看事务隔离级别 select @@transaction_isolation; # REPEATABLE-READ #设置事务的隔离级别 set session transaction isolation level read uncommitted ; set session transaction isolation level read committed ; set session transaction isolation level repeatable read ; set session transaction isolation level serializable ;场景一
在idea中开启两个控制台,设置事务级别为 读未提交隔离级别 并开启事务
控制台1 第一次查询
控制台2 执行如下语句 未提交
控制台1 再次查询
可见在控制台2执行更新操作后,还没提交,控制台1再次执行查询操作时,查询到的数据已经改变了,证实了读未提交发生脏读现象。
场景二在idea中开启两个控制台,设置事务级别为 读已提交隔离级别 并开启事务
控制台1 第一次查询
控制台2 执行如下语句 未提交
控制台1 再次查询
证实了事务的隔离级别设置为读已提交解决了脏读问题
场景三在idea中开启两个控制台,设置事务级别为 读已提交 并开启事务
控制台2 执行如下语句 未提交
控制台1 第一次查询
控制台2 执行commit提交后 控制台1 再次查询结果不同
可见在控制台1在一次事务中,在控制台2更新前后查询到的数据不同,证实了读已提交发生了不可重复读问题
场景四在idea中开启两个控制台,设置事务级别为 可重复读隔离级别 并开启事务
控制台2 执行如下语句 未提交
控制台1 第一次查询
控制台2 执行commit提交后 控制台1 再次查询结果相同
可见在控制台1在一次事务中,在控制台2更新前后查询到的数据不同,证实了可重复读隔离级别解决了不可重复读问题
场景五在idea中开启两个控制台,设置事务级别为 可重复读隔离级别 并开启事务
控制台1 第一次查询 为空
控制台2 执行插入 并提交
控制台1 执行相同的插入sql 发现已经存在 于是就查询,但是又查不到数据
对于控制台1来说就像是“幻觉”一样,证实了可重复读隔离级别发生了幻读问题
场景六在idea中开启两个控制台,设置事务级别为 串行化隔离级别 并开启事务
控制台1 执行查询 为空
控制台2 执行插入 可见操作阻塞
控制台1提交事务后,控制台2才能够完成插入操作
这种阻塞的效果有效的避免了幻读问题,证实了串行化隔离级别解决了幻读问题
总结:实际使用还得根据业务本身去设置隔离级别,隔离级别越高、数据越安全高但性能也越差,隔离级别越低、数据越不安全但性能越好,在设置事务隔离级别时要权衡数据安全和性能。一般情况我们都会采用数据库的默认隔离级别(Repeatable Read)