我有一个程序员朋友, 我们都叫他回龙观大叔, 因为他所在公司经营不善, 被动离职。我们一起听听他的故事.
回龙观大叔的自述
距离上次面试过去两天了, 但仍未能抹平心灵的创伤, 上次面试问了我几个mysql问题, 都没能很好的答上来.
比如:
代码语言:javascript复制1. mysql B 树是什么结构?
2. mysql 事务是怎么是实现的?
3. 你先回去等通知吧
最后我心都凉了, 质问了面试官几句, 问这些对工作有啥用? 有真正考察到我的实力吗? 随后我就生气走了.
回龙观某小区出租屋中, 喝着上周剩下的半瓶可乐, 坐在电脑前边刷微信边找工作, 吐槽着人生不公与公司的冷漠.
代码语言:javascript复制嗯? juejin 又有活动了? 小册免费学?
作为薅羊毛上瘾的我来说, 自然也不会错过这根羊毛, 买个 mysql 小册吧, 时代变了, 得学点基础原理应付应付面试了.
狂磕 mysql 第一面
客户端与服务器是怎么连接
未来的面试官如果问我: 客户端与服务器是怎么连接的呀?
我会先漏出一丝微笑以示尊重, 然后答:
mysql有三种连接方式, TCP/IP、命名管道和共享内存和Unix域套接字文件, 但是我们一般都使用的是 TCP/IP 模式的, 因为后面两个只能客户端与服务端在同一机器上, 但是作为核心基础数据库, 我们一般都分开部署的.
指定默认端口 3306, 端口可以在启动 mysql 的时候使用 -P 指定, max_connections 指定同时最大连接数
mysql是怎么接收请求并处理的
未来面试官肯定的点了点头, 再问我: mysql是怎么接收请求并处理的
我再答:
mysql处理请求一共分为三大步骤 连接管理、解析与优化、存储引擎.
顺便找面试官要张纸, 我要把整体结构画出来!!!
image.png
面试官你看最上面对外连接管理这个框, 一个请求进来, 首先要建立连接(TCP三次握手), mysql 会从线程池里面分配一个线程来处理当前请求
数据库也肯定需要账号密码, 需要检测账号密码合法性和权限, 如果鉴权失败就会返回错误信息, 处理线程释放到池等待下一次请求.
比如面试官你提个问题, 我背这么多东西, 得想想是哪块的知识, 你看这个解析优化就是做这个的. 一个 sql 语句给到 mysql, mysql 得分析下 sql 吧, 定位到具体的表和条件.
有时候别人已经查过了, 就没必要再查一次, 查询缓存模块就是干这个用的, 但是缓存在mysql中还是有些问题, 他是根据传进来的sql生成的缓存key, sql语句大小写、随机函数都会 cache miss, 有严重的锁争用, 这个在新版本已经被移除掉了.
查询优化是根据行数、实际查询进行调整优化, 核心有限过滤大部分数据.
存储引擎是我们存储数据方式的不同而使用不同的引擎, 一般我们默认使用 innodb 引擎
创建表可以指定, 也可以使用 default-storage-engine 指定默认引擎
关于 mysql 字符集
面试官不耐烦的听完讲了上面问题后, 问: mysql的字符集遇到过什么问题? 不要偏离主题.
我会答:
utf8mb3:阉割过的utf8字符集,只使用1~3个字节表示字符。
utf8mb4:正宗的utf8字符集,使用1~4个字节表示字符。
在MySQL中utf8是utf8mb3的别名,utf8就意味着使用1~3个字节来表示一个字符,如果使用4字节编码一个字符的情况,比如存储一些emoji表情啥的,那请使用utf8mb4, 英文、数字等只使用一个字符即可表示.
字符集和字符编码区别
字符集和字符编码的关系,字符集是规范,字符编码是规范的具体实现;字符集规定了符号和二进制代码值的唯一对应关系,但是没有指定具体的存储方式;unicode、ASCII、GB2312、GBK都是字符集;其中ASCII、GB2312、GBK既是字符集也是字符编码;注意不混淆这两者区别;而unicode的具体实现有UTF-8,UTF-16,UTF-32。
Innodb 存储行数据底层原理
存储引擎是管理组织我们数据的地方, 存储有很多类型, 目前一般主要使用 Innodb, 它的流行并不是偶然, 支持事务、行锁、聚簇索引等都有很多优势, 面试官之后会问的, 我就先不说了.
Innodb 会为表加一些隐藏列:
列名 | 作用 |
---|---|
DB_ROW_ID | 行ID,唯一标识一条记录 |
DB_TRX_ID | 事务ID |
DB_ROLL_PTR | 回滚指针 |
InnoDB表对主键的生成策略:优先使用用户自定义主键作为主键,如果用户没有定义主键,则选取一个Unique键作为主键,如果表中连Unique键都没有定义的话,则InnoDB会为表默认添加一个名为row_id的隐藏列作为主键
Compact格式存储
一个不定长字符串存储占用空间( varchar(xx) )
- 真实数据
- 真实数据占用字节的长度
- NULL值标识,如果该列有NOT NULL属性则可以没有这部分存储空间
VARCHAR(M)类型的列最多可以占用 65535 个字节, 但是我们有额外的空间占用, 最多可存储 65532 个字符(长度占用两个字符、NULL标记占用1个)
如果指定 NOT NULL, 可使用 65533 个字节, utf8mb4 最多有4个字节, 最多存储 16383 个字符(65533/4).
MySQL中磁盘和内存交互的基本单位是页,也就是说MySQL是以页为基本单位来管理存储空间的,我们的记录都会被分配到某个页中存储。而一个页的大小一般是16KB,也就是16384字节, 建议单行记录不要超过此大小, 否则会发生行溢出, 超出的部分放到其他页称为页溢出.
一个页需要132字节空间记录信息, 每个条需要最多 27 字节记录额外信息, 每page页最少展示两行记录, 所以需要额外减掉
顺利通关
好啦好啦~ 估计面试官会让我等会儿~ 进入二面.
《(第二回合)回龙观大叔狂磕mysql》敬请期待~