数据库的隔离级别

数据库的隔离级别本文主要介绍了数据库中的隔离级别,以及其会产生的场景。

大家好,又见面了,我是你们的朋友全栈君。

详解数据库的隔离级别

1,数据库事务的四大特性

数据库事务:是作为单个工作单元而执行的一系列操作,如查询和修改数据,甚至是修改数据的定义。

  1. 原子性 (Atomicity)

原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。即要么都成功,要么都失败。

在这里插入图片描述

如上图: 小明要给小红转200元,那么这个过程包括两个步骤:小明给银行转200:1000-200=800;银行给小红转账200:1000+200=1200。原子性规定这两个步骤一起成功,或者一起失败,不能只发生其中一个动作。如果小明只减200或者小红只加200,那么银行就会乱套。

  1. 一致性 (Consistency)

一致性是指事务前后数据的完整性必须保持一致。

在这里插入图片描述

仍是如上图:小红和小明初始的金额总数为:1000+1000=2000;在转账完成之后,小明余额800元,小红余额1200元。俩人金额总数为:800+1200=2000。一致性表示事务完成后,符合逻辑运算。

  1. 隔离性 (Isolation)

隔离性是指多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

在这里插入图片描述

如上图:多个用户同时操作,产生俩个事务:1,小明给小红转账200;2,小刚给小红转账100。隔离性是指小明和小刚给小红转账这两个事务不会相互影响。

  1. 持久性 (Durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

仍是如上图的例子:小明给小红转账200元:

操作前小明:1000,小红:1000
操作后小明:800,小红:1200
如果在操作前(事务还没有提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为:小明:1000,小红:1000;
如果在操作后(事务已经提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该仍为
A:800,B:1200,不会恢复到原始。

2,数据库的隔离级别问题

2.1脏读

脏读是指一个事务在执行过程中读取到另一个事务未提交的数据的现象就是脏读。

如上图小明和小刚给小红转账:

在这里插入图片描述

1、在小明给小红转账过程中,银行对小红的银行卡余额进行了修改为1200,小刚给小红转账时读取了小红的银行卡余额修改后的数据,并加100为1300了。

2、由于某些原因,小明撤销了转账的事务转账事务没有完成提交,发生了RollBack操作,则小刚读取的数据就是脏数据。这样就产生了数据错误。

PS:银行实际转账流程不是如此,该例子只是为了便于理解脏读。

2.2 不可重复读

不可重复读是指对于数据库中的某个数据,一个事务范围内的多次查询却返回了不同的结果,这是由于在查询过程中,数据被另外一个事务修改并提交了。

事务B读取了两次数据资源,在这两次读取的过程中事务A修改了数据,导致事务B在这两次读取出来的数据不一致。

注: 不可重复读和脏读的区别是,脏读读取到的是一个未提交的数据,而不可重复读读取到的是前一个事务提交的数据;而不可重复读在一些情况也并不影响数据的正确性,比如需要多次查询的数据也是要以最后一次查询到的数据为主。

2.3 虚读(幻读)

幻读是事务非独立执行时发生的一种现象。例如事务1批量对一个表中某一列列值为1的数据修改为2的变更,但是在这时,事务2对这张表插入了一条列值为1的数据,并完成提交。此时,如果事务T1查看刚刚完成操作的数据,发现还有一条列值为1的数据没有进行修改,而这条数据其实是2刚刚提交插入的,这就是幻读。
幻读和不可重复读都是读取了另一条已经提交的事务(这点同脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

注:

  1. 幻读和不可重复读都是读取了另一条已经提交的事务。不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体

  2. 解决不可重复读的方法是 锁行,解决幻读的方式是 锁表

3,数据库的锁机制

3.1 共享锁

由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享锁,不能获取排它锁,也就是说只能读不能写。

3.2 排它锁

由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁,典型是mysql事务。

3.3 表锁

给整张表加锁

3.4 行锁

给行数据加锁

因此锁可以分为表级共享锁行级共享锁表级排它锁行级排它锁

4,数据库的隔离级别

4.1 读取未提交(READ-UNCOMMITTED)

在这个隔离级别,select语句不加锁,所有事务都可以“看到”未提交事务的执行结果。读取未提交数据,也被称为“读脏”。

4.2 读取已提交(READ-COMMITTED)

大多数数据库系统的默认隔离级别(但是不是MySQL的默认隔离级别),满足了隔离的早先简单定义:一个事务开始时,只能“看见”已经提交事务所做的改变,一个事务从开始到提交前,所做的任何数据改变都是不可见的,除非已经提交。可避免脏读的发生,在互联网大数据量,高并发量的场景下,几乎不会使用上述两种隔离级别。

4.3 可重复读(REPEATABLE-READ)

MySQL数据库默认的隔离级别。该级别解决了READ UNCOMMITTED隔离级别导致的问题。它保证同一事务的多个实例在并发读取事务时,会“看到同样的”数据行。不过,这会导致另外一个棘手问题“幻读”。InnoDB和Falcon存储引擎通过多版本并发控制机制解决了幻读问题。

4.4 可串行化(SERIALIZABLE)

该级别是最高级别的隔离级。它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简而言之,可串行化是在每个读的数据行上加锁。在这个级别,可能导致大量的超时Timeout和锁竞争Lock Contention现象,实际应用中很少使用到这个级别,但如果用户的应用为了数据的稳定性,需要强制减少并发的话,也可以选择这种隔离级。

根据数据库的隔离级别问题可以看出数据库的隔离级别的缺点:

隔离级别 脏读可能性 不可重复读可能性 幻读可能性 加锁读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE

5,数据库的三大范式

范式是数据库设计时遵循的一种规范,不同的规范要求遵循不同的范式。

5.1 第一范式

数据库的属性不可分割,即每个属性都是不可分割的原子项。即保证数据库的每一列不可再分。

5.2 第二范式

前提:必须满足第一范式。不存在部分依赖,即非主属性必须完全依赖于主属性。即第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。

5.3 第三范式

前提:必须满足第一、第二范式。不存在传递依赖,即非主属性不能与非主属性之间有依赖关系,非主属性必须直接依赖于主属性,不能间接依赖主属性。即第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。

作者:王二黑_Leon
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
本文章仅作为自学所用。

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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143037.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 苹果消息推送服务教程:第一部分(共2部分)

    苹果消息推送服务教程:第一部分(共2部分)这篇文章还可以在这里找到 英语LearnhowtoaddPushNotificationsintoyouriPhoneapp!这是iOS教程团队的MatthijsHollemans编写的一篇教程,MatthijsHollemans是一个经验丰富的iOS开发者和设计师。在iOS系统中,在后台运行的程序能够进行的操作是非常有限的。这种限制

    2022年7月12日
    28
  • 带宽指信道所能送的信号的频率宽度_信道带宽计算公式

    带宽指信道所能送的信号的频率宽度_信道带宽计算公式信道带宽1.4M3M5M10M15M20M分别对应子载波数721803006009001200,这些子载波数是怎么算出来的?

    2022年8月31日
    3
  • NULL与nullptr

    传统意义上来说,c++把NULL、0视为同一种东西,有些编译器将NULL定义为((void*)0),有些将其定义为0.c++不允许直接将void*隐式的转化为其他类型,但是如果NULL被定义为((void*)0),当编译char*p=NULL;NULL只好被定义为0。还有:void  func(int);void  func(char*);如果NULL被定义为0,func(NUL…

    2022年4月6日
    328
  • Java文件操作(超详细+代码示例)「建议收藏」

    Java文件操作(超详细+代码示例)「建议收藏」Java文件操作一、Java.io包1.1File类1.2Stream流1.2.1使用FileInputStream类1.2.2使用FileOutputStream类二、序列化我们日常使用电脑的时候,基本都会和文件打交道,比如我们做ppt,或者写论文的时候,我们打开的word,ppt等等都是一个文件,这些文件不一样的主要是因为后缀名不一样,所以计算机才可以分辨出来这些文件的区别。文件一…

    2022年7月26日
    14
  • navicat15 用注册码激活_在线激活2022.01.25

    (navicat15 用注册码激活)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~1TCF…

    2022年3月31日
    161
  • centOS7下实践查询版本/CPU/内存/硬盘容量等硬件信息

    centOS7下实践查询版本/CPU/内存/硬盘容量等硬件信息1.内核版本uname-a能确认是64位还是32位,其它的信息不多[root@localhost~]#uname-aLinuxlocalhost.localdomain3.10.0-327.el7.x86_64#1SMPThuNov1922:10:57UTC2015x86_64x86_64x86_64GNU/Linuxmore/etc/*relea

    2022年6月26日
    34

发表回复

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

关注全栈程序员社区公众号