数学建模社区-数学中国
标题:
拼多多面试问了数据库基础知识,今天分享出来
[打印本页]
作者:
杨利霞
时间:
2020-4-28 15:19
标题:
拼多多面试问了数据库基础知识,今天分享出来
拼多多面试问了数据库基础知识,今天分享出来
/ q8 ~+ p* V2 K% }, H: v7 j
% ^; [+ r- ^0 l
前言
: {# _7 h) l+ M
8 c0 i9 O; \( V' d2 S; L" l6 l
我是个标题党,所有文章的名字只是我的噱头,我们应该有一颗谦逊的心,所以希望大家怀着空杯心态好好学,一起进步。
- o( H+ h* x6 w% ?. S9 F5 R; |
6 } J* R7 L5 B: O% s' W
数据库我想大家应该一点都不陌生吧,我想不管你写啥的,数据库就算没用过也听过了,是我们项目体系里面不可或缺的一环。
) r1 L R* K0 h
$ t- Y2 @9 ?/ t1 j' q
问了一圈,身边朋友公司要么用自研,要么就清一色的MySQL,所以想看Oracle的朋友可能要失望了,但是不影响你了解数据库的通用知识。
) r5 P9 Z! \! u0 o$ w# Q
# A3 Y1 ^9 ~! b9 x
正文
) s& A( n* G, D0 Z7 v
. U. I4 j/ p4 r! Q1 N
你知道MySQL的基本架构么?你能在纸上给我大致画出这个示意图么?
* f+ l5 x- i0 E
2020-4-28 15:17 上传
下载附件
(48.19 KB)
7 B" j2 Y' { n1 M
好的那我们按照顺序了解下,连接器是啥?
7 v# A4 |% j N6 \5 ?: y
我们要进行查询,第一步就是先去链接数据库,那这个时候就是连接器跟我们对接。
, p/ G. @! T8 [3 s; G0 h
1 y+ E2 B6 y; F# x, i8 R R$ N7 a
他负责跟客户端建立链接、获取权限、维持和管理连接。
2 |$ h7 c8 u, ?0 ~) G& c- U" o: t, K
* N: I; | ^' m. j
链接的时候会经过TCP握手,然后身份验证,然后我们输入用户名密码就好了。
+ n' m: J; U0 s/ z: |: b' q; T
$ I0 _5 A4 z4 y* E. ~/ O! ]3 X
验证ok后,我们就连上了这个MySQL服务了,但是这个时候我们处于空闲状态。
4 j% C' \ a6 c
% f/ I2 d( \$ [
怎么查看空闲连接列表?
/ F' K1 `& h0 c$ f
show processlist,下图就是我在自己的数据库表执行命令的结果,其中的Command列显示为Sleep的这一行,就表示现在系统里面有一个空闲连接。
. C# O' b2 P0 A1 P' k
2020-4-28 15:18 上传
下载附件
(56.41 KB)
* c: }$ a; r. z L) b& n. @
这里需要注意的是,我们数据库的客户端太久没响应,连接器就会自动断开了,这个时间参数是wait_timeout控制住的,默认时长为8小时。
3 D6 R1 k' ]- H' X% `0 H
2 J) {9 _1 Q3 q6 g. b/ w) F! Q
断开后重连的时候会报错,如果你想再继续操作,你就需要重连了。
! U3 B+ @7 J6 O( `) I2 O& R
7 c8 j4 G( b: g! ?
这个有个我看过的书本的案例:
& {, O8 w% n0 l. e
$ W0 T5 _. |- w
一个在政府里的朋友说,他们的系统很奇怪,每天早上都得重启一下应用程序,否则就提示连接数据库失败,他们都不知道该怎么办。
6 {! \1 ^% e; c7 n4 h' u
我分析说,按照这个错误提示,应该就是连接时间过长了,断开了连接。数据库默认的超时时间是8小时,而你们平时六点下班,下班之后系统就没有人用了,等到第二天早上九点甚至十点才上班,这中间的时间已经超过10个小时了,数据库的连接肯定就会断开了。
5 `- [; g9 w/ ?1 b
是的,就是超出了超时时间,然后写代码的人也没注意到这个细节,所以才会出现这个问题。
7 X+ W) M1 p( [1 r. i( d1 o
( N9 o4 I" z. R, P: ^ _( q
把超时时间改得长一点,问题就解决了。
: y9 U* x) e2 x: G% A" [7 h9 ?7 V
+ F5 g3 u( L1 X" |
这种参数其实我们平时不一定能接触到,但是真的遇到问题的时候,知道每个参数的大概用法,不至于让你变成无头苍蝇。
. u! [7 \ O( ?- v; F$ q
3 k4 i8 z' ]- f0 ^% ^3 V: w
那除了重新链接,还有别的方式么?因为建立链接还是比较麻烦的。
, i, U* ]# j, J0 k
使用长连接。
" `, D: n D' j& q3 n
7 s. n2 u1 A6 ]' p9 X
但是这里有个缺点,使用长连接之后,内存会飙得很快,我们知道MySQL在执行过程中临时使用的内存是管理在连接对象里面的。
# _+ u/ `- h. t* B) X# o; e4 [
+ ?* f3 M! f3 V: e$ C
只有在链接断开的时候才能得到释放,那如果一直使用长连接,那就会导致OOM(Out Of Memory),会导致MySQL重启,在JVM里面就会导致频繁的Full GC。
$ Z% H4 s8 ~9 }+ o6 \- l$ r: Y
+ U9 P Q9 d' m+ A1 S! r
那你会怎么解决?
* ?6 S/ h5 _/ I
我一般会定期断开长连接,使用一段时间后,或者程序里面判断执行过一个占用内存比较大的查询后就断开连接,需要的时候重连就好了。
7 [$ |# M% T1 j
9 y/ U H, T9 N0 f
还有别的方法么?你这种感觉不优雅呀小老弟。
. y/ x4 k' X( Z7 h8 R* m
执行比较大的一个查询后,执行mysql_reset_connection可以重新初始化连接资源。这个过程相比上面一种会好点,不需要重连,但是会初始化连接的状态。
" q- u' v& t9 R0 b/ c7 ^
7 `8 r0 k5 u, u" o% c- Z
你了解MySQL的查询缓存么?
2 F* [" V& Z, q$ k0 g/ i, E$ W/ H
MySQL拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。
* d# O r; c, R& B
* z# z. C3 Q) B0 F" E
大家是不是好奇同一条语句在MySQL执行两次,第一次和后面的时间是不一样的,后者明显快一些,这就是因为缓存的存在。
?8 @6 b+ Z9 {" n1 f5 d
) \6 x. P' ]2 p8 h; X; ~) h. {
他跟Redis一样,只要是你之前执行过的语句,都会在内存里面用key-value形式存储着。
! y+ D6 J& u4 V1 z5 b+ s1 t* q
- `8 ]8 s7 I6 u V
查询的时候就会拿着语句先去缓存中查询,如果能够命中就返回缓存的value,如果不命中就执行后面的阶段。
+ e" v( J, m0 e4 H3 }! u
7 o! m/ w/ h1 m+ y
但是我还是不喜欢用缓存,因为缓存弊大于利。
/ S; r' O% R: X* ]
' u9 n9 @ g' ?8 o8 u' z
哦?此话怎讲?
' _6 T' m0 b. h5 @ x
缓存的失效很容易,只要对表有任何的更新,这个表的所有查询缓存就会全部被清空,就会出现缓存还没使用,就直接被清空了,或者积累了很多缓存准备用来着,但是一个更新打回原形。
, e v E, w- d6 x; Y' m
4 _" s# s) l2 B p6 W
这就导致查询的命中率低的可怕,只有那种只查询不更新的表适用缓存,但是这样的表往往很少存在,一般都是什么配置表之类的。
- e& a! z c# M+ _$ y) I: I* x
" Q0 K8 t/ b/ }; ~" o' H1 d: n
那我们查询的时候不想用缓存一般都是怎么操作的,或者是用缓存又怎么操作?
6 I0 p* ^! s& N9 U8 ~
可以显示调用,把query_cache_type设置成为DEMAND,这样SQL默认不适用缓存,想用缓存就用SQL_CACHE。
( W9 n+ }2 t5 H8 s) S1 P
' u5 L) s, Z7 k2 Y9 f
有个小技巧就是,我们之前开发的时候,都会去库里看看sql执行时间,但是可能是有缓存的,一般我们就在sql前面使用SQL_NO_CACHE就可以知道真正的查询时间了。
& o' R4 d: c1 R5 A- T$ o
! ~" E9 A& U; e% n6 F; D$ w* b
select SQL_NO_CACHE * from B
# O; [. [, ?* m' i6 [6 |! O
缓存在MySQL8.0之后就取消了,所以大家现在应该不需要太关注这个问题,主要是我之前用的版本都不高,所以缓存一直有,在《高性能MySQL》书中也看到了一些关于缓存的介绍,就想起来给大家也提一下了。
* K! z6 x4 r5 q) s6 }5 } \
1 T6 V9 F' w7 D9 g7 w9 D. ~8 H
缓存查询完了应该做啥呢?
! s9 u( H/ `, f" F0 x! @, e
在缓存没有命中的情况下,就开始执行语句了,你写的语句有没有语法错误,这是接下来MySQL比较关心的点。
: | f' \- m% \4 U9 c
7 g0 O7 g+ R8 O @
那他会怎么做呢?会先做词法分析,你的语句有这么多单词、空格,MySQL就需要识别每个字符串所代表的是什么,是关键字,还是表名,还是列名等等。
" ^, `7 B3 e1 k2 c7 w
( c- l* ^3 B+ X _. y1 J
然后就开始语法分析,根据词法分析的结果,语法分析会判断你sql的对错,错了会提醒你的,并且会提示你哪里错了。
! X) C) w4 V2 s# |: s+ v3 _
2020-4-28 15:19 上传
下载附件
(28.19 KB)
8 T4 a5 k" b3 |1 P$ ~4 X2 n
分析没错之后就进入下一步,优化器。
% X% W! @4 k' g: s& k* [, X
* X9 u7 O6 }. x
主要是优化什么呢?
0 _" D2 c2 X. e! W4 u
优化就比较简单了,因为我们建立表可能会建立很多索引,优化有一步就是要确认使用哪个索引,比如使用你的主键索引,联合索引还是什么索引更好。
8 t0 I; d8 h2 v( r f6 U, {
3 R" i8 I4 g+ D, c
还有就是对执行顺序进行优化,条件那么多,先查哪个表,还是先关联,会出现很多方案,最后由优化器决定选用哪种方案。
/ n* r" G' M" g% x9 ]
" a% n" U" k% Z- u# W% ]# `3 E6 H
最后就是执行了,执行就交给执行器去做。
8 J0 w) x R2 E. a) X+ E+ W- Y, |
7 h- }# v2 o2 z, K
第一步可能就是权限的判断,其实这里我不确定的一个点就是,我接触的公司很多都是自研的线上查询系统,我们是不能用Navicat直连线上库,只能去网页操作,那表的权限是在MySQL层做的,还是系统做的,我猜应该是系统层做的,MySQL可能默认就全开放了,只是我们 不知道ip。
8 Y5 V0 g1 K- [' q( P- a
: H# H: @$ ~6 q; L) F8 U4 ~
有知道的小伙伴也可以在公众号【三太子敖丙】去加我微信跟我说。
: Z+ o3 G2 Y: \% {2 J; a/ e
+ {. h7 J) l+ T5 h: ~7 |7 ]
执行的时候,就一行一行的去判断是否满足条件,有索引的执行起来可能就好点,一行行的判断就像是接口都提前在引擎定义好了,所以他比较快。
8 Y: v, N V8 L! t* Z& X' y
' f! V' ]: }% l" u
数据库的慢日志有个rows_examined字段,扫描多少行可以看到,还有explain也可以看到执行计划,我们扫描了多少行。
: z @7 X1 H9 w
9 V5 e8 V4 v. [- k# f0 E
可以小伙子,基础大致框架还是了解得很清楚的,我们下次深入了解下,索引和部分机制。
8 o7 U& {% [5 q/ G+ w1 J
好的,我们下次见。
2 A. J! ?/ T- S* }2 r0 q4 K0 \1 m
$ o; k8 u/ o' G* L1 ~6 F
总结
6 ~0 E k* Y8 o6 \6 s# }6 T1 \
2 i; ~. d' S; a w" F: l
基本上我把MySQL的逻辑架构的东西都简单聊了一遍,当然你去自信了解的话,你会发现其实里面还有很多细节的,我只是说了一些常见的问题,这还是阿里丁奇学长的《MySQL实战》的思路。
1 e$ I0 @" f1 Y$ f4 l% Y
7 A/ J6 r# F/ y* i! s( h* J8 _' m
我自己在MySQL方面更多的可能就是理论知识了,还做不到深入了解的地步,大家如果有机会一定要深入的去学习一下。
5 S7 v. d3 y9 F5 j# p9 X
————————————————
6 N$ k7 Z; H: z0 Y7 I
版权声明:本文为CSDN博主「敖 丙」的原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接及本声明。
* M* j% ]! t& `
原文链接:https://blog.csdn.net/qq_35190492/article/details/104203466
! \3 y _0 `8 @- Z( ~
u- j+ P% w8 ?* Q/ s- p! T) h
/ t7 T$ t2 b/ k( r+ e f& f
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5