数据库MySQL动手模拟四种隔离级别(要两个客户机)

在这里插入图片描述

以Navicat为客户机A,cmd终端为客户机B

首先要有个数据库和表

打开客户机A

-- 首先要有个数据库
create database company;
use company;

-- 首先要有个表
#建立account表
CREATE TABLE account(
 account_no INT AUTO_INCREMENT PRIMARY KEY,
 account_name VARCHAR(10) NOT NULL,
 balance INT UNSIGNED  #balance不能取负值
);

#向account表插入记录
INSERT INTO account VALUES(null,'李三',1000);
INSERT INTO account VALUES(null,'王五',1000);

动手模拟

脏读现象

读脏数据也称为读未提交的数据 。
原因:由于后一事务读了前一个事务写了但尚未提交的数据引起,称为写—读冲突。
结果:读到有可能要回退的更新数据。

-- 打开MySQL客户机A,执行下面语句。
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT @@transaction_isolation;

在这里插入图片描述

START TRANSACTION;    #开始事务
SELECT * FROM account;

现在客户机A上account表
在这里插入图片描述
cmd终端管理员权限打开,作为客户机B
->要先转到bin文件夹
->root登录
在这里插入图片描述

#显示所有的数据库
show databases;

#在新建的数据库company中创建新用户tempuser
#password:123
#并授予所有权限
CREATE USER 'tempuser'@'localhost' IDENTIFIED BY '123';
GRANT ALL PRIVILEGES ON company.* TO tempuser@localhost with grant option; #创建用户时显示localhost,grant时也要显示
show grants for tempuser@'loaclhost';    #@前不加''@后加
#登录tempuser

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT @@transaction_isolation;

START TRANSACTION;
#cmd中要先
USE company;
UPDATE account SET balance=balance+1000 WHERE account_no=1;

在这里插入图片描述
然后再打开客户机A

SELECT * FROM account;

在这里插入图片描述
MySQL客户机A看到了MySQL客户机B尚未提交的更新结果,造成脏读现象。
客户机A在窗口直接打开account表,由于两个客户机的事务都没有提交,所以,account表中的数据没有变化,'李三’账户的余额仍然是200。
在这里插入图片描述

不可重复读现象

-- 为防止上一个模拟影响本次模拟,打开MySQL客户机B,执行下面语句。
ROLLBACK;
-- 打开MySQL客户机A,执行下面语句。

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT @@transaction_isolation;

START TRANSACTION;
SELECT * FROM account;

在这里插入图片描述
在这里插入图片描述

-- 打开MySQL客户机B,执行下面语句。
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
UPDATE account SET balance=balance+1000 WHERE account_no=1;
COMMIT;

在这里插入图片描述

-- 打开MySQL客户机A,执行下面语句。 
SELECT * FROM account;

在这里插入图片描述
MySQL客户机A在同一个事务中两次执行“SELECT * FROM account;”的结果不相同,造成不可重复读现象。

幻影读现象

-- 打开MySQL客户机A,执行下面语句。
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT @@transaction_isolation;

set autocommit = 0;        # 将自动提交设置为0 不进行自动提交 自动提交将看不到效果 最好两个事务都开启
START TRANSACTION;
SELECT * FROM account;

在这里插入图片描述
在这里插入图片描述

-- 打开MySQL客户机B,执行下面语句。
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
INSERT INTO account VALUES(10,'赵六',3000);
COMMIT;
SELECT * FROM account;

在这里插入图片描述

-- 打开MySQL客户机A,执行下面语句。 
SELECT * FROM account;

在这里插入图片描述

#由于MySQL客户机A检测到account表中不存在account_no=10的账户信息,在MySQL客#户机A继续执行下面INSERT语句。
INSERT INTO account VALUES(10,'赵六',3000);

在这里插入图片描述

运行结果显示account表中确实存在account_no=10的账户信息,但由于REPEATABLE READ(可重复读)隔离级别使用了“障眼法”,使得MySQL客户机A无法查询到account_no=10的账户信息,这种现象称为幻影读现象。
说明:幻影读和不可重复读现象不同之处在于,幻影读现象读不到其他事务已经提交(COMMIT)的行数据,而不可重复读现象读到的是其他事务已经提交(COMMIT)的数据。

避免幻影读现象

-- 打开MySQL客户机A,执行下面语句。
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT @@transaction_isolation;

START TRANSACTION;
SELECT * FROM account;

在这里插入图片描述
在这里插入图片描述

-- 打开MySQL客户机B,执行下面语句。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
INSERT INTO account VALUES(20,'马七',5000);

SELECT * FROM account;

在这里插入图片描述
在这里插入图片描述

-- 打开MySQL客户机B,执行下面语句。
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT @@transaction_isolation;
START TRANSACTION;
INSERT INTO account VALUES(20,'马七',5000);

由于发生了锁等待超时引发的错误异常,事务被回滚,所以account_no=20的账户信息并没有添加到account表中。
在这里插入图片描述

posted @ 2022-10-08 01:19  昔痕  阅读(53)  评论(0编辑  收藏  举报