MySQL知识网络
MySQL知识网络
引擎
InnoDB
- 支持表锁 、行锁
- 支持事务
- *.frm 表结构文件
- *.idb 表数据和索引文件
MyISAM
- 支持表锁
- *.frm 表结构文件
- *.MYD 表数据文件
- *.MYI表索引文件
MEMORY
内存表
CSV
csv形式
索引
BTREE
主键索引
主键索引就是聚簇索引
聚簇索引
聚簇索引就是主键索引
普通索引
数据端也存在主键 (回表)
联合索引
最左前缀原则
HASH
- key:value
事务
事务是一组操作的集合
事务特性
原子性:满足原子操作,对数据操作,要么全部成功,要么全部失败。
一致性:数据开始和完成,数据都保持一致。
隔离性:事物之间是相互独立的,中间状态对外不可见。
持久性:数据的修改时永久的
隔离级别
1. 原因
多个事务并发执行,会出现几个问题
脏读:A事务未提交, B事务读到A的结果(破坏了隔离性)
不可重复读:A事务在本次事务中,对自己未操作的数据,进行多次读取,出现了结果不一致,或者记录不存在的情况。(破坏了一致性, update)
注:主要是MVCC、和锁来解决这个问题
幻读:A事务在本次事务中,对自己的数据进行多次读取,第一次不存在, 第二次记录出现了。(破坏了一致性, insert)
注:主要用next-key锁来解决这个问题
2.解决办法(制定标准)
为了权衡【隔离】和【并发】的矛盾,ISO定义了四个事务级别,每个级别的隔离程度不同,出现的情况也不同
Read uncommitted
存在问题:脏读、不可重复读、幻读
实现原理:读无锁
改:启用行级共享锁
Read committed
存在问题:不可重复读、幻读
实现原理:读行级共享锁
改:行级排他锁
Repeatable read
存在问题:幻读
实现原理: 读取共享锁直到事务结束释放 写排它锁直到事务结束释放
Serializable
存在问题:不可并发
实现原理:读取表级共享锁直到事务结束释放, 写表级排它锁直到事务结束释放
3.实现(InnoDB)
锁机制:阻止其他事物进行操作,各个隔离级别主要体现在读取数据是加的锁和释放的时机。
RU: 事务读取时, 不加锁。
RC: 事务读取时,加行级共享锁(读到才加锁), 一旦读完,立即释放(并不是事务结束)。
RR: 事务读取时,加行级共享锁,直到事务结束才会释放。
SE: 事务读取时加表级共享锁,直到事务结束时,才释放
MVCC机制:生成一个数据快照,并用这个快照来提供一定级别的一致性读取,也成为了多版本数据控制。(基于undo做的快照,将读取数据页变成读快照来防止脏读、幻读、不可重复去的问题)
原理:
通过每行保存两个隐藏列:trx_id(事务id)和 roll_pointer(回滚指针)两个字段
每次操作都会生成一条undo log日志,回滚指针指向前一条数据
从最新记录开始找:
如果当前记录:事务id<未提交事务的最小id,则可读(即:活跃事务最小id)
如果当前记录: 未提交事务的最小id <事务id <= 未提交事务的最大id,则判断是否存在未提交事务数组中,存在则不可读(当然自己的事务也是可读),不存在可读
如果当前记录:事务id>未提交事务的最大id, 则不可读
注:可重复读仅在事务开始创建一次快照,而读已提交是每次执行语句时都要重新创建一次。
快照的规则:
- 事务内更新可读到
- 版本未提交,不能读到
- 版本已提交,但是在快照后创建的,不能读到
- 版本已提交,且在快照创建前创建的,可以读到
并发写问题:
多个事务对同一条数据修改。更新前要先读数据,这里的说的读,是更新之前的读叫做“当前读”,总是当前版本的数据, 也就是多个版本中最新一次提交的那版。
实际就是【CAS版本控制】和【读写分离】思想
主要用于RC和RR级别
锁
分类
MySQL锁分为共享锁和排它锁, 也叫读锁和写锁
读锁是共享的,可以通过lock in share mode实现,这时候只能读不能写。
写锁是排他的,它会阻塞其他的写锁和读锁。从颗粒度来区分,可以分为表锁和行锁两种。
表锁会锁定整张表并且阻塞其他用户对该表的所有读写操作,比如alter修改表结构的时候会锁表。
行锁又可以分为乐观锁和悲观锁,悲观锁可以通过for update实现,乐观锁则通过版本号实现。
行锁&表锁
只有明确锁定索引, 才会执行行锁,否则执行表锁
无锁
# 主键不存在
select * from user where id=-1 for update;
行锁
select * from user where id=1 for update;
select * from user wehre id=1 and name='xxx' for update;
表锁
# 主键不明确
select * from user where name='xxx' for update;
select * from user where id <> 3 for update;
锁算法(机制)
行锁算法
Record Lock(普通行锁)
键值存在条件范围内
记录存在
Gap Lock(间隙锁)
- 对于键值不存在的条件范围内,叫做“间隙”(GAP).引擎就会对这个“间隙”加锁,这种机制就是Gap机制(InnoDB独有的)
Next-Key Lock(行 & 间隙)
在键值范围条件内,同时键值又不在条件范围内 (注: Next-Key 锁 用来解决RR中幻读)
注: Next-Key 锁 用来解决RR中幻读
# id 只有1-50
select * from user id>49 for update;
表锁算法
意向锁(升级机制)
当一个事务带着表锁去访问一个被加了行锁的资源,那么, 此时, 这个行锁就会升级成意向锁,将表锁住。
# 事务A
select * from user where id=10 for update;
# 事务B (B表锁中的值包含 A行锁 id=10)
select * from user where name ='xxx' for update;
自增锁
事务插入自增类型的列时,获取自增锁
如果一个事务正在往表中插入自增记录,其他事物都必须等待
实现
共享锁 & 排它锁
行锁和表锁是粒度的概念, 共享锁和它他锁使他们的具体实现
共享锁(s)
- 允许一个事务去读一行,阻止其他事物去获取该行的排它锁; 都能读,但是不能改
排他锁(x):写锁
允许持有排它锁的事务去读数据,阻止其他事物去获取该资源的共享锁和排它锁; 改的时候谁都不许操作
不能获取任何锁,不代表不能读
注意
某个事务获取数据的排它锁,其他事务不能获取该数据的任何锁,并不代表其他事务不能无锁读取数据。
- 无锁
select ... from ...
- 共享锁
select ... lock in share mode
MySQL8.0以上,for share 代替了lock in share mode,但是任然支持lock in share mode;但是 nowait、skip locked,配合自旋锁,可以高效的实现一个等待队列。
- 排它锁
update ...
delete ...
insert ...
select ... for update
乐观锁&悲观锁
无论是什么锁都需要加失败重试
乐观锁
概念:总是假设最好的情况,每次拿数据的时候都认为别人不会修改,所以不会上锁。但是在更新的时候判断一下在此期间别人有没有更新这个数据,一般通过版本号机制和CAS算法实现。乐观锁适用于写比较少的情况下(多读场景)
一般通过版本号进行更新, 同版本方可更新成功,不同版本则需要重试更新操作,直到成功
update user set name='xxx' where id=1 and version=1;
悲观锁
概念:总是假设最坏的情况,每次拿数据的时候都认为有人回修改,每次拿数据的时候都会上锁,然后别人想拿数据就一直堵塞。多写场景
排它锁的实现
日志
InnoDB日志
redo log (重做日志)
redo log通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。
作用:
确保事务的持久性。防止在发生故障的时间点,当有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。
undo log (回滚日志)
undo用来回滚行记录到某个版本。undo log一般是逻辑日志,根据每行记录进行记录。
作用:
保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读
MySQL server 日志
bin log(归档日志)
作用:
用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。
用于数据库的基于时间点的还原。
redo log 和 binlog 区别
- redo log是属于innoDB层面,binlog属于MySQL Server层面的,这样在数据库用别的存储引擎时可以达到一致性的要求。
- redo log是物理日志,记录该数据页更新的内容;binlog是逻辑日志,记录的是这个更新语句的原始逻辑
- redo log是循环写,日志空间大小固定;binlog是追加写,是指一份写到一定大小的时候会更换下一个文件,不会覆盖。
- binlog可以作为恢复数据使用,主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用。
一条更新语句执行的顺序
update T set c=c+1 where ID=2;
- 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
- 执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
- 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
- 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
- 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。
SQL优化
常见面试题
- mysql主从同步怎么搞的?分哪几个过程?如果有一台新机器要加到从机里,怎么个过程。
- 主mysql将日志写入bin log
- 从mysql连上主mysql,获取bin log
- 主mysql dump线程将bin log日志推送给从mysql
- 从mysql将得到的日志 写入relay log
- 从mysql开一个sql线程 读取relay log 并执行sql语句,完成同步
- 从mysql记录自己的bin log
- binlog 日志是 master 推的还是 salve 来拉的?
刚刚连接的时候是 slave来拉 后面是master主动推过来
binlog 有哪几种模式
row 记录数据值,同时也会记录关联表的信息情况,优点不冲突 缺点日志大
statement 记录sql逻辑, 优点数据小, 缺点使用function 可能导致主从数据不一致
mixed row和statement的结合
mysql有哪些日志
redo log、bin log、undo log、relay log、slow query log、error log、general log
mysql加锁规则
加锁规则 next-key lock
- 唯一索引等值查询
- 记录存在时,
next-key lock
退化成行锁
- 记录不存在时,
next-key lock
退化成间隙锁
- 非唯一索引等值查询
- 记录存在时,加
next-key lock
外, 还额外加一个间隙所
, 也就是两把锁 - 当记录不存在时,加
next-key lock
, next-key lock退化成间隙锁
MySQL知识网络的更多相关文章
- MySQL知识树-查询语句
在日常的web应用开发过程中,一般会涉及到数据库方面的操作,其中查询又是占绝大部分的.我们不仅要会写查询,最好能系统的学习下与查询相关的知识点,这篇随笔我们就来一起看看MySQL查询知识相关的树是什么 ...
- 两个容易被忽略的mysql知识
原文:两个容易被忽略的mysql知识 为什么标题要起这个名字呢?commen sence指的是那些大家都应该知道的事情,但往往大家又会会略这些东西,或者对这些东西一知半解,今天我总结下自己在mysql ...
- 【MySQL】MySQL知识图谱
MySQL 文章目录 MySQL 表 锁 索引 连接管理 事务 日志系统 简单记录 极客时间 - MySQL实战45讲 MySQL知识图谱 表 表 引擎选择 编码问题 表空间管理 字段设计 备份和恢复 ...
- 支持中文!秒建 wiki 知识库的开源项目,构建私人知识网络
不知道有没有人和我一样,觉得自建的东西是互联网上的"自留地".私人空间,有一种自己的一亩三分地随心所欲的痛快. 比如自建的博客想写什么随笔就写什么,不用取悦读者可以自娱自乐:再比如 ...
- MySQL知识小结
MySQL的知识面试中还是经常被问到的,简单的使用似乎无法达到面试官的要求,很多问题会关于Mysql存储引擎,所以这里还是需要系统学习一下Mysql的一些知识,面试过程中游刃有余. MySQL体系结构 ...
- [mysql]知识补充
知识概况 视图 函数 存储过程 事务 索引 触发器 [视图] 视图是一个虚拟表,可以实现查询功能,不能进行增删改 本质:根据sql语句获取动态的数据集,并为其命名 1.创建视图 --create vi ...
- mysql知识初篇(一)
mysql介绍 (1) mysql数据库是瑞典AB开发. (2) mysql--> sun --> oracle. (3) mysql数据库的特点. 1. 开源. 2. 免费. 3. 跨平 ...
- 【Mysql知识补充】
一.子查询 1.定义 子查询是将一个查询语句嵌套在另一个查询语句中.内层查询语句的查询结果,可以为外层查询语句提供查询条件.子查询中可以包含:IN.NOT IN.ANY.ALL.EXISTS 和 NO ...
- TCP/IP协议(一)网络基础知识 网络七层协议
参考书籍为<图解tcp/ip>-第五版.这篇随笔,主要内容还是TCP/IP所必备的基础知识,包括计算机与网络发展的历史及标准化过程(简述).OSI参考模型.网络概念的本质.网络构建的设备等 ...
- 一些值得收藏的MySQL知识链接
https://yq.aliyun.com/articles/5533(死锁分析的很好的一篇文章) http://hedengcheng.com/?spm=5176.100239.blogcont55 ...
随机推荐
- Prometheus之自定义标签
前言: 我们一般通过grafana导入Dashboard模板用来展示数据,但是有时候需要自己定义展示项目,这时需要自己在Prometheus重新自定义标签,并在grafana进行应用. 1.Prome ...
- python将日志生成到文件和控制台
# 日志收集设置import logging, osfrom logging.handlers import TimedRotatingFileHandlerimport datetimecurren ...
- huggingface vit训练CIFAR10数据集代码 ,可以改dataset训练自己的数据
上代码,使用hugging face fineturn vit模型 自己写的代码 from transformers import ViTImageProcessor, ViTForImageClas ...
- D365虚拟机安装
原本有本地VM是2023.3.31安装的,奈何微软不断升级,导致程序一些新特性用不到,例如: 1,Master Planning ---> Planning Optimization, 2,mi ...
- [HTML] 访问 a 链接不带 referer 的方式
html5 新属性 referrerpolicy: referrerpolicy no-referrer no-referrer-when-downgrade origin origin-when-c ...
- 推荐一个使用 HardLink 硬链接减少重复文件占用磁盘空间的工具
在 NTFS 文件系统里面,咱可以使用 HardLink 硬链接的方式,将多个重复的文件链接到磁盘的同一份记录里面,从而减少在磁盘里面对重复文件存储多份记录,减少磁盘空间的占用.本文将和大家推荐我所做 ...
- OpenTK 垂直同步对刷新率的影响
本文将和大家介绍 Vsync 垂直同步的开启对 OpenTK 应用的刷新率的影响 在上一篇博客 OpenTK 入门 初始化窗口 告诉了大家如何初始化 OpenTK 承载 OpenGL 的窗口的应用,在 ...
- C# 从控制台创建 WinUI 3 应用
本文将告诉大家如何从控制台而不是 WinUI3 模版项目,从零一步步创建出 WinUI 3 应用 本文不是 WinUI 3 入门博客,本文将从比较基础层的方式创建出 WinUI 3 应用,适合于了解 ...
- 修复 GitLab 的 CI Runner 提示找不到 pwsh 执行文件
本文告诉大家如何修复使用 GitLab 的 Runner 做 CI 时提示 "pwsh": executable file not found in %PATH% 错误 有两个方法 ...
- dotnet C# 反射扫描程序集所有类型会不会触发类型静态构造函数
在 dotnet 里面,有很多框架都喜欢扫描程序集进行初始化逻辑,在扫描程序集的所有类型的时候,相当于碰到所有类型.而某个类型的静态构造函数将会在某个类型被使用之前被 CLR 调用,那么扫描类型是否会 ...