Mysql面试大全,看完可以吊打面试官!!!
Posted 我是springmeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql面试大全,看完可以吊打面试官!!!相关的知识,希望对你有一定的参考价值。
最近有小伙伴出去面试,感觉总是被mysql的问题吊打。最近小孟整理一些mysql的面试题,希望能帮助到你。
推荐优质文章:
1,送你50个项目
3,学生信息系统开源
目录
Q1:JDBC 连接数据库步骤(以 MYSQL 为例)
1、加载 JDBC 驱动程序:
通过 Class 类的 forName 方法实现,并将驱动地址放进去
成功加载后,会将 Driver 类的实例注册到 DriverManager 类中。
2、提供 JDBC 连接的 URL 、创建数据库的连接
•要连接数据库,需要向 java.sql.DriverManager 请求并获得 Connection 对象,
该对象就代表一个数据库的连接。
•使用 DriverManager 的 getConnectin()方法传入指定的欲连接的数据库的路径、数
据库的用户名和密码。
Connection con=DriverManager.getConnection(url , username , password);
&&&:"jdbc:mysql://localhost/test?user=root&password=123&useUnicode=tr
ue&characterEncoding=utf-8”;
3、创建一个 Statement •要执行 SQL 语句,必须获得 java.sql.Statement 实例
•执行静态 SQL 语句。通常通过 Statement 实例实现。
•执行动态 SQL 语句。通常通过 PreparedStatement 实例实现。
String sql = “”;
Statement st = con.createStatement() ;
PreparedStatement pst = con.prepareStatement(sql) ;
4、执行 SQL 语句
Statement 接口提供了 executeQuery、executeUpdate、execute 三种方法
executeQuery:执行 select 语句,返回 ResultSet 结果集
ResultSet rst = pst.executeQuery(); • executeUpdate:执行 insert、update、delete 语句
pst.executeUpdate();
5、关闭 JDBC 对象
操作完成以后要把所有使用的 JDBC 对象全都关闭,以释放 JDBC 资源。
Q2:如何进行Mysql的优化
1、SELECT语句务必指明字段名称
SELECT *增加很多不必要的消耗(cpu、io、内存、网络带宽);增加了使用覆盖索引的可能性;当表结构发生改变时,前断也需要更新。所以要求直接在select后面接上字段名。
2、当只需要一条数据的时候,使用limit 1
这是为了使EXPLAIN中type列达到const类型
3、如果排序字段没有用到索引,就尽量少排序
4、如果限制条件中其他字段没有索引,尽量少用or
or两边的字段中,如果有一个不是索引字段,而其他条件也不是索引字段,会造成该查询不走索引的情况。很多时候使用 union all 或者是union(必要的时候)的方式来代替“or”会得到更好的效果。
5、尽量用union all代替union
union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。当然,union all的前提条件是两个结果集没有重复数据。
Q3:MySQL 8.0 的新特性,太实用了!
1、隐藏索引
隐藏索引的特性对于性能调试非常有用。在 8.0 中,索引可以被“隐藏”和“显示”。当一个索引隐藏时,它不会被查询优化器所使用。
也就是说,我们可以隐藏一个索引,然后观察对数据库的影响。如果数据库性能有所下降,就说明这个索引是有用的,于是将其“恢复显示”即可;如果数据库性能看不出变化,说明这个索引是多余的,可以删掉了。
隐藏一个索引的语法是:
ALTER TABLE t ALTER INDEX i INVISIBLE;
恢复显示该索引的语法是:
ALTER TABLE t ALTER INDEX i VISIBLE;
当一个索引被隐藏时,我们可以从 show index
命令的输出中看到,该索引的 Visible
属性值为 NO
。
注意:当索引被隐藏时,它的内容仍然是和正常索引一样实时更新的,这个特性本身是专门为优化调试使用。如果你长期隐藏一个索引,那还不如干脆删掉,因为毕竟索引的存在会影响插入、更新和删除的性能。
2、设置持久化
MySQL 的设置可以在运行时通过 SET GLOBAL
命令来更改,但是这种更改只会临时生效,到下次启动时数据库又会从配置文件中读取。
MySQL 8 新增了 SET PERSIST
命令,例如:
SET PERSIST max_connections = 500;
MySQL 会将该命令的配置保存到数据目录下的 mysqld-auto.cnf
文件中,下次启动时会读取该文件,用其中的配置来覆盖缺省的配置文件。
3、UTF-8 编码
从 MySQL 8 开始,数据库的缺省编码将改为 utf8mb4
,这个编码包含了所有 emoji 字符。
多少年来我们使用 MySQL 都要在编码方面小心翼翼,生怕忘了将缺省的 latin 改掉而出现乱码问题。从此以后就不用担心了。
Q4:MySQL 的逻辑架构了解吗?
第⼀层是服务器层,主要提供连接处理、授权认证、安全等功能。
第⼆层实现了 MySQL 核⼼服务功能,包括查询解析、分析、优化、缓存以及⽇期和时间等所有内置函数,所有跨存储引擎的功能都在这⼀层实现,例如存储过程、触发器、视图等。
第三层是存储引擎层,存储引擎负责 MySQL 中数据的存储和提取。服务器通过 API 与存储引擎通信, 这些接⼝屏蔽了不同存储引擎的差异,使得差异对上层查询过程透明。除了会解析外键定义的 InnoDB 外,存储引擎不会解析 SQL,不同存储引擎之间也不会相互通信,只是简单响应上层服务器请求。
Q5:谈⼀谈 MySQL 的读写锁
在处理并发读或写时,可以通过实现⼀个由两种类型组成的锁系统来解决问题。这两种类型的锁通常被称为共享锁和排它锁,也叫读锁和写锁。读锁是共享的,相互不阻塞,多个客户在同⼀时刻可以同时读取同⼀个资源⽽不相互⼲扰。写锁则是排他的,也就是说⼀个写锁会阻塞其他的写锁和读锁,确保在给定时间内只有⼀个⽤户能执⾏写⼊并防⽌其他⽤户读取正在写⼊的同⼀资源。
在实际的数据库系统中,每时每刻都在发⽣锁定,当某个⽤户在修改某⼀部分数据时,MySQL 会通过锁定防⽌其他⽤户读取同⼀数据。写锁⽐读锁有更⾼的优先级,⼀个写锁请求可能会被插⼊到读锁队列的前⾯,但是读锁不能插⼊到写锁前⾯。
Q6:MySQL 的锁策略有什么?
表锁是MySQL中最基本的锁策略,并且是开销最⼩的策略。表锁会锁定整张表,⼀个⽤户在对表进⾏写操作前需要先获得写锁,这会阻塞其他⽤户对该表的所有读写操作。只有没有写锁时,其他读取的⽤户 才能获取读锁,读锁之间不相互阻塞。
⾏锁可以最⼤程度地⽀持并发,同时也带来了最⼤开销。InnoDB 和 XtraDB 以及⼀些其他存储引擎实现了⾏锁。⾏锁只在存储引擎层实现,⽽服务器层没有实现。
Q7:数据库死锁如何解决?
死锁是指多个事务在同⼀资源上相互占⽤并请求锁定对⽅占⽤的资源⽽导致恶性循环的现象。当多个事 务试图以不同顺序锁定资源时就可能会产⽣死锁,多个事务同时锁定同⼀个资源时也会产⽣死锁。
为了解决死锁问题,数据库系统实现了各种死锁检测和死锁超时机制。越复杂的系统,例如InnoDB 存储引擎,越能检测到死锁的循环依赖,并⽴即返回⼀个错误。这种解决⽅式很有效,否则死锁会导致出现⾮常慢的查询。还有⼀种解决⽅法,就是当查询的时间达到锁等待超时的设定后放弃锁请求,这种⽅ 式通常来说不太好。InnoDB ⽬前处理死锁的⽅法是将持有最少⾏级排它锁的事务进⾏回滚。
死锁发⽣之后,只有部分或者完全回滚其中⼀个事务,才能打破死锁。对于事务型系统这是⽆法避免的,所以应⽤程序在设计时必须考虑如何处理死锁。⼤多数情况下只需要重新执⾏因死锁回滚的事务即可。
Q8:事务是什么?
事务是⼀组原⼦性的 SQL 查询,或者说⼀个独⽴的⼯作单元。如果数据库引擎能够成功地对数据库应⽤该组查询的全部语句,那么就执⾏该组查询。如果其中有任何⼀条语句因为崩溃或其他原因⽆法执⾏, 那么所有的语句都不会执⾏。也就是说事务内的语句要么全部执⾏成功,要么全部执⾏失败。
Q9:事务有什么特性?
原⼦性 atomicity
⼀个事务在逻辑上是必须不可分割的最⼩⼯作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于⼀个事务来说不可能只执⾏其中的⼀部分。
数据库总是从⼀个⼀致性的状态转换到另⼀个⼀致性的状态。
隔离性 isolation
针对并发事务⽽⾔,隔离性就是要隔离并发运⾏的多个事务之间的相互影响,⼀般来说⼀个事务所做的修改在最终提交以前,对其他事务是不可⻅的。
持久性 durability
⼀旦事务提交成功,其修改就会永久保存到数据库中,此时即使系统崩溃,修改的数据也不会丢失。
Q10:MySQL 的隔离级别有哪些?
未提交读 READ UNCOMMITTED
在该级别事务中的修改即使没有被提交,对其他事务也是可⻅的。事务可以读取其他事务修改完但未提交的数据,这种问题称为脏读。这个级别还会导致不可重复读和幻读,性能没有⽐其他级别好很多,很 少使⽤。
提交读 READ COMMITTED
多数数据库系统默认的隔离级别。提交读满⾜了隔离性的简单定义:⼀个事务开始时只能"看⻅"已经提 交的事务所做的修改。换句话说,⼀个事务从开始直到提交之前的任何修改对其他事务都是不可⻅的。也叫不可重复读,因为两次执⾏同样的查询可能会得到不同结果。
可重复读 REPEATABLE READ(MySQL默认的隔离级别)
可重复读解决了不可重复读的问题,保证了在同⼀个事务中多次读取同样的记录结果⼀致。但还是⽆法 解决幻读,所谓幻读指的是当某个事务在读取某个范围内的记录时,会产⽣幻⾏。InnoDB 存储引擎通过多版本并发控制MVCC 解决幻读的问题。
可串⾏化 SERIALIZABLE
最⾼的隔离级别,通过强制事务串⾏执⾏,避免幻读。可串⾏化会在读取的每⼀⾏数据上都加锁,可能导致⼤量的超时和锁争⽤的问题。实际应⽤中很少⽤到这个隔离级别,只有⾮常需要确保数据⼀致性且 可以接受没有并发的情况下才考虑该级别。
Q11:MVCC 是什么?
MVCC 是多版本并发控制,在很多情况下避免加锁,⼤都实现了⾮阻塞的读操作,写操作也只锁定必要的⾏。
InnoDB 的MVCC 通过在每⾏记录后⾯保存两个隐藏的列来实现,这两个列⼀个保存了⾏的创建时间,⼀个保存⾏的过期时间间。不过存储的不是实际的时间值⽽是系统版本号,每开始⼀个新的事务系统版 本号都会⾃动递增,事务开始时刻的系统版本号会作为事务的版本号,⽤来和查询到的每⾏记录的版本号进⾏⽐较。
REPEATABLE READ |
READ |
UNCOMMITTED |
SERIALIZABLE |
Q12:谈⼀谈 InnoDB
InnoDB 是 MySQL 的默认事务型引擎,⽤来处理⼤量短期事务。InnoDB 的性能和⾃动崩溃恢复特性使得它在⾮事务型存储需求中也很流⾏,除⾮有特别原因否则应该优先考虑 InnoDB。
InnoDB 的数据存储在表空间中,表空间由⼀系列数据⽂件组成。MySQL4.1 后 InnoDB 可以将每个表的数据和索引放在单独的⽂件中。
REPEATABLE |
READ ,并通过间隙锁策略防⽌幻读,间隙锁使 InnoDB 不仅仅锁定查询涉及的⾏,还会对索引中的间隙进⾏锁定防⽌幻⾏的插⼊。
InnoDB 表是基于聚簇索引建⽴的,InnoDB 的索引结构和其他存储引擎有很⼤不同,聚簇索引对主键查询有很⾼的性能,不过它的⼆级索引中必须包含主键列,所以如果主键很⼤的话其他所有索引都会很⼤,因此如果表上索引较多的话主键应当尽可能⼩。
InnoDB 的存储格式是平***⽴的,可以将数据和索引⽂件从⼀个平台复制到另⼀个平台。
InnoDB 内部做了很多优化,包括从磁盘读取数据时采⽤的可预测性预读,能够⾃动在内存中创建加速读操作的⾃适应哈希索引,以及能够加速插⼊操作的插⼊缓冲区等。
Q13:谈⼀谈 MyISAM
MySQL5.1及之前,MyISAM 是默认存储引擎,MyISAM 提供了⼤量的特性,包括全⽂索引、压缩、空间函数等,但不⽀持事务和⾏锁,最⼤的缺陷就是崩溃后⽆法安全恢复。对于只读的数据或者表⽐较⼩、可以忍受修复操作的情况仍然可以使⽤ MyISAM。
.MYD |
.MYI |
MyISAM 将表存储在数据⽂件和索引⽂件中,分别以 和作为扩展名。MyISAM 表可以包含动态或者静态⾏,MySQL 会根据表的定义决定⾏格式。MyISAM 表可以存储的⾏记录数⼀般受限于可⽤磁盘空间或者操作系统中单个⽂件的最⼤尺⼨。
MyISAM 对整张表进⾏加锁,读取时会对需要读到的所有表加共享锁,写⼊时则对表加排它锁。但是在表有读取查询的同时,也⽀持并发往表中插⼊新的记录。
对于MyISAM 表,MySQL 可以⼿动或⾃动执⾏检查和修复操作,这⾥的修复和事务恢复以及崩溃恢复的概念不同。执⾏表的修复可能导致⼀些数据丢失,⽽且修复操作很慢。
对于 MyISAM 表,即使是 BLOB 和 TEXT 等⻓字段,也可以基于其前 500 个字符创建索引。MyISAM 也⽀持全⽂索引,这是⼀种基于分词创建的索引,可以⽀持复杂的查询。
MyISAM 设计简单,数据以紧密格式存储,所以在某些场景下性能很好。MyISAM 最典型的性能问题还是表锁问题,如果所有的查询⻓期处于 Locked 状态,那么原因毫⽆疑问就是表锁。
Q14:谈⼀谈 Memory
如果需要快速访问数据且这些数据不会被修改,重启以后丢失也没有关系,那么使⽤ Memory 表是⾮常有⽤的。Memory 表⾄少要⽐ MyISAM 表快⼀个数量级,因为所有数据都保存在内存,不需要磁盘IO,Memory 表的结构在重启后会保留,但数据会丢失。
Memory 表适合的场景:查找或者映射表、缓存周期性聚合数据的结果、保存数据分析中产⽣的中间数据。
Memory 表⽀持哈希索引,因此查找速度极快。虽然速度很快但还是⽆法取代传统的基于磁盘的表, Memory 表使⽤表级锁,因此并发写⼊的性能较低。它不⽀持 BLOB 和 TEXT 类型的列,并且每⾏的⻓度是固定的,所以即使指定了 VARCHAR 列,实际存储时也会转换成CHAR,这可能导致部分内存的浪费。
如果 MySQL 在执⾏查询的过程中需要使⽤临时表来保持中间结果,内部使⽤的临时表就是 Memory 表。如果中间结果太⼤超出了Memory 表的限制,或者含有 BLOB 或 TEXT 字段,临时表会转换成MyISAM 表。
Q15:查询执⾏流程是什么?
简单来说分为五步:① 客户端发送⼀条查询给服务器。② 服务器先检查查询缓存,如果命中了缓存则⽴刻返回存储在缓存中的结果,否则进⼊下⼀阶段。③ 服务器端进⾏ SQL 解析、预处理,再由优化器
⽣成对应的执⾏计划。④ MySQL 根据优化器⽣成的执⾏计划,调⽤存储引擎的 API 来执⾏查询。⑤ 将结果返回给客户端。
Q16:VARCHAR 和 CHAR 的区别?
VARCHAR ⽤于存储可变字符串,是最常⻅的字符串数据类型。它⽐ CHAR 更节省空间,因为它仅使⽤必要的空间。VARCHAR 需要 1 或 2 个额外字节记录字符串⻓度,如果列的最⼤⻓度不⼤于 255 字节则只需要 1 字节。VARCHAR 不会删除末尾空格。
VARCHAR 适⽤场景:字符串列的最⼤⻓度⽐平均⻓度⼤很多、列的更新很少、使⽤了 UTF8 这种复杂字符集,每个字符都使⽤不同的字节数存储。
CHAR 是定⻓的,根据定义的字符串⻓度分配⾜够的空间。CHAR 会删除末尾空格。
CHAR 适合存储很短的字符串,或所有值都接近同⼀个⻓度,例如存储密码的 MD5 值。对于经常变更的数据,CHAR 也⽐ VARCHAR更好,因为定⻓的 CHAR 不容易产⽣碎⽚。对于⾮常短的列,CHAR 在存储空间上也更有效率,例如⽤ CHAR 来存储只有 Y 和 N 的值只需要⼀个字节,但是 VARCHAR 需要两个字节,因为还有⼀个记录⻓度的额外字节。
Q17:DATETIME 和 TIMESTAMP 的区别?
DATETIME 能保存⼤范围的值,从 1001~9999 年,精度为秒。把⽇期和时间封装到了⼀个整数中,与时区⽆关,使⽤ 8 字节存储空间。
TIMESTAMP 和 UNIX 时间戳相同,只使⽤ 4 字节的存储空间,范围⽐ DATETIME ⼩得多,只能表示1970 ~2038 年,并且依赖于时区。
Q18:数据类型有哪些优化策略?
更⼩的通常更好
⼀般情况下尽量使⽤可以正确存储数据的最⼩数据类型,更⼩的数据类型通常也更快,因为它们占⽤更 少的磁盘、内存和 CPU 缓存。
尽可能简单
简单数据类型的操作通常需要更少的 CPU 周期,例如整数⽐字符操作代价更低,因为字符集和校对规则使字符相⽐整形更复杂。应该使⽤ MySQL 的内建类型 date、time 和 datetime ⽽不是字符串来存储⽇期和时间,另⼀点是应该使⽤整形存储 IP 地址。
尽量避免 NULL
通常情况下最好指定列为 NOT NULL,除⾮需要存储 NULL值。因为如果查询中包含可为 NULL 的列对MySQL 来说更难优化,可为 NULL 的列使索引、索引统计和值⽐较都更复杂,并且会使⽤更多存储空间。当可为 NULL 的列被索引时,每个索引记录需要⼀个额外字节,在MyISAM 中还可能导致固定⼤⼩的索引变成可变⼤⼩的索引。如果计划在列上建索引,就应该尽量避免设计成可为 NULL 的列。
Q19:索引有什么作⽤?
索引也叫键,是存储引擎⽤于快速找到记录的⼀种数据结构。索引对于良好的性能很关键,尤其是当表中数据量越来越⼤时,索引对性能的影响愈发重要。在数据量较⼩且负载较低时,不恰当的索引对性能 的影响可能还不明显,但数据量逐渐增⼤时,性能会急剧下降。
索引⼤⼤减少了服务器需要扫描的数据量、可以帮助服务器避免排序和临时表、可以将随机 IO 变成顺序 IO。但索引并不总是最好的⼯具,对于⾮常⼩的表,⼤部分情况下会采⽤全表扫描。对于中到⼤型的表,索引就⾮常有效。但对于特⼤型的表,建⽴和使⽤索引的代价也随之增⻓,这种情况下应该使⽤分区技术。
在MySQL中,⾸先在索引中找到对应的值,然后根据匹配的索引记录找到对应的数据⾏。索引可以包括⼀个或多个列的值,如果索引包含多个列,那么列的顺序也⼗分重要,因为 MySQL 只能使⽤索引的最左前缀。
Q20:谈⼀谈 MySQL 的 B-Tree 索引
⼤多数 MySQL 引擎都⽀持这种索引,但底层的存储引擎可能使⽤不同的存储结构,例如 NDB 使⽤ T- Tree,⽽ InnoDB 使⽤ B+ Tree。
B-Tree 通常意味着所有的值都是按顺序存储的,并且每个叶⼦⻚到根的距离相同。B-Tree 索引能够加快访问数据的速度,因为存储引擎不再需要进⾏全表扫描来获取需要的数据,取⽽代之的是从索引的根节点开始进⾏搜索。根节点的槽中存放了指向⼦节点的指针,存储引擎根据这些指针向下层查找。通过
⽐较节点⻚的值和要查找的值可以找到合适的指针进⼊下层⼦节点 以上是关于Mysql面试大全,看完可以吊打面试官!!!的主要内容,如果未能解决你的问题,请参考以下文章