数据库基础知识
E-R图:实体、属性和联系
数据库范式
1-NF:实体的属性不能再被分割
2-NF:函数依赖、部分函数依赖、完全函数依赖、传递函数依赖
3-NF:消除传递函数依赖的字段设计
主键和外键的区别:
主键是唯⼀表示数据的id;外键是table1余table2的关联,在table2中做主键
为什么不使⽤外键?
因为⼀次更新需要级联更新所有相关的外键的数据,分库分表也外键不⽣效
什么是存储过程?
存储过程是⼀段sql语句的集合
drop、truncate、delete 的区别?
drop 删除表结构
truncate:清理整表数据
delete * from table_name where xxx;清理指定条件的数据
3、MySQL
MySQL的架构:client发起请求 ——> ⾸先经过查询缓存,能查到直接返回,不能查到——> 分析器 ——> 优化器
(优化执⾏⽅式,选择索引)——> 执⾏器(查询存储引擎,返回结果)
MySQL的存储引擎有哪些?
MyISAM
InnoDB
1、InnoDB⽐MyISAM的好处?
InnoDB⽀持事务,并且有多种事务隔离级别
InnoDB⽀持⾏级锁,MVCC
InnoDB⽀持崩溃可恢复2、MySQL的索引实现
索引是查询和快速检索数据的数据组织结构
索引的优缺点?有了索引查询更快,但是索引本身的存储和结构维护会耗费⼀定的空间和时间
索引的数据结构?
B树、B+树的区别?
B树每个节点存储的都是key、data;B+树只有叶⼦节点【叶⼦节点才有所有的数据】存储data
B树叶⼦节点都是独⽴的,B+树叶⼦节点相邻之间是连接的
最左匹配原则
联合索引使⽤索引情况
索引:a_b
在索引结构⾥⾯是先按照a字段进⾏了排序,在a相同的数据⾥,按照b字段排序,整体结构看b字段不是有序的
varchar类型的字段本身⻓度+2【变⻓字节】
单张表索引字段最好不要超过5个
索引下推
索引失效场景
select *
未遵循最左匹配原则
在索引列上进⾏计算、函数、类型转换
使⽤%开始的like查询
or查询
MySQL语句的执⾏计划
explain 语句,获取优化器优化之后的执⾏⽅式
select * from t_table where a > 1 and b = 2; // 使⽤的索引是a字段
select * from t_table where a >= 1 and b = 2 // 使⽤的索引⽤到了a、b两个字段。a=1时b=2是有
效的【索引下推了】
SELECT * FROM t_table WHERE a BETWEEN 2 AND 8 AND b = 2 // 使⽤了a、b两个字段,MySQL中
SELECT * FROM t_user WHERE name like 'j%' and age = 22 //[联合索引name_age],实际查询过程中
使⽤了name、age两个字段进⾏查询,这⾥⾯⽤到age=22的条件相当于⽤到了索引下推type:
all:全表扫描
ref:使⽤普通索引
system:表中只有⼀⾏数据
const:表中最多有⼀⾏数据
eq_ref:连表查询时后表只有⼀⾏数据对应
range:索引范围查询
index:遍历整个索引树
index_merge:查询条件使⽤多个索引
possible_keys:可能⽤到的索引
key:实际⽤到的索引
key_len:实际索引的⻓度
rows:⼤致要扫描的⾏数
Extra:
Using filesort:在排序时使⽤了外部的索引排序,没有⽤到表内索引进⾏排序。
Using temporary:MySQL 需要创建临时表来存储查询的结果,常⻅于 ORDER BY 和 GROUP BY。
Using index:表明查询使⽤了覆盖索引,不⽤回表,查询效率⾮常⾼。
Using index condition:表示查询优化器选择使⽤了索引条件下推这个特性。
Using where:表明查询使⽤了 WHERE ⼦句进⾏条件过滤。⼀般在没有使⽤到索引的时候会出现。
3、MySQL⽇志
1、MySQL 中常⻅的⽇志有哪些?
2、慢查询⽇志有什么⽤?
3、binlog 主要记录了什么?
4、redo log 如何保证事务的持久性?
对数据库中数据进⾏修改时,记录修改操作,然后将修改操作记录到redo log,只要记录到了redo log的⽇志⽂件
中,那么即便发⽣数据库服务器宕机情况,也能根据redo log的记录,恢复事务的执⾏,保证事务的持久化完成
redo log的刷盘机制?
redo log中记录修改数据记录,每次事务提交的时候,将redo log数据内容同步到磁盘中
内存的redo log buffer ——> 系统buffer ——> 磁盘的redo log⽂件中
从buffer刷新到磁盘⽂件的配置:0、1、2
0:只是记录到redo log buffer中,由系统单独起线程控制 刷新到系统buffer和redo log⽂件
1:每次执⾏事务的commit时,都要刷新到磁盘的redo log⽂件
2:每次提交事务时只是把数据刷到系统buffer中,再每隔⼀秒刷新到redo log⽂件
redo log的写⼊机制
redo log⽂件存储是环状,⼀个指向当前正在写⼊的地址,⼀个指向刷盘的地址,这两个之间的间隔代表可以写⼊
的空间。ib_logfile0ib_logfile1ib_logfile2
redo log的LSN机制
⽂件的逻辑序列号,⽤来⽐对写⼊到磁盘中的和内存中的位置是不是⼀致的
写redo log和binlog的时机
①、预提交redo log的写⼊ ——》②、提交binlog写⼊——》③、提交写⼊redo log
这样流程可以保证事务操作数据的完整性:预提交redolog,系统崩溃存在两种情况:1、写⼊了binlog,则按照执
⾏预提交的正式提交;2、没有写⼊binlog,则将事务操作回滚,使⽤undo log恢复数据
5、undo log是什么?有什么作⽤?如何保证事务的⼀致性?
undo log记录的是事务变更时的逆向过程数据
作⽤:⽤来恢复事务回滚前数据状态
undo log存储⽅式:
通过回滚段的⽅式管理,每个回滚段⾥有多个segment。
undo log⻚的重⽤怎么实现?
每次事务执⾏完之后并不会⽴刻回收回滚段,⽽是判断segment是否可重⽤,如果可以的话,那么⼀个segment是
属于多个事务使⽤的
undo log如何实现MVCC
undo log记录了事务内修改操作的数据列表:事务内insert操作执⾏完成后删除;update、delete操作会将事务内
对⾏记录的变更都记录下来,通过版本号⽅式代表每⾏不同版本下的记录MVCC:读取数据时,如果⾏数据对当前事务不可⻅,可以通过读取undo log中事务开始之前的数据
6、binlog 和 redo log 有什么区别?
binlog是mysql记录数据变更的⽇志⽂件;redo log是InnoDB引擎记录事务操作数据⻚的修改内容
binlog记录内容:根据设置的模式不同记录的内容不同
Row模式 :记录的是变更的数据内容
statement模式 :记录的是修改数据的sql语句内容
Mixed模式 :Row模式和statement模式的混合
7、MySQL的事务机制是如何实现的?
MySQL开启事务时,将待更新的数据加载到内存中——> 记录事务开始前数据到undo log中——> 修改数据并记录
到redo log中——> 提交事务 ——>数据变更写⼊到binlog;redo log⽇志记录刷新到磁盘上
4、MySQL事务
事务的特性:
A:原⼦性。⼀组SQL语句要么都执⾏,要么都不执⾏
C:⼀致性。事务执⾏前后,数据时⼀致的。⼀致的理解,例如转账,前后总额都是⼀样的
I:隔离性。事务之间执⾏时是互相隔离的
D:持久性。事务提交后对数据的修改是永久的
保证了AID、也就实现了C
并发事务中存在的问题?
脏读:事务A修改数据之后事务B读取到了修改之后的数据,事务A回滚的话,事务B读的数据就是脏读
丢失修改:事务A和事务B同时读取了数据,事务A修改并提交后,事务B在修改提交的话,会导致事务A的提
交丢失
不可重复读:事务期间多次读取数据,读到的数据不⼀致,数据被修改了
幻读:事务期间多次读取数据,数据记录条数不⼀致,出现新增、删除的数据
不可重复读和幻读的区别?⼀个是数据被修改,⼀个是数据出现新增和删除
并发事务控制⽅式
锁 + MVCC
锁:共享锁、排他锁表级锁,⾏级锁。与共享锁、排他锁是交叉搭配的关系
⼀致性⾮锁定读和锁定读:
⼀致性⾮锁定读:读取时 MVCC 采⽤版本控制,读第⼀遍version=1,再读是如果version!=1 则代表不可⻅
锁定读:读取的是最新数据,读到之后会对数据加锁
select ... lock in share mode
select ... for update
insert、update、delete
锁定读的情况下,如何保证⼀个事务之间读到的数据时⼀致的?
MVCC + Next-key-lock 解决 幻读 问题:
使⽤ Next-key Lock
事务隔离级别
读未提交:读其他事务未提交的修改数据
读已提交:读取到其他事务已经提交的修改数据。通过MVCC机制实现
可重复读:事务内多次读取数据都是⼀致的。通过MVCC机制实现
串⾏化:不同事务之间串⾏执⾏
默认是可重复读
InnoDB对MVCC的实现
通过这三个内容实现:隐藏字段 + ReadView + undo-log
隐藏字段是指在每个数据记录⾏后有隐藏字段,记录操作当前记录的最新事务id、undo-log的数据快照地址;
ReadView:是指事务开始之后创建的当前事务与其他事务可⻅性的结构。数据可⻅性算法使⽤该结构
undo-log:分为两部分,⼀部分是insert语句,对其他事务必然不可⻅,⼀种是修改语句,在事务提交之后undo
log进⼊暂存阶段,等不可⽤时再清理掉
RR + MVCC 解决不可重复读问题:
在不可重复读的问题下,RC下的MVCC还是会出现问题
RR下的MVCC不会出现该问题
原因是创建ReadView的时机不同:RC每次读取时都会创建ReadView、RR事务开始后第⼀次读取才会创建
ReadView5、MySQL锁
InnoDB⾏锁,锁的是索引数据⻚上的数据
类型:
⾏锁(Record):
间隙锁(Gap):锁定的是⾏之间的间隙,不包括⾏记录本身
临键锁(Next-key lock):锁定的是⾏以及⾏的间隙,包括⾏记录本身。默认使⽤的是该锁
操作主键或者唯⼀键索引时,临键锁会降级为⾏锁
举例
!
:
主键等值查询&&值存在
主键等值查询&&值不存在
主键范围查询:
A<= key < B
A < key <= B
A < key < B
共享锁(S)和排它锁(X)
select... lock in share mode
select... for update
⼀般的 select 不会加锁,因为有MVCC控制读取正确版本的数据
意向锁是什么含义?
意向锁是存储引擎在对数据进⾏加锁前⾸先获取意象锁
6、MySQL优化
单张表数据超过500w时尽量分表存储
查询数据时都要带有时间限制
主库负责写⼊,从库负责读取
分表:垂直分区、⽔平分区
-- 垂直分区指的是数据列进⾏拆分,有原来20个字段拆分为单表10个字段
--⽔平分区:拆分的是表中记录的数据量,从500w条数据拆分为单标100w数据;⼀般分表的时候会进⾏分库,这
样可以将表的数据分布式存储在不同的机器上--分表之后的唯⼀id,美团的leaf ⽣成分布式唯⼀id
⼀条sql语句执⾏的很慢的原因
每次执⾏都很慢的话:是否⽤到了索引;没有⽤到索引有可能是⾃⼰查询字段顺序不对,也有可能是系统评估
不⾛索引
偶尔执⾏很慢:是不是业务⾼峰期,或者是执⾏期间遇到锁表情况
limit语句在偏移量⾮常⼤时查询效率变低
原因:如果条件是⾮主键索引的话,使⽤limit a,b查询时会根据索引查到id,在根据id回表查询a+b条数据,
最终保留a,b的数据
解决办法:①、根据⾮主键索引查询到limit a,b下最⼩的id,再使⽤id查询主键索引的列记录