数据库隔离级别[通俗易懂]

数据库隔离级别[通俗易懂]数据库隔离级别 如果没有隔离级别会出现的问题 脏读 意思是读取到了事务正在修改的数据,如果事务回滚,那么拿到的数据就是错误的 | 时间 | 事务A | 事务B | | | | | | 1 | 开始事务

数据库隔离级别

数据库隔离级别

如果没有隔离级别会出现的问题

脏读

意思是读取到了事务正在修改的数据,如果事务回滚,那么拿到的数据就是错误的

时间 事务A 事务B
1 开始事务
2 读取quantity为5
3 修改quantity为4
4 开始事务
5 读取到quantity为4
6 发生错误,回滚,quantity为5
7 提交事务

在按照正常逻辑quantity应该为5

不可重复读

时间 事务A 事务B
1 开始事务
2 读取quantity为5
3 开始事务
4 修改quantity为4
5 提交事务
6 读取quantity为4
7 提交事务

在同一个事务内,两次读取同一个数据产生不一致

幻读

时间 事务A 事务B
1 开始事务
2 更新所有行的quantity为100
3 开始事务
4 插入一行quantity为5
5 提交事务
6 查询所有行的quantity
7 提交事务

当一个事务内更新所有行后,另一个事务插入了新行,当再次查看记录时,发现有未更新的记录,好像幻觉一样

丢失更新

第一种情况:

时间 事务A 事务B
1 开始事务
2 查询到quantity为10
3 开始事务
4 查询到quantity为10
5 更新quantity为11
6 提交事务
7 更新quantity为9
8 事务回滚,quantity为10

可以看到,回滚的事务把正常事务的数据覆盖了,正常事务的数据丢失了

第二种情况:

时间 事务A 事务B
1 开始事务
2 查询到quantity为10
3 开始事务
4 查询到quantity为10
5 更新quantity为9
6 提交事务
7 更新quantity为11
8 提交事务

这种情况是事务在执行期间,其他事务对数据进行了修改,那么当前事务拿到的数据就是错的,对错的数据进行更新,那也就没有意义了

解决方法

对于脏读、不可重复读、幻读

我们可以使用数据库提供的隔离级别来避免以上情况

隔离级别 脏读 不可重复读 幻读
Read-Uncommitted(读取未提交的内容)
Read-Committed(读取已提交的内容) ×
Repeatable-Read(可重读) × ×
Serializable(串行化) × × ×

Mysql的默认隔离级别为Repeatable-Read,可以通过以下命令查看

SELECT @@global.tx_isolation;--查看全局隔离级别
SELECT @@session.tx_isolation;--查看当前连接的隔离级别

代码100分

修改隔离级别

代码100分SET @@global.tx_isolation="Read-Committed"
SET @@session.tx_isolation="Read-Committed"
--或
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE

对于丢失更新

使用悲观锁

悲观锁主要有共享锁(读锁)和排他锁(写锁)

  • 共享锁是指多个事务可以共享一个一把锁,都可以读取到数据,但是不能修改
  • 排他锁就是一个事务获得了排他锁,那么其他事务就不能获得锁(包括共享锁和排他锁),获取排他锁的事务可以对数据进行访问和修改

Mysql默认开启了自动事务提交,可以使用以下命令关闭

SET autocommit=0	--关闭自动事务提交

这里必须要强调一下锁的概念,不管是共享锁还是排他锁,都是我们给每一个数据元素加的,如果一个数据元素已经有了排他锁,那么久不能再给它加任何锁,如果一个数据元素有共享锁,那么还可以给它加共享锁,Mysql的InnoDB引擎默认给insert、update、delete都加了排他锁,而select未加任何锁

数据库隔离级别[通俗易懂]

新建一个查询窗口,开始事务,但是没有提交,因为update默认给数据元素加排他锁,所以这个时候我们去更新该数据元素就会出现

数据库隔离级别[通俗易懂]

上一个事务还没有提交,数据元素还有排他锁,这个update语句要给数据元素加排他锁,所以只有等待,这也验证了update语句默认会给相关的数据元素加排他锁

数据库隔离级别[通俗易懂]

如果使用select语句加共享锁进行查询一样会阻塞

数据库隔离级别[通俗易懂]

但是使用select语句不加任何锁是可以查出数据的,但是数据是更新之前的

所以,使用悲观锁在高并发情况下,对于减库存这样的操作,首先要使用排他锁的select语句拿到库存,如果已经有事务对这个数据元素上了锁,那么只有等待该事务释放锁,只有这样拿到的库存才是正确的

代码100分BEGIN;
DECLARE @now_quantity INT;
SELECT quantity INTO @now_quantity FROM item WHERE id=1 FOR UPDATE;//一定要加排他锁
UPDATE item SET quantity=@now_quantity-1 WHERE id=1;
COMMIT;

而且需要注意,MySQL InnoDB默认行级锁。行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁把整张表锁住

使用悲观锁的方式解决丢失更新很简单,但是也会带来效率上的问题,如果一个事务上了锁,那么其他的都只有等待

使用乐观锁

我们可以给表中加上一个version自增的版本字段,查询的时候拿到版本字段和库存,当需要去更新的时候,如果版本不一致,那么需要重新查询,重复上述步骤,知道拿到的版本和数据库中的版本一致时,才进行更新,这样就不需要等待,效率更高

数据库隔离级别[通俗易懂]
数据库隔离级别[通俗易懂]

数据库隔离级别[通俗易懂]

数据库隔离级别[通俗易懂]

数据库隔离级别[通俗易懂]

数据库隔离级别[通俗易懂]

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/9175.html

(0)
上一篇 2023-02-14
下一篇 2023-02-14

相关推荐

  • oracle行转列decode_oracle行转列逗号隔开

    oracle行转列decode_oracle行转列逗号隔开###第一种 函数 wm_content(‘待转列名称’) 11g 往后,不推荐使用 ###实例 多表关联时可以使用 (SELECT wm_concat(nvl(B1.OPERA_CODE,’a’)…

    2023-03-21
    152
  • 啥叫大数据_hadoop大数据可视化

    啥叫大数据_hadoop大数据可视化一、概述 DataX 是阿里云 DataWorks数据集成 的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、Sql

    2023-05-19
    135
  • Sqlite—索引介绍[通俗易懂]

    Sqlite—索引介绍[通俗易懂]创建索引 1、单列索引 单列索引是一个只基于表的一个列上创建的索引。基本语法如下: sqlite> CREATE INDEX index_name ON table_name (column_n

    2023-02-15
    156
  • MySQL集群搭建_docker mysql集群

    MySQL集群搭建_docker mysql集群NDB群集安装 介绍 https://dev.mysql.com/doc/refman/8.0/en/mysql-cluster-basics.html NDBCLUSTER (也称为NDB

    2023-02-04
    136
  • centos7+ mysql5.7 升级到mysql8+「终于解决」

    centos7+ mysql5.7 升级到mysql8+「终于解决」参考网址吧。 按如下网址提供的实操步骤,顺利完成了mysql5.6的卸载和mysql8.20的安装。 注意: 1、在初始化指令步骤,会自动生成一个数据库root密码。注意先保存下来。防止无法登录。 …

    2023-02-26
    151
  • 如何安装jieba库

    如何安装jieba库jieba是一款中文分词库,由于其简洁易用的特点,成为了众多自然语言处理(NLP)工程师的选择。然而,很多初学者在安装jieba时,可能会遇到一些问题,比如说安装不了或者安装了但是用不了。本文将从多个方面对jieba库的安装进行详细地阐述,并提供解决方案。

    2024-04-18
    74
  • Python l in numbers:使用Python处理数字的工具

    Python l in numbers:使用Python处理数字的工具Python是一种通用编程语言,可以用于构建各种类型的应用程序。然而,在数字处理方面,Python表现出色,因为它由各种强大的数字处理工具组成。这篇文章将详细介绍使用Python处理数字的工具。

    2024-02-23
    121
  • Python计算自然对数e的倒数

    Python计算自然对数e的倒数自然对数e的倒数指的是数学常数e的倒数,e是自然常数,约等于2.71828。e的倒数也是一个常数,可以用分数形式表示为1/e。

    2024-03-28
    79

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注