MySQL事务

111 阅读5分钟

MySQL事务

默认MySQL的事务是自动提交的,也就是说,当执行完一条DML语句时,MySQL会立即隐式的提交事务。

一、事务四大特性:

1. 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
2. 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
3. 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
4. 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

上述就是事务的四大特性,简称ACID。

四大特性通俗解释:

1. 原子性
    
    在一个事务中可能会有多个增删改操作,
    如果有一个操作失败了,其他成功的操作就失效了,必须是全部操作都成功,操作才能生效。

2. 一致性:

    两个事务ABA事务减去小明的工资1000B事务增加小红的工资1000,那么在提交事务后,
    小明的工资必定少了1000,小红的工资必定增加1000,不能出现一方工资减少,另一方工资却没增加情况。
    (也就是必须遵循守恒定律)

3. 隔离性
    
    两个事务A,BA事务和B事务并发操作的情况下执行操作的时候,互不影响。

4. 持久性

    事务一旦提交或者回滚,数据就永久的保存到磁盘上或者从磁盘中消失了。

二、并发事务问题

1. 赃读:一个事务读到另外一个事务还没有提交的数据
2. 不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
3. 幻读:一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了 "幻影"。

通俗解释

1. 脏读

    AB两个事务同时操作数据,A事务中,查询小明的工资为1000, 查询完毕后,
    B事务正好给小明增加了1000工资,A事务再次查询的时候发现小明的工资变成了2000,这就是脏读。
   (注意点:脏读是B事务还没有在事务提交的前提下,对数据做了更改,就已经影响到了A事务查询数据的结果了)。
   
解决脏读就是解决B事务对数据做了修改后,还没有提交事务的情况下,A事务查询到的数据还是之前查询到的数据

脏读解决方法:将事务隔离级别设置为Read committed
   
2. 不可重复读

    AB两个事务同时操作数据,A事务中,查询小明的工资为1000, 查询完毕后,
    B事务正好给小明增加了1000工资,并且B事务进行了提交事务,提交事务后,A事务再去查询小明的工资,发现小明的工资变成了2000。这就是不可重复读。
   (注意点:不可重复读是B事务在提交事务后的前提下,对数据做了更改,才会影响到了A事务查询数据的结果)。
   
解决不可重复读就是解决B事务对数据做了修改后,还提交了事务的情况下,A事务查询到的数据还是之前查询到的数据

不可重复读解决方法:将事务隔离级别设置为Repeatable Read

3. 幻读

   AB两个事务同时操作数据,A事务中,查询数据表的数据, 查询完毕后(假如只查到两条数据)
   B事务这个时候插入了一条数据,插入完毕后,A事务也打算插入一条数据,
   但是第三条数据B事务已经插入了,A不知情。那么插入的时候就会报错,提示数据已存在,
   这个时候A事务再去查数据,还是两条数据,看不到第三条B事务已经插入的数据,
   (为什么看不到B事务插入的第三条数据,是因为之前已经解决了不可重复读的问题,也就是B事务在执行了插入操作后,并提交了事务,对A事务还是不可见的),
   那这个时候就出现了幻读,即插入不了数据,又查询不到数据。
   
幻读解决方法:将事务隔离级别设置为Serializable

三、事务隔离级别

为了解决并发事务所引发的问题,在数据库中引入了事务隔离级别。主要有以下几种:

隔离级别脏读不可重复读幻读
Read uncommitted
Read committed×
Repeatable Read(默认)××
Serializable×××

1. 查看事务隔离级别

SELECT @@TRANSACTION_ISOLATION;

2. 设置事务隔离级别

SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }


注意:事务隔离级别越高,数据越安全,但是性能越低。

3. SESSION 和 GLOBAL的区别

1. MySQL的session和global一般用来对事务配置进行暂时设置,
不管设置的是session还是global,当数据库服务重启,事务的配置就会失效,重新回到默认的事务配置。

2. session和global体现在新的设置生效的范围。

    session:当前会话,也就是当前连接立即生效。
    (如果释放当前连接后(关闭窗口后),在重新打开一个会话(窗口),配置就会失效。

    global:全局,不包含当前连接,之后新获取的连接都会生效。
    (只有重启mysql服务,配置才会失效)

因此修改事务隔离级别设置时,需要保持打开的窗口一致,每个窗口都要执行一下修改语句

(针对session立即生效,如果是global的话,需要重新打开一个窗口)