草庐IT

MySQL面经

fsdshuron 2023-03-28 原文

内容援引自JavaGuide、哔哩哔哩黑马程序员数据库从入门到精通,感谢各位大神原创分享

数据库Mysql

常见的关系型数据库包括mysqlSQL ServerOracle、常见的非关系型数据库RedisMongDB等。

特点

Mysql开源免费,生态完善,支持事务、高可用(读写分离、分库分表)。

基础架构:
  • 服务层:连接器、查询缓存(移除)、分析器、优化器、执行器;通用日志模块binlog
  • 存储引擎层:插件式存储引擎(为表设置存储引擎),支持InnoDBMyISAM等;InnoDB包括redologundolog日志
存储引擎

使用插件式存储引擎,默认InnoDB支持事务、行锁、外键,数据恢复(redolog),MyISAM不支持事务、采用表锁、不支持外键,不支持数据恢复。此外InnoDB主键使用聚簇索引,叶子节点保存记录,MyISAM使用非聚簇索引,叶子节点保存记录的地址,两者均为B+ Tree。

MySQL索引

用于快速查询或快速定位排序的数据结构,常见的索引结构包括Hash树、B树、B+树、红黑树。InnoDB和MyISAM均使用B+树作为索引结构。

索引优缺点

优点:加快检索速度,创建唯一索引保证数据唯一性。缺点:创建、维护索引时间开销,且索引占物理存储空间。

索引结构

  • 为什么不使用hash?
    可能出现哈希碰撞(拉链式)、不支持顺序查找和范围查找。
  • 为什么不使用B树?
    B树节点存索引和数据,B+树只有叶子节点存储索引和数据且构成双向链表,其它节点存储索引,故相同数据量下B树高度更高,查询效率更低,且不支持范围查找。
  • 为什么不使用红黑树?
    红黑树是自平衡二叉查找树,树过高造成大量的磁盘 IO。
  • B+树一般不超过3层,能存储多少数据?
    最小存储单元一页16KB,叶子节点存索引和记录,假设索引和一条记录占1KB,则一页可存16K/1K=16条记录,非叶子节点存索引和指针,假设主键索引为bigint占8字节,指针占6字节,则一个节点可存16k/(8+4)=1170 个指针,两层的B+树可存1170*16条记录,三层的B+树可存1170*1170*16条记录,约两千万数据量。

索引的类别

​ 索引相关的概念包括聚簇索引、非聚簇索引、主键索引、辅助索引、唯一索引、普通索引、联合索引、覆盖索引、前缀索引、全文索引。
​ 聚簇索引,叶子节点保存索引和记录,非聚簇索引叶子节点保存索引和记录相关值(记录地址或主键),且InnoDB存储引擎非聚簇索引不一定需要回表查询(覆盖索引)
​ 主键索引,非null,不可重复,没有显示指定时检查是否存在非null的唯一索引,存在则将该字段作为主键索引否则默认创建6字节的自增索引。设计表时不建议使用过长字段作为主键,不建议使用非单调字段作为主键(引发索引频繁分裂,这解释了为什么不宜使用UUID作为主键)。
​ 联合索引,多个字段一起创建索引,索引使用要求满足最左匹配原则,缺失停止匹配,范围查询右侧字段停止匹配

# 创建(a,b,c)联合索引 等值查询中a、ab、abc均可使用索引,b、bc、c不可使用索引,全部为等值查询时字段顺序对是否使用索引不产生影响;
# 以下语句a,b走索引,c不走索引,建议将区分度高的字段放最左侧以过滤更多数据
select * from t where a=1 and b > 1 and c=1;  
# 如果是建立(a,c,b)联合索引,则a,b,c都走索引

​ 索引下推:非聚簇索引遍历过程中,根据索引中包含的字段过滤不符合条件的记录,减少回表次数。

正确使用索引

  • 是否有必要创建索引,很少查询的表没必要创建索引,频繁更新的字段不适合创建索引;
  • 为哪些字段创建索引,为查询字段,排序字段和分组字段创建索引,优先创建联合索引且区分度高的字段放在左侧(可能产生覆盖索引效果,避免回表,且可以过滤较多记录),字符串类型的字段可优先考虑前缀索引;
  • 避免索引失效,如隐式类型转换、在字段上进行函数操作、or逻辑中某条件字段没有索引则涉及的索引全部失效

索引优化

  • SQL提示,在SQL语句中加入人为提示优化操作use indexignore indexforce index,注意use index仅是建议,不代表优化器会选择的执行计划;
  • 插入数据,批量插入、手动提交事务、主键顺序插入
  • 主键 优化,减少主键长度、主键递增、避免对主键进行修改
  • update优化,InnoDB行锁针对索引,有索引时锁行,没有索引锁表
#id有主键索引,锁行;
update student set no = '123' where id = 1; 
#name没有索引,锁表
update student set no = '123' where name = 'test'; 
  • order by优化,多字段排序且一个升序一个降序,要注意创建索引时索引的升序和降序
  • limit优化,覆盖索引、子查询、联表查询
# 优化前
SELECT * FROM xxx limit 1000000,20
# 子查询优化
SELECT * FROM xxx WHERE ID >=(select id from xxx limit 1000000, 1) limit 20;
# 联表优化
SELECT * FROM xxx a JOIN (select id from xxx limit 1000000, 20) b ON a.ID = b.id;
MySQL事务

ACID原则,原子性、一致性、隔离性、持久性

​ 其中一致性是目的,原子性是指要么都执行,要么都不执行,隔离性是指并发事务的独立性,持久性是指事务被提交后可持久化。

并发事务的问题,脏读、不可重复读、幻读

​ 脏读是指事务A读取事务B未提交的数据,不可重复读是指事务A多次读某条记录的读取结果不同,幻读是指幻读指事务A读取某一范围的数据行,事务B在该范围内插入了新行,事务A再读取该范围的数据行时,出现幻影行

并发事务控制,锁+MVCC

​ MySQL中通过读写锁实现并发控制,读锁为共享锁,写锁为排它锁,读读兼容,读写或写写互斥。按粒度MySQL锁又可划分为表锁和行锁,其中表锁不会出现死锁,锁冲突概率高,并发性能低;行锁针对索引字段加锁,会出现死锁,并发度高,行锁 又包括记录锁、间隙锁、临键锁。

  • 行锁发生死锁的场景描述
事务A 事务B
1、delete from xxxx where id = 1;
2、delete from xxxx where id = 2;
3、delete from xxxx where id = 2;
事务A等事务B释放记录2行锁
4、delete from xxxx where id = 1;
事务B等事务A释放记录1行锁
  • MVCC 多版本并发控制

​ MySQL的隔离级别包括读未提交(脏读、不可重复读、幻读风险),读已提交(不可重复读,幻读风险),可重复读(默认隔离级别,幻读风险)和可串行化。特殊的,InnoDB实现的可重复读隔离级别可解决幻读风险,快照读由MVCC机制保证,当前读使用临键锁保证。
​ 在读已提交和可重复读隔离级别下,执行普通select会使用一致性非锁定读MVCC,读记录的快照数据;执行insertdeleteupdateselect...lock in share modeselect...for update会使用锁定读,读取记录的最新数据,并对读取到的记录加锁,即当前读。
​ MVCC机制的实现依赖隐藏字段、Read Viewundo log,InnoDB存储引擎为记录添加默认主键(主键不存在且不存在非空的唯一索引时默认添加)、事务id回滚指针3个隐藏字段;读已提交隔离级别下每次select查询前创建Read View,可重复读隔离级别下事务开始第一次select前创建Read View,Read View用于可见性判断,主要包括m_low_limit_idm_up_limit_idm_idsm_creator_trx_id字段,根据数据可见性算法(比较记录的事务id和Read View中字段)若当前记录对该事务不可见则使用回滚指针进行数据回滚。

三大日志

​ Mysql日志包括查询日志、慢查询日志、错误日志和binlog日志、redolog日志、undolog日志,其中binlog支持数据备份和主从同步,rodolog支持数据 恢复以保证持久性,undolog支持事务回滚以保证原子性和支持MVCC多版本并发控制。

binlog - MySQL

​ binlog日志支持数据备份和主从同步,包括三种记录格式statementrowmixed,其中statement记录SQL语句(获得时间戳等SQL语句容易导致数据备份不一致或主从数据不一致),row记录SQL语句和操作数以规避以上问题,但占用内存,折中方案mixed由MySQL判断是否会引起数据不一致,选择statement或row。
​ binlog的刷盘策略:1)事务提交将binlog cache写入到page cache,系统自行决定刷盘;2)事务提交进行刷盘;3)折中方案,提交事务binlog cache写入到page cache,提交N个事务进行刷盘;

redolog - InnoDB

​ redolog日志支持数据恢复,保证事务的持久性。Mysql数据以页16KB为单位(页、段、区、表),查询记录时从磁盘加载数据页放入缓冲池Buffer pool中,后续查询优先在缓冲池中查找,未命中再从磁盘加载,减少IO开销。更新记录时,更新缓存数据,将数据页上的更新记录到redolog buffer中,根据一定的刷盘策略进行持久化。
​ rodolog刷盘策略:1)事务提交不进行刷盘(Mysql实例挂或宕机可能会有一秒数据的丢失);2)事务提交将redolog buffer写入page cache中(Mysql实例挂没有数据丢失,宕机可能会有一秒的数据丢失);3)事务提交刷盘(Mysql实例挂或宕机不会有数据丢失)。兜底措施后台线程每隔1s将redolog buffer写入到page cache,然后进行刷盘;redolog buffer占用内存到一定阈值后台线程主动刷盘。
​ 为什么要使用redolog,而不是直接将修改的数据页刷盘?通常数据更新只影响数据页中的少量记录,且数据页刷盘是随机写,刷盘成本高。采用redolog记录更新属于顺序写,刷盘成本低,有利于提高数据库的并发能力。
两阶段提交:redolog prepare - binlog - redolog commit。

  • redolog-宕机-binlog,主从结构中,主使用redolog数据恢复,从使用binlog数据恢复,主从数据不一致。
  • binlog-宕机-redolog,主从结构中主使用redolog,从使用binlog,主从数据不一致。
  • 两阶段提交,redolog prepare - 宕机 - binlog - redolog commit,redolog有事务记录,binlog没有事务记录,事务回滚;redolog prepare - binlog - 宕机 - redolog commit,redolog有事务记录,binlog也有对应的事务记录,提交事务恢复 数据。

undolog

​ undolog日志支持事务回滚和MVCC,保证事务的原子性和隔离性。

MySQL执行计划

explain sql

有关MySQL面经的更多相关文章

  1. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  2. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

  3. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

  4. ruby-on-rails - 当我通过 rvm 使用 rails3 时,如何在 ubuntu 上安装 mysql2 gem? - 2

    我正在尝试绕过rails配置这个极其复杂的迷宫。到目前为止,我设法在ubuntu上设置了rvm(出于某种原因,ruby在ubuntu存储库中已经过时了)。我设法建立了一个Rails项目。我希望我的测试项目使用mysql而不是mysqlite。当我尝试“rakedb:migrate”时,出现错误:“!!!缺少mysql2gem。将其添加到您的Gemfile:gem'mysql2'”当我尝试“geminstallmysql”时,出现错误,告诉我需要为安装命令提供参数。但是,参数列表很大,我不知道该选择哪些。如何通过在ubuntu上运行的rvm和mysql获取rails3?谢谢。

  5. Centos7-yum安装mysql-修改密码-无密码登录-安全配置 - 2

    目录1、yum安装mysql修改密码(1)在mysql里面修改(2)第二种方式,利用mysqladmin修改密码2、没有密码,登录mysql修改密码3、mysql的安全设置1、yum安装mysql在CentOS中默认安装有MariaDB(MySQL的一个分支),安装完成之后可以直接覆盖MariaDB。rpm-qa|grepmariadb查询是否安装了mariadbrpm-e--nodepsmariadb-libs-5.5.60-1.el7_5.x86_64卸载mariadwgethttp://dev.mysql.com/get/mysql57-community-release-el7-11.

  6. ruby - 安装 dm-mysql-adapter 时出错 - 2

    我是Ruby的新手。我安装了DataMapper并且正在尝试安装dm-mysql-adapter-1.0.2gem。但是当我尝试安装时,出现以下错误。我正在使用ubuntu操作系统。vinoth@vinoth-laptop:~/Downloads$geminstalldm-mysql-adapter-1.0.2----with-mysql-lib=/usr/lib/mysql----with-mysql-conf=/usr/bin/mysqlWARNING:Installingto~/.gemsince/home/vinoth/gemsand/home/vinoth/gems/bina

  7. ruby-on-rails - gem 列表中的 mysql2 gem 但获取项目找不到 gem - 2

    我目前正在构建一个需要mysql2gem的RoR项目。我成功安装了gem。因为它出现在我的gem列表中。[root@vc2cmmka035538nsimple_cms]#gemlist***LOCALGEMS***actionmailer(3.2.3)actionpack(3.2.3)activemodel(3.2.3)activerecord(3.2.3)activeresource(3.2.3)activesupport(3.2.14,3.2.3)arel(3.0.2)bigdecimal(1.1.0)builder(3.2.2,3.0.0)bundler(1.1.5)c2c_li

  8. ruby - 如何在 heroku 中使用自己的 mysql 数据库服务器? - 2

    我想使用托管在我自己服务器上的mysql数据库。我已经更改了DATABASE_URL和SHARED_DATABASE_URL配置变量以指向我的服务器,但它仍在尝试连接到heroku的amazonaws服务器。我该如何解决? 最佳答案 根据Herokudocumentation,更改DATABASE_URL是正确的方法。Ifyouwouldliketohaveyourrailsapplicationconnecttoanon-Herokuprovideddatabase,youcantakeadvantageofthissamemec

  9. ruby - 如何设置mysql2时区选项以删除查询警告 - 2

    使用mysql2做查询总是得到警告/usr/local/lib/ruby/gems/1.9.1/gems/mysql2-0.2.6/lib/active_record/connection_adapters/mysql2_adapter.rb:463:warning::database_timezoneoptionmustbe:utcor:local-defaultingto:local我确实看到了时区选项Mysql2现在支持两个时区选项::database_timezone-thisisthetimezoneMysql2willassumefieldsarealreadystored

  10. ruby-on-rails - 将 Rails/ClearDB App 推送到 Heroku 错误 'Can' t 连接到 '127.0.0.1' 上的 MySQL 服务器 - 2

    每次我跑:gitpushherokumaster我收到以下错误:Running:rakeassets:precompilerakeaborted!Can'tconnecttoMySQLserveron'127.0.0.1'我在运行rails-vRails3.2.11和ruby-vruby1.9.3p194(2012-04-20revision35410)[x86_64-darwin12.2.0]我已经通过HerokuCLI安装了ClearDB,它似乎工作正常,但我无法找出这个错误。这是我用于生产的yml:production:adapter:mysql2encoding:utf8hos

随机推荐