【MySQL】数据库的脏读,不可重复读和幻读,覆盖索引是什么,索引类型有哪些

数据库的脏读,不可重复读和幻读

三个都是并发事务带来的数一致性问题,严重程度递减
脏读 :读到来还没事务提交的数据,万一事务回滚了,读取到的数据不存在。
不可重复读 :同一个事务里两次读同一行数据,结果不一样。因为中间有别的事务改了这行数据并提交了。强调数据内容变了

**幻读:**同一个事务里执行两次同样的范围查询,返回行数不一样。因为中间有别的事务插入或删除了符合条件的数据。强调的是数据行数变了。

MySQL InnoDB在可重复读级别下,用MVCC加间隙锁,大部分场景能避免幻读

MVCC

MVCC = 多版本并发控制(Multi-Version Concurrency Control)

让读和写可以同时进行,而不用加锁
如何实现的 :不直接改原数据,而是"保留多个版本"

每个事务都有自己的时间点(版本号)

只能看到"自己应该看到的版本"
核心机制

  1. 隐藏字段
    每一行数据都有:
    trx_id(哪个事务改的)
    roll_pointer(指向旧版本)
  2. Undo Log(回滚日志)
    存:历史版本数据
  3. Read View(一致性视图)
    用来判断:这个版本能不能被当前事务看到

InnoDB怎么解决的

问题 InnoDB 如何解决
脏读 MVCC(读历史版本)
不可重复读 MVCC(一致性视图)
幻读 MVCC + 锁(间隙锁)
  1. 脏读:MVCC天然解决。读的是快照,没提交的数据版本不可见
  2. 不可重复读:可重复读级别下,用同一个 Read View。ReadView在事务开始时就固定了后续查询复用同一个ReadView,所以同一行数据读出来永远一样。

事务一开始就"锁定视角" 后面一直用这个视角看数据

  1. 幻读:只能保证"已有行"的一致性,不能阻止"新行插入"
    所以用:间隙锁(Gap Lock) + Next-Key Lock
    不仅锁数据还锁"数据之间的空隙"

锁住"范围"

别人不能插入新数据

学到这,也许你会想到Redis中也学到了快照(RDB)

我们来做一个区分:

MVCC中的快照=某一时刻的数据"视图"(你看到的数据版本)

本质:

不是复制一份数据

而是:

通过 MVCC 规则"决定你能看到哪个版本"

Redis中的快照:快照持久化

作用:把"某一时刻"的数据,整体保存下来

对比点 Redis RDB MySQL MVCC
是不是拷贝数据 不是
存在哪里 磁盘文件 内存 + undo log
用途 持久化 事务隔离
本质 数据备份 版本控制

MySQL的存储引擎有什么,区别是什么


MySQL的覆盖索引是什么

在解释什么是覆盖索引之前,我们先了解一下二级索引

在 InnoDB 里有两种索引:1.聚簇索引(主键索引)2. 二级索引(普通索引)
主键索引 :user(id, name, age)

如果id是主键,我们用id查询时,直接返回整行数据

id=1 → (1, 张三, 18)
二级索引 :index(name)

还是以上为例,我们用name查询返回的结果:是name=张三 → id=1

我们发现并没有age,于是就进行下一步回表

执行流程:

1.走 name 的二级索引 找到 → id=1

2.再去主键索引(聚簇索引) 找到整行数据

什么是覆盖索引 呢?

我们举个例子,主键索引相=正文,二级索引=目录。我们通过目录来查找正文内容在哪一页,让后根据页码查找答案。这一步相当于回表。如果我们发现,正文内容就在目录里,表明了我们不需要再去正文查找内容。也就不需要回表了。这就叫覆盖索引。
总结

二级索引 → 只存(索引列 + 主键)

需要其他字段 → 回表

如果查询字段都在索引里 → 覆盖索引

MySQL的索引类型

从三个维度来分类:数据结构,存储方式,索引性质。
数据结构

  • B+树索引:最常用,多层平衡树结构,叶子节点用链表串起来,既可以快速定位单条记录,快速做高效扫描
  • 哈希索引
  • 全文索引
  • 空间索引
    存储方式
  • 主键索引:唯一/非空,一张表只能有一个
  • 唯一索引:保证列值不重复,允许有NULL,可以有多个NULL
  • 普通索引
  • 联合索引:多列组合成一个索引,遵循最左前缀原则,列顺序很重要
  • 全文索引
  • 空间索引
相关推荐
其实防守也摸鱼8 小时前
《SQL注入进阶实验:基于sqli-Labs的报错注入(Error-Based Injection)实战解析》
网络·数据库·sql·安全·网络安全·sql注入·报错注入
Ting.~8 小时前
软件设计师备考笔记【day3】-数据库
数据库·笔记
Bert.Cai8 小时前
MySQL FLOOR()函数详解
数据库·mysql
小碗羊肉8 小时前
【MySQL | 第七篇】索引
数据库·mysql
m0_495496418 小时前
SQL中如何获取前N个最大值并排除自己_利用窗口函数限制
jvm·数据库·python
m0_740653228 小时前
mysql如何提取日期中的年份_使用year函数从日期中截取
jvm·数据库·python
hanyi_qwe8 小时前
Mysql 与 Nginx 双机高可用
数据库·mysql·nginx
S1998_1997111609•X8 小时前
login:/-system.web,dex.dmp,b-scode:app·%
网络·数据库·百度·facebook·twitter
运气好好的8 小时前
mysql数据库日志文件过大如何清理_定期备份与重置日志文件
jvm·数据库·python
2401_831419449 小时前
如何防止MongoDB副本集被误初始化_副本集名称(replSetName)锁定
jvm·数据库·python