mysql事务隔离级别实战

2021/05/18 mysql

docker安装Mysql

拉取mysql 8的镜像

docker pull mysql:8

运行 mysql 容器

docker run -itd --name docker-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -v /Users/songtao/Docker/Mysql:/var/lib/mysql mysql

启动 mysql 容器

docker start docker-mysql

查看容器

docker ps

进入容器

docker exec -it cd2676 bash

登录mysql

mysql -u root -p

事务隔离级别使用演示

MySQL 命令行的默认配置中事务都是自动提交的,即执行SQL语句后就会马上执行 COMMIT 操作。如果要显式地开启一个事务需要使用命令:START TARNSACTION

可以使用下面命令来设置隔离级别

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

下面使用两个命令行来模拟两个线程开启事务

查看当前进程的事务隔离级别

select @@SESSION.TRANSACTION_ISOLATION;

查看系统设置的事务隔离级别

select @@global.TRANSACTION_ISOLATION;

READ UNCOMMITTED (读未提交)

在一个事务中修改值还未提交,在另一个事务中就可以读取到该值

image-20210517195136438

image-20210517195241771

READ COMMITTED (读已提交)

image-20210518095322257

image-20210518095356737

虽然避免了读未提交,但是却出现了,一个事务还没有结束,就发生了 不可重复读问题。

3 REPEATABLE READ (可重复读)

image-20210518102009797

image-20210518102113297

一个事务对数据库进行操作,这种操作的范围是数据库的全部行,然后第二个事务也在对这个数据库操作,这种操作可以是插入一行记录或删除一行记录,那么第一个是事务就会觉得自己出现了幻觉,怎么还有没有处理的记录呢? 或者 怎么多处理了一行记录呢?

幻读和不可重复读有些相似之处 ,但是不可重复读的重点是修改,幻读的重点在于新增或者删除

3.1 幻读

幻读,并不是说事务中多次读取获取的结果集不同,幻读更重要的是某次的 select 操作得到的结果集所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 记录不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,如同产生了幻觉。

image-20210518134412074

image-20210518134433298

3.2 Lock wait(锁等待)

image-20210518140412187

image-20210518140429377

由于id = 1 的这条数据的写锁已经被SESSION 1 获取,另一个事务再更新这条数据的话就会出现锁等待的情况。

3.3 Dead lock(死锁)

image-20210518103936651

image-20210518103954194

两个事务之间相互等待,导致死锁。

参考

https://juejin.cn/post/6847902219241848845

https://snailclimb.gitee.io/javaguide/#/docs/database/%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB(%E5%9B%BE%E6%96%87%E8%AF%A6%E8%A7%A3)

Search

    Post Directory