MYSQL基础知识之事务

1、概念

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,所以这些操作要么同时成功,要么同时失败。

事务的四大特性:

原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败;

一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态;

隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行;

持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变是永久的。

MySQL的事务默认是自动提交的,当执行一条DML语句,MySQL会隐式的提交事务

 

2、手动提交事务

 查看是否自动提交事务:select @@autocommit;

 其中1为自动提交事务,0为手动提交事务。

事务提交方式改为手动提交:set @@autocommit=0;

提交事务:commit; 

回滚事务:rollback; 

 在另外一个会话里查询该表,显示数据并未被UPDATE,原因就是还没进行事务提交。(注意要再另外一个窗口查看数据)

提交事务后才正真更新

自动提交事务中手动提交:

当我们不想把自动提交事务改为手动提交事务,而防止自动提交事务出错时,可以在自动提交事务中,手动开始事务。

语法:start transaction 或 begin;

 在另一个窗口查看数据,可看到数据未更新

 再在原窗口执行COMMIT;后即可看到数据已更新

 

3、并发事务问题

当有两个或两个以上的事务同时执行、提交事务时,可能会引发并发事务问题,并发事务常见的问题有:

脏读:一个事务读取了另一个事务还没提交的数据;

不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,这种称为不可重复读;

幻读:一个事务按照条件查询数据时,没有对应的数据行,但在插入数据时,这行数据已经存在了,好像出现了“幻影”。

 

4、事务隔离级别

为了解决事务并发问题,我们设置事务的隔离级别,不同的隔离级别可以解决不同的事务并发问题,如下表:

 查看事务的隔离级别:select @@transaction_isolation;

 设置事务隔离级别:

set [session | global] transaction isolation level {read uncommitted | read committed | repeatable read | serializable}

其中session是当前会话窗口有效,global是对当前客户端的所有会话窗口有效。

 

4.1、Read uncommitted(读未提交)

设置事务隔离级别为Read uncommitted:set session transaction isolation level read uncommitted;

 窗口1:

 窗口2:

 再看窗口1:

 结论:在窗口2更新数据事务后,没有提交事务,但在窗口1查看数据发现数据已经更新了,这就属于脏读了

 

4.2、Read committed(读已提交,可解决脏读问题)

设置事务级别为read committed

窗口1:

 窗口2:

 此时窗口2未提交,看窗口1

 可看到数据未更新

窗口2COMMIT;后再看窗口1:

窗口2:

 窗口1:

 可看到数据已更新

结论:Read committed隔离级别可以解决脏读问题。但注意解决不了不可重复读和幻读

 

4.3、Repeatable Read(可重复读)

为了解决不可重复读,把事务隔离级别改为Repeatable Read

窗口1:

 窗口2:

 窗口1:

 窗口1:

 在窗口1开启一个事务并查询数据表的数据后,在窗口2中开启事务并更新提交事务,再返回窗口1中查询数据表发现查询结果和之前查询一样,这就叫可重复读,在窗口1中提交第一个事务后,再次查询数据表数据发现数据发生了改变。这就解决了并发问题的不可重复读。

Repeatable Read可以解决脏读和不可重复读,但解决不了幻读:

窗口1:

窗口2:

 窗口1:

 在窗口1中开启事务并查询id为3的数据,发现数据表中没有id为5的数据,在窗口2中,开启事务并添加id为5的数据并提交事务后,在窗口1中添加id为5的数据,发现已经有id为5的数据了,但查询id为5的数据时,发现没有查到,这就是幻读。

 

4.4、Serializable(串行化,可避免脏读、不可重复读、幻读的发生)

为了解决幻读并发事务问题,可以把事务隔离级别改为Serializable

窗口1:

 窗口2:

在窗口1查询id为6的数据,因为没有id为6的数据,所以没有查询到,在窗口2中插入id为6的数据,发现一直没有插入成功,这是因为在窗口1中已经开启了一个事务,需要窗口1开启的事务结束后,才能执行窗口2的事务,这样就解决了幻读问题。

 

posted @ 2023-04-07 00:13  城为唯一  阅读(44)  评论(0编辑  收藏  举报