Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL并发事务及隔离级别

MySQL并发事务问题及隔离级别操作演示(附详细图文)

作者:学Java的小半

在高并发环境下,数据库事务操作可能引发脏读、不可重复读、幻读和丢失更新等数据一致性问题,这篇文章主要介绍了MySQL并发事务问题及隔离级别操作演示的相关资料,需要的朋友可以参考下

举例演示了MySQL的并发事务问题,以及四个事务隔离级别的区别,例子直接跳转标题3.

1.并发事务问题

(1)脏读 (Dirty Read)

(2)不可重复读 (Non-repeatable Read)

(3) 幻读 (Phantom Read)

2.事务隔离级别

我们可以通过给事务设置隔离级别来解决上述并发问题

MySQL 提供了四种隔离级别

隔离级别脏读不可重复读幻读说明
READ UNCOMMITTED (读未提交)可能可能可能最低隔离级别,性能最好但问题最多
READ COMMITTED (读已提交)可能可能不可能只读取已提交的数据,Oracle默认级别
REPEATABLE READ (可重复读)可能不可能不可能MySQL默认级别,确保同一事务内读取一致
SERIALIZABLE (串行化)不可能不可能不可能最高隔离级别,性能最差但最安全

事务隔离级别的相关操作

查看当前隔离级别

SELECT @@transaction_isolation;
-- 或
SHOW VARIABLES LIKE 'transaction_isolation';

设置隔离级别

可以设置全局级别或会话级别:

-- 设置全局隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 设置下一个事务的隔离级别
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

3.操作演示

(1).准备数据

首先,准备一个简单的数据表做演示

这里是一个简单的账户表

create table account
(
    user_name varchar(20) not null,
    money     double      null,
    id        int auto_increment
        primary key
);

# 添加数据
insert into account values ('jack',8000,1),('mary',8000,2);

因为要演示并发问题,所以,我们直接使用cmd打开两个窗口演示

找到 上面表所在的数据库

(2).脏读

我们先演示,脏读:一个事务读取了另一个未提交事务修改过的数据

先设置左窗口的事务隔离级别为  read uncommitted

set session transaction isolation level read uncommitted ;

然后在左窗开启一个事务,查询一下 account表的数据:

接着在右窗开启一个事务,修改 一下 account表的数据:

注意,这时我们并没有commit 提交右窗修改的数据

但是,我们再在左窗查询 数据,却发现查询到的数据已经修改了

这就体现了脏读问题,右窗的事务,访问到了左窗事务还未提交的数据!

演示完成,别忘了结束两边的事务,再进行后续操作

我们把右窗事务隔离级别修改为 readcommited 就可以避免脏读问题

就是下面 不可重复读的操作演示,不再赘述

右窗:

左窗:

(3.1).不可重复读

右窗事务隔离级别设置为 readcommited

开启一个事务,查询一下数据

在左窗开启一个事务,修改表中数据

左窗还未提交zai再次在右窗查询,发现数据没有变化,也就是解决了 脏读问题

左窗提交数据后再次在右窗查询,发现数据变化了,

在右窗的一个事务过程中,出现了多次读取同一数据但返回不同结果的现象,这就是不可重复读

(3.2).解决不可重复读

 设置右窗事务隔离级别为REPEATABLE READ (可重复读), 开启一个事务,查询当前表数据

左窗还是开启一个事务,修改表中数据,这次我们直接提交!

右窗再次查询表数据,可以看到,这次左窗事务虽然已经提交了修改,但是右窗查询数据还是没变。这样一个事务里就不会出现多次读取同一数据但返回不同结果的现象,这就解决了上面 不可重复的的问题

我们结束右窗事务后,再次查询,则看到了最新数据

(4.1).幻读

右窗不改变隔离级别,依旧为  repeatable read 

开启新事务,查询id为3的信息,当前没有id为3的人,当然查询不到

此时,左窗开启一个事务,插入id= 3的一条数据 ,并直接提交

由于,并发执行,之前右窗没有查询到id= 3的数据,于是也准备插入一条id= 3的数据,但是由于左窗已经插入完成,所以无法插入。如下图

右窗再次查询id为3的信息,但是还是查询不到

像这样右窗这样,查询时查询不到,插入时又认为数据已经存在不让插入 的现象 就叫 幻读

(4.2).解决幻读

设置右窗事务隔离级别为SERIALIZABLE (串行化),开启事务,查询id= 4的数据,没有

左窗开启事务,插入id= 4的一条数据,但是按回车后,却没有运行,这就是因为 右窗事务隔离级别为SERIALIZABLE (串行化)

只能在右窗执行完当前事务的全部操作后,左窗事务才能继续!

左窗:

总结

到此这篇关于MySQL并发事务问题及隔离级别操作演示的文章就介绍到这了,更多相关MySQL并发事务及隔离级别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文