数学建模社区-数学中国

标题: 拼多多面试问了数据库基础知识,今天分享出来 [打印本页]

作者: 杨利霞    时间: 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
1.jpg 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
2.jpg * c: }$ a; r. z  L) b& n. @
这里需要注意的是,我们数据库的客户端太久没响应,连接器就会自动断开了,这个时间参数是wait_timeout控制住的,默认时长为8小时。
3 D6 R1 k' ]- H' X% `0 H2 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 n7 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 }! u7 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 _
3.jpg
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