当前位置: 首页 > backend >正文

MySQL 事务(二)

文章目录

  • 事务隔离性理论
    • 理解隔离性
    • 隔离级别
  • 事务隔离级别的设置和查看
  • 事务隔离级别
    • 读未提交
    • 读提交(不可重复读)

在这里插入图片描述

事务隔离性理论

  1. 理解隔离性
    MySQL服务可能会同时被多个客户端进程(线程)访问,访问的方式以事务方式进行
  2. 一个事务可能由多条SQL构成,也就意味着,任何一个事务,都有执行前,执行中,执行后的阶段。而所谓的原子性,其实就是让用户层要么看到执行前,要么看到执行后执行中出现问题,可以随时回滚。所以单个事务,对用户表现出来的特性,就是原子性。
  3. 但,毕竟所有事务都要有个执行过程,那么在多个事务各自执行多个SQL的时候,就还是有可能会出现互相影响的情况。比如:多个事务同时访问同一张表,甚至同一行数据。
  4. 数据库中,为了保证事务执行过程中尽量不受干扰,就有了一个重要特征:隔离性
  5. 数据库中,允许事务受不同程度的干扰,就有了一种重要特征:隔离级别

理解隔离性

  1. sql操作都是具有原子性的,update和select,谁先来谁就先跑
  2. 每一个人都只能看到自己活着时候世界所对应的样子,所以我们时间线一直在延展的时候,每个人看到的世界都应该是不一样的,这才符合自然规律,人与人之间具有隔离性,因此让每一个事务都看到最新的数据是不合理的,而是应该让每一个事务在他到来时看到他应该看到的数据。这就是隔离性的体现。
  3. 隔离性具体要隔离到什么程度,我们就有了隔离级别的概念
  4. 隔离性就是你可以看到你出生后的时间线的内容,不能看到你出生前的内容
  5. 隔离级别是你试衣服的时候要进试衣间,试鞋子就不用进试衣间

在这里插入图片描述

隔离级别

  1. 读未提交:在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际公司不会用这种),这种相当于没有隔离级别
  2. 读提交:一个事务commit之后,另一个事务可以看到这个事务的提交结果
  3. 可重复读:相当于一个事务做完操作后,另一个事务也做完操作后,两个事务都关闭后,重新启动事务才能看到结果,在操作的途中是看不到结果的,类比于两个小孩在浑浊的水中潜水,一个小孩要确认另一个小孩是否还在潜水要浮上水面才能知道结果,这是MySQL默认的隔离级别,在操作的途中看到的结果是相同的
  4. 串行化:事务最高的隔离级别,一个mysql执行完成后另一个mysql才能执行,会影响效率
  5. 隔离,基本都是通过锁实现的,不同的隔离级别,锁的使用是不同的

上面四种隔离级别关注的场景都是当有一个人在进行写的时候另一个人来读 (读写并发),读读的场景都用的是串行化,一个任务进行完才能进行下一个任务

事务隔离级别的设置和查看

1. 只影响当前事务的隔离级别,mysql会默认使用session的隔离级别
2. 全局的隔离级别对所有的事务都影响,全局的改了,当前会话的和另一个事务的都会改变(在重新登入后更改)

SELECT @@session.tx_isolation; 
--查看会话(当前)全局隔级别(默认用全局的初始化)
set global transaction isolation level READ UNCOMMITTED; 
-- 查看 
mysql> SELECT @@global.tx_isolation; 
--查看全局隔级别 
+-----------------------+ 
| @@global.tx_isolation | 
+-----------------------+ 
| REPEATABLE-READ       | 
+-----------------------+ 
1 row in set, 1 warning (0.00 sec) mysql> SELECT @@session.tx_isolation; 
--查看会话(当前)全局隔级别(默认用全局的初始化)
+------------------------+ 
| @@session.tx_isolation | 
+------------------------+ 
| REPEATABLE-READ        | 
+------------------------+ 
1 row in set, 1 warning (0.00 sec) mysql> SELECT @@tx_isolation; 
--默认同上,跟上面的一个是同一个意思 
+-----------------+ 
| @@tx_isolation  | 
+-----------------+ 
| REPEATABLE-READ |
+-----------------+ 
1 row in set, 1 warning (0.00 sec) --设置 
-- 设置当前会话 or 全局隔离级别语法 
// transaction 事务
// isolation 隔离
SET [SESSION | GLOBAL] transaction isolation  level
// 读可不可提交,读可提交,可重复读,串行化
{READ UNCOMMITTED | READ COMMITTED | 
REPEATABLE READ | SERIALIZABLE} --设置当前会话隔离性,另起一个会话,看不多,只影响当前会话 
mysql> set session transaction isolation level serializable; -- 串行化 
Query OK, 0 rows affected (0.00 sec) mysql> SELECT @@global.tx_isolation; --全局隔离性还是RR 
+-----------------------+ 
| @@global.tx_isolation | 
+-----------------------+ 
| REPEATABLE-READ       | 
+-----------------------+ 
1 row in set, 1 warning (0.00 sec) mysql> SELECT @@session.tx_isolation; --会话隔离性成为串行化 
+------------------------+ 
| @@session.tx_isolation | 
+------------------------+ 
| SERIALIZABLE           | 
+------------------------+ 
1 row in set, 1 warning (0.00 sec) mysql> SELECT @@tx_isolation; --同上 
+----------------+ 
| @@tx_isolation | 
+----------------+ 
| SERIALIZABLE   | 
+----------------+ 
1 row in set, 1 warning (0.00 sec) --设置全局隔离性,另起一个会话,会被影响 
mysql> set global transaction isolation level READ UNCOMMITTED; 
Query OK, 0 rows affected (0.00 sec) mysql> SELECT @@global.tx_isolation; 
+-----------------------+ 
| @@global.tx_isolation | 
+-----------------------+ 
| READ-UNCOMMITTED      | 
+-----------------------+ 
1 row in set, 1 warning (0.00 sec) mysql> SELECT @@session.tx_isolation; 
+------------------------+ 
| @@session.tx_isolation | 
+------------------------+
| READ-UNCOMMITTED       | 
+------------------------+ 
1 row in set, 1 warning (0.00 sec)mysql> SELECT @@tx_isolation; 
+------------------+ 
| @@tx_isolation   | 
+------------------+ 
| READ-UNCOMMITTED | 
+------------------+ 
1 row in set, 1 warning (0.00 sec)-- 注意,如果没有现象,关闭mysql客户端,重新连接。

设置当前事务的隔离级别为读提交

在这里插入图片描述

事务隔离级别

读未提交

  1. 脏读:一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,两个事务并发执行
  2. 几乎没有加锁,虽然效率高,但是问题太多,严重不建议采用
--终端A 
-- 设置隔离级别为 读未提交 
mysql> set global transaction isolation level read uncommitted; 
Query OK, 0 rows affected (0.00 sec) --重启客户端
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   | 
+------------------+ 
| READ-UNCOMMITTED | 
+------------------+ 
1 row in set, 1 warning (0.00 sec)mysql> select * from account;
+----+--------+----------+
| id | name   | blance   | 
+----+--------+----------+ 
| 1  | 张三   | 100.00   | 
| 2  | 李四   | 10000.00 | 
+----+--------+----------+ 
2 rows in set (0.00 sec) mysql> begin;                   --开启事务 
Query OK, 0 rows affected (0.00 sec)mysql> update account set blance=123.0 where id=1;  --更新指定行 
Query OK, 1 row affected (0.05 sec) 
Rows matched: 1  Changed: 1  Warnings: 0--没有commit哦!!!--终端B mysql> begin;
mysql> select * from account;
+----+--------+----------+ 
| id | name   | blance   | 
+----+--------+----------+ 
| 1 | 张三    | 123.00   | --读到终端A更新但是未commit的数据[insert,delete同样] 
| 2 | 李四    | 10000.00 | 
+----+--------+----------+ 
2 rows in set (0.00 sec) 

读提交(不可重复读)

在这里插入图片描述

-- 终端A 
mysql> set global transaction isolation level read committed; 
Query OK, 0 rows affected (0.00 sec) 
--重启客户端 
mysql> select * from account; --查看当前数据 
+----+--------+----------+ 
| id | name   | blance   | 
+----+--------+----------+ 
| 1  | 张三   | 123.00   | 
| 2  | 李四   | 10000.00 | 
+----+--------+----------+ 
2 rows in set (0.00 sec) mysql> begin; --手动开启事务,同步的开始终端B事务 
Query OK, 0 rows affected (0.00 sec) mysql> update account set blance=321.0 where id=1; --更新张三数据 
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1 Changed: 1 Warnings: 0 --切换终端到终端B,查看数据。 mysql> commit; --commit提交! 
Query OK, 0 rows affected (0.01 sec) --切换终端到终端B,再次查看数据。 --终端B 
mysql> begin; --手动开启事务,和终端A一前一后 
Query OK, 0 rows affected (0.00 sec) mysql> select * from account; --终端A commit之前,查看不到 
+----+--------+----------+ 
| id | name   | blance   | 
+----+--------+----------+ 
| 1  | 张三   | 123.00   | --老的值 
| 2  | 李四   | 10000.00 | 
+----+--------+----------+ 
2 rows in set (0.00 sec) --终端A commit之后,看到了!
--but,此时还在当前事务中,并未commit,那么就造成了,同一个事务内,同样的读取,在不同的时间段(依旧还在事务操作中!),读取到了不同的值,这种现象叫做不可重复读(non reapeatable read)!!(这个是问题吗??) 
mysql> select *from account; 
+----+--------+----------+ 
| id | name   | blance   | 
+----+--------+----------+ 
| 1  | 张三   | 321.00   |  --新的值 
| 2  | 李四   | 10000.00 | 
+----+--------+----------+ 
2 rows in set (0.00 sec) 

不可重复读会出现什么问题呢?
两个事务都同时启动,一个事务提交了(关闭了),另一个运行的事务(查询)看到第一个事务的提交结果是不合理的,两个事务都应该是原子的

不可重复读会造成问题吗?会造成什么后果?
比如说小王要把tom的工资重3200改到4500,而小张负责工资表发放奖品的任务,小张要进行查询的任务,当事务运行到3000到4000奖品的查询时,查到了tom,之后小王提交了事务,在4000到5000奖品的查询时,又查到了tom,这在公司就出现了问题

在这里插入图片描述
所以我们不应该让我们的用户在实际操作的时候,两个正在执行的事务一方能够读到另一方的提交。所以虽然读提交比读未提交隔离级别高,但是我们也不推荐!因为会导致上述的不可重复读的问题!!

http://www.xdnf.cn/news/5838.html

相关文章:

  • 在 Qt Creator 中为 QDockWidget 设置隐藏和显示按钮
  • 中电金信参编的国家标准《信息技术 中间件 消息中间件技术要求》正式发布
  • 【爬虫】DrissionPage-1
  • 【TDengine源码阅读】#if defined(__APPLE__)
  • (C语言)超市管理系统(测试版)(指针)(数据结构)(二进制文件读写)
  • Android支持离线功能的复杂业务场景(如编辑、同步):设计数据同步策略的解决方案
  • 基于大模型的腰椎管狭窄术前、术中、术后全流程预测与治疗方案研究报告
  • 数据服务包括哪些内容?一文讲清数据服务模块的主要功能!
  • 【HarmonyOs鸿蒙】七种传参方式
  • IoTDB集群的一键启停功能详解
  • 裸机开发的核心技术:轮询、中断与DMA
  • PowerShell 实现 conda 懒加载
  • MUSE Pi Pro 编译kernel内核及创建自动化脚本进行环境配置
  • 什么是IoT长连接服务?
  • 最终一致性和强一致性
  • Datawhale 5月coze-ai-assistant 笔记1
  • 免费实用的远程办公方案​
  • Spark的缓存
  • 麦肯锡110页PPT企业组织效能提升调研与诊断分析指南
  • 从0到1上手Kafka:开启分布式消息处理之旅
  • ES6中的解构
  • 【SpringBoot】集成kafka之生产者、消费者、幂等性处理和消息积压
  • c语言第一个小游戏:贪吃蛇小游戏08(贪吃蛇完结)
  • 本地的ip实现https访问-OpenSSL安装+ssl正式的生成(Windows 系统)
  • 职坐标AIoT开发技能精讲培训
  • Tomcat的调优
  • 【用「概率思维」重新理解生活】
  • RabbitMQ 核心概念与消息模型深度解析(二)
  • 开源模型应用落地-qwen模型小试-Qwen3-8B-融合VLLM、MCP与Agent(七)
  • 六、Hive 分桶