⾯试常问的20个数据库⾼频⾯试题详解!
进了互联⽹公司,整天也就是搬砖,等到了⾯试的时候,发现数据库⽅⾯,忘得⼀塌糊涂,抽时间整理了⼀些数据库⽅⾯的题。欢迎⼤家向我推荐你在⾯试过程中遇到的问题,我会把⼤家推荐的问题添加到下⾯的常⽤⾯试题清单中供⼤家参考。
事务四⼤特性(ACID)原⼦性、⼀致性、隔离性、持久性?
原⼦性(Atomicity)
原⼦性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应⽤到数据库,如果操原⼦性是指事务包含的所有操作要么全部成功,要么全部失败回滚
作失败则不能对数据库有任何影响。
⼀致性(Consistency)
事务开始前和结束后,数据库的完整性约束没有被破坏。⽐如A向B转账,不可能A扣了钱,B却没收到。
事务开始前和结束后,数据库的完整性约束没有被破坏。⽐如A向B转账,不可能A扣了钱,B却没收到
隔离性(Isolation)
隔离性是当多个⽤户并发访问数据库时,⽐如操作同⼀张表时,数据库为每⼀个⽤户开启的事务,不能被其他事务的操作所⼲扰,多个并发事务之间要相互隔离。
扰,多个并发事务之间要相互隔离
同⼀时间,只允许⼀个事务请求同⼀数据,不同的事务之间彼此没有任何⼲扰。⽐如A正在从⼀张银⾏卡中取钱,在A取钱的过程结束前,B 不能向这张卡转账。
持久性(Durability)
关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到
关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。 持久性(Durability)
持久性是指⼀个事务⼀旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
会丢失提交事务的操作
事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别?
从理论上来说, 事务应该彼此完全隔离, 以避免并发事务所导致的问题,然⽽, 那样会对性能产⽣极⼤的影响, 因为事务必须按顺序运⾏, 在
在实际开发中, 为了提升性能, 事务会以较低的隔离级别运⾏, 事务的隔离级别可以通过隔离事务属性指定。
实际开发中, 为了提升性能, 事务会以较低的隔离级别运⾏, 事务的隔离级别可以通过隔离事务属性指定
事务的并发问题
1、脏读
脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
不可重复读:事务 A 多次读取同⼀数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同⼀数据2、不可重复读
时,结果因此本事务先后两次读到的数据结果会不⼀致。
幻读:幻读解决了不重复读,保证了同⼀个事务⾥,查询的结果都是事务开始时的状态(⼀致性)。
3、幻读
例如:事务T1对⼀个表中所有的⾏的某个数据项做了从“1”修改为“2”的操作 这时事务T2⼜对这个表中插⼊了⼀⾏数据项,⽽这个数据项的数值还是为“1”并且提交给数据库。 ⽽操作事务T1的⽤户如果再查看刚刚修改的数据,会发现还有跟没有修改⼀样,其实这⾏是从事务T2中添加的,就好像产⽣幻觉⼀样,这就是发⽣了幻读。
⼩结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满⾜条件的⾏,⼩结
解决幻读需要锁表。
事务的隔离级别
事务隔离级别脏读不可重复读幻读
读未提交 read-uncommitted是是是
不可重复读 read-committed否是是
可重复读 repeatable-read否否是
串⾏化 serializable否否否
读未提交读未提交:另⼀个事务修改了数据,但尚未提交,⽽本事务中的SELECT会读到这些未被提交的数据脏读脏读
不可重复读
不可重复读:事务 A 多次读取同⼀数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同⼀数据时,结果因此本事务先后两次读到的数据结果会不⼀致。
可重复读可重复读:在同⼀个事务⾥,SELECT的结果是事务开始时时间点的状态,因此,同样的SELECT操作读到的结果会是⼀致的。但是,会有幻读幻读现象
串⾏化
串⾏化:最⾼的隔离级别,在这个隔离级别下,不会产⽣任何异常。并发的事务,就像事务是在⼀个个按照顺序执⾏⼀样MySQL默认的事务隔离级别为repeatable-read
MySQL ⽀持 4 中事务隔离级别
MySQL ⽀持 4 中事务隔离级别.事务的隔离级别要得到底层数据库引擎的⽀持, ⽽不是应⽤程序或者框架的⽀持.Oracle ⽀持的 2 种事务隔离级别:READ_COMMITED , SERIALIZABLE
补充:
1. SQL规范所规定的标准,不同的数据库具体的实现可能会有些差异
2. MySQL中默认事务隔离级别是“可重复读”时并不会锁住读取到的⾏事务隔离级别事务隔离级别:未提交读时未提交读时,写数据只会锁住相应的⾏。事务隔离级别为事务隔离级别为:可重复读时可重复读时,写数据会锁住整张表。事务隔离级别为事务隔离级别为:串⾏化时串⾏化时,读写数据都会锁住整张表。
隔离级别越⾼隔离级别越⾼,越能保证数据的完整性和⼀致性越能保证数据的完整性和⼀致性,但是对并发性能的影响也越⼤,鱼和熊掌不可兼得啊。对于多数应⽤程序,可以优先对于多数应⽤程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,⽽且具有较好的并发性能考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,⽽且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应⽤程序采⽤悲观锁或乐观锁来控制。
MySQL 常见的三种存储引擎(InnoDB 、MyISAM 、MEMORY )的区别?
MySQL 存储引擎MyISAM 与InnoDB 如何选择
MySQL有多种存储引擎,每种存储引擎有各⾃的优缺点,可以择优选择使⽤:MyISAM 、InnoDB 、MERGE 、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE 、FEDERATED 、ARCHIVE 、CSV 、BLACKHOLE 。虽然MySQL⾥的存储引擎不只是MyISAM与InnoDB这两个,但常⽤的就是两个虽然MySQL⾥的存储引擎不只是MyISAM与InnoDB这两个,但常⽤的就是两个。两种存储引擎的⼤致区别表现在
两种存储引擎的⼤致区别表现在:InnoDB⽀持事务,MyISAM不⽀持InnoDB⽀持事务,MyISAM不⽀持,这⼀点是⾮常之重要。事务是⼀种⾼级的处理⽅式,如在⼀些列增删改中只要哪个出错还可以回滚还原,⽽MyISAM就不可以了。MyISAM适合查询以及插⼊为主的应⽤
MyISAM适合查询以及插⼊为主的应⽤。InnoDB适合频繁修改以及涉及到安全性较⾼的应⽤InnoDB适合频繁修改以及涉及到安全性较⾼的应⽤。InnoDB⽀持外键,MyISAM不⽀持。
从MySQL5.5.5以后,InnoDB是默认引擎从MySQL5.5.5以后,InnoDB是默认引擎。InnoDB不⽀持FULLTEXT类型的索引。idea和idear的区别
InnoDB中不保存表的⾏数InnoDB中不保存表的⾏数,如select count(*) from table 时,InnoDB需要扫
描⼀遍整个表来计算有多少⾏,但是MyISAM只要简单的读出保存好的⾏数即可。注意的是,当count(*)语句包含where条件时MyISAM也需要扫描整个表。
对于⾃增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段⼀起建⽴联合索引。DELETE FROM table 时,InnoDB不会重新建⽴表,⽽是⼀⾏⼀⾏的 删除,效率⾮常慢InnoDB不会重新建⽴表,⽽是⼀⾏⼀⾏的 删除,效率⾮常慢。MyISAM则会重建表MyISAM则会重建表。InnoDB⽀持⾏锁(某些情况下还是锁整表,如 update table set a=1 where user like '%lee%'。
关于MySQL 数据库提供的两种存储引擎,MyISAM 与InnoDB 选择使⽤:
INNODB会⽀持⼀些关系数据库的⾼级功能INNODB会⽀持⼀些关系数据库的⾼级功能,如事务功能和⾏级锁,MyISAM不⽀持如事务功能和⾏级锁,MyISAM不⽀持。MyISAM的性能更优,占⽤的存储空间少
MyISAM的性能更优,占⽤的存储空间少,所以,选择何种存储引擎,视具体应⽤⽽定。
如果你的应⽤程序⼀定要使⽤事务,毫⽆疑问你要选择INNODB引擎
如果你的应⽤程序⼀定要使⽤事务,毫⽆疑问你要选择INNODB引擎。但要注意,INNODB的⾏级锁是有条件的。在where条件没有使⽤主键时,照样会锁全表。⽐如DELETE FROM mytable这样的删除
语句。
MyISAM索引和数据是分开的,⽽且其索引是压缩的,可以更如果你的应⽤程序对查询性能要求较⾼,就要使⽤MyISAM了
如果你的应⽤程序对查询性能要求较⾼,就要使⽤MyISAM了。MyISAM索引和数据是分开的,⽽且其索引是压缩的,可以更
MyISAM拥有全⽂索引的功能,这查询性能明显优于INNODB。压缩后的索引也能节约⼀些磁盘空间。MyISAM拥有全⽂索引的功能,这好地利⽤内存
好地利⽤内存。所以它的查询性能明显优于INNODB
可以极⼤地优化LIKE查询的效率。
可以极⼤地优化LIKE查询的效率
有⼈说MyISAM只能⽤于⼩型应⽤,其实这只是⼀种偏见。如果数据量⽐较⼤,这是需要通过升级架构来解决,⽐如分表分库,⽽不是单纯地依赖存储引擎。
现在⼀般都是选⽤innodb了,主要是MyISAM的全表锁,读写串⾏问题,并发效率锁表,效率低,MyISAM对于读写密集型应⽤⼀现在⼀般都是选⽤innodb了,主要是MyISAM的全表锁,读写串⾏问题,并发效率锁表,效率低
般是不会去选⽤的。
MEMORY存储引擎
MEMORY是MySQL中⼀类特殊的存储引擎。它使⽤存储在内存中的内容来创建表,⽽且数据全部放在内存中。这些特性与前⾯的MEMORY是MySQL中⼀类特殊的存储引擎。它使⽤存储在内存中的内容来创建表,⽽且数据全部放在内存中
两个很不同。
每个基于MEMORY存储引擎的表实际对应⼀个磁盘⽂件。该⽂件的⽂件名与表名相同,类型为frm类型。该⽂件中只存储表的结构。⽽其数据⽂件,都是存储在内存中,这样有利于数据的快速处理,提⾼整个表的效率。值得注意的是,服务器需要有⾜够的内存来维持MEMORY存储引擎的表的使⽤。如果不需要了,可以释放内存,甚⾄删除不需要的表。
MEMORY默认使⽤哈希索引。速度⽐使⽤B型树索引快。当然如果你想⽤B型树索引,可以在创建索
引时指定。
MEMORY⽤到的很少,因为它是把数据存到内存中,如果内存出现异常就会影响数据。如果重启或者关机,所有数据都会消注意,MEMORY⽤到的很少,因为它是把数据存到内存中,如果内存出现异常就会影响数据。如果重启或者关机,所有数据都会消MEMORY的表的⽣命周期很短,⼀般是⼀次性的。
失。因此,基于MEMORY的表的⽣命周期很短,⼀般是⼀次性的
MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各⾃的适⽤场景?
事务处理上⽅⾯
强调的是性能,每次查询具有原⼦性,其执⾏数度⽐InnoDB类型更快,但是不提供事务⽀持
不提供事务⽀持。
MyISAM:强调的是性能
MyISAM
提供事务⽀持事务,外部键等⾼级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能⼒(crash recovery InnoDB:提供事务⽀持事务,外部键等⾼级数据库功能
InnoDB
capabilities)的事务安全(transaction-safe (ACID compliant))型表。
锁级别
MyISAM:只⽀持表级锁mysql语句的执行顺序
只⽀持表级锁,⽤户在操作MyISAM表时,select,update,delete,insert语句都会给表⾃动加锁,如果加锁以后的表MyISAM
满⾜insert并发的情况下,可以在表的尾部插⼊新的数据。
InnoDB:⽀持事务和⾏级锁,是innodb的最⼤特⾊。⾏锁⼤幅度提⾼了多⽤户并发操作的新能。但是InnoDB的⾏锁,只是在InnoDB
WHERE的主键是有效的,⾮主键的WHERE都会锁全表的。
查询语句不同元素(where、jion、limit、group by、having等等)执⾏先后顺序?
1.查询中⽤到的关键词主要包含六个,并且他们的顺序依次为 select--from--where--group by--having--order by
其中select和from是必须的,其他关键词是可选的,这六个关键词的执⾏顺序 与sql语句的书写顺序并不是⼀样的,⽽是按照下⾯的顺序来执⾏
from:需要从哪个数据表检索数据
where:过滤表中数据的条件
group by:如何将上⾯过滤出的数据分组
having:对上⾯已经分组的数据进⾏过滤的条件
select:查看结果集中的哪个列,或列的计算结果
order by :按照什么样的顺序来查看返回的数据
2.from后⾯的表关联,是⾃右向左解析 ⽽where条件的解析顺序是⾃下⽽上的。
也就是说,在写SQL⽂的时候,尽量把数据量⼩的表放在最右边来进⾏关联(⽤⼩表去匹配⼤表),⽽把能筛选出⼩量数据的条件放在where语句的最左边 (⽤⼩表去匹配⼤表)
什么是临时表,临时表什么时候删除?
时表可以⼿动删除:
DROP TEMPORARY TABLE IF EXISTS temp_tb;复制代码
临时表只在当前连接可见,当关闭连接时,MySQL会⾃动删除表并释放所有空间。因此在不同的连接中可以创建同名的临时表,并且操作属于本连接的临时表
并且操作属于本连接的临时表。
增加关键字TEMPORARY,如:
创建临时表的语法与创建表语法类似,不同之处是增加关键字TEMPORARY
CREATE TEMPORARY TABLE tmp_table (
NAME VARCHAR (10) NOT NULL,
time date NOT NULL
);
select * from tmp_table;复制代码
MySQL B+Tree索引和Hash索引的区别?
Hash索引结构的特殊性,其检索效率⾮常⾼,索引的检索可以⼀次定位;
B+树索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问;
那为什么⼤家不都⽤Hash索引⽽还要使⽤B+树索引呢?
Hash索引
1. Hash索引仅仅能满⾜"=","IN"和"<=>"查询,不能使⽤范围查询,因为经过相应的Hash算法处理之后的Hash值的⼤⼩关系,并不能保
mysql下载方法证和Hash运算前完全⼀样;
2. Hash索引⽆法被⽤来避免数据的排序操作,因为Hash值的⼤⼩关系并不⼀定和Hash运算前的键值完全⼀样;
3. Hash索引不能利⽤部分索引键查询,对于组合索引,Hash索引在计算Hash值的时候是组合索引键合并后再⼀起计算Hash值,⽽不
是单独计算Hash值,所以通过组合索引的前⾯⼀个或⼏个索引键进⾏查询的时候,Hash索引也⽆法被利⽤;
4. Hash索引在任何时候都不能避免表扫描,由于不同索引键存在相同Hash值,所以即使取满⾜某个Hash键值的数据的记录条数,也⽆
法从Hash索引中直接完成查询,还是要回表查询数据;
5. Hash索引遇到⼤量Hash值相等的情况后性能并不⼀定就会⽐B+树索引⾼。
B+Tree索引
MySQL中,只有HEAP/MEMORY引擎才显⽰⽀持Hash索引。
MySQL中,只有HEAP/MEMORY引擎才显⽰⽀持Hash索引importdata用法
常⽤的InnoDB引擎中默认使⽤的是B+树索引
常⽤的InnoDB引擎中默认使⽤的是B+树索引,它会实时监控表上索引的使⽤情况,如果认为建⽴哈希索引可以提⾼查询效率,则⾃动
在InnoDB中默认开启⾃适应哈希索引),通过观察搜索模式,MySQL会利⽤
在内存中的“⾃适应哈希索引缓冲区”建⽴哈希索引(在InnoDB中默认开启⾃适应哈希索引
index key的前缀建⽴哈希索引,如果⼀个表⼏乎⼤部分都在缓冲池中,那么建⽴⼀个哈希索引能够加快等值查询。
B+树索引和哈希索引的明显区别是:
因为只需要经过⼀次算法即可到相应的键值;当然了,这个前提是,键值都是如果是等值查询,那么哈希索引明显有绝对优势
如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过⼀次算法即可到相应的键值;当然了,这个前提是,键值都是唯⼀的。如果键值不是唯⼀的,就需要先到该键所在位置,然后再根据链表往后扫描,直到到相应的数据;
唯⼀的。如果键值不是唯⼀的,就需要先到该键所在位置,然后再根据链表往后扫描,直到到相应的数据
如果是范围查询检索,这时候哈希索引就毫⽆⽤武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办如果是范围查询检索,这时候哈希索引就毫⽆⽤武之地了
法再利⽤索引完成范围查询检索;
哈希索引没办法利⽤索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);同理,哈希索引没办法利⽤索引完成排序
哈希索引也不⽀持多列联合索引的最左匹配规则;
哈希索引也不⽀持多列联合索引的最左匹配规则
在有⼤量重复键值情况下,哈希索引的效率也是极低的,因为存在所B+树索引的关键字检索效率⽐较平均,不像B树那样波动幅度⼤,在有⼤量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。
谓的哈希碰撞问题
在⼤多数场景下,都会有范围查询、排序、分组等查询特征,⽤B+树索引就可以了。
在⼤多数场景下,都会有范围查询、排序、分组等查询特征,⽤B+树索引就可以了
sql查询语句确定创建哪种类型的索引,如何优化查询
性能优化过程中,选择在哪个列上创建索引是最重要的步骤之⼀,可以考虑使⽤索引的主要有两种类型的列:在where⼦句中出现性能优化过程中,选择在哪个列上创建索引是最重要的步骤之⼀
的列,在join⼦句中出现的列。
考虑列中值的分布,索引的列的基数越⼤,索引的效果越好。
对字符串列进⾏索引,应该指定⼀个前缀长度,可节省⼤量索引空间,提升查询速度。
使⽤短索引,如果对字符串列进⾏索引,应该指定⼀个前缀长度
bushy利⽤最左前缀,顾名思义,就是最左优先,在多列索引,有体现:(ALTER TABLE people ADD INDEX lname_fname_age
利⽤最左前缀
(lame,fname,age);),所谓最左前缀原则就是先要看第⼀列,在第⼀列满⾜的条件下再看左边第⼆列,以此类推
降低写操作的性能。
不要过度建索引,只保持所需的索引。每个额外的索引都要占⽤额外的磁盘空间,并降低写操作的性能
不要过度建索引,只保持所需的索引
索引越多,所花的时间越长。
在修改表的内容时,索引必须进⾏更新,有时可能需要重构,因此,索引越多,所花的时间越长
MySQL只对⼀下操作符才使⽤索引
MySQL只对⼀下操作符才使⽤索引:<,<=,=,>,>=,between,in
以及某些时候的like(不以通配符%或_开头的情形)。
以及某些时候的like
聚集索引和⾮聚集索引区别?
聚合索引(clustered index) / ⾮聚合索引(nonclustered index)
根本区别
表记录的排列顺序和与索引的排列顺序是否⼀致。
聚集索引和⾮聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否⼀致
聚集索引
聚集索引表记录的排列顺序和索引的排列顺序⼀致,所以查询效率快,只要到第⼀个索引值记录,其余就连续性的记录在物理也⼀样连续存放。聚集索引对应的缺点就是修改慢,因为为了保证表中记录的物理和索引顺序⼀致,在记录插⼊的时候,会对数据页重新排序。
重新排序
聚集索引类似于新华字典中⽤拼⾳去查汉字,拼⾳检索表于书记顺序都是按照a~z排列的,就像相同的逻辑顺序于物理顺序⼀样,当你需要查a,ai两个读⾳的字,或是想⼀次寻多个傻(sha)的同⾳字时,也许向后翻⼏页,或紧接着下⼀⾏就得到结果了。
⾮聚集索引
异步通信的作用⾮聚集索引制定了表中记录的逻辑顺序,但是记录的物理和索引不⼀定⼀致,两种索引都采⽤B+树结构,⾮聚集索引的叶⼦层并不和实际数据页相重叠,⽽采⽤叶⼦层包含⼀个指向表中的记录在数据页中的指针⽅式。⾮聚集索引层次多,不会造成数据重排。
和实际数据页相重叠,⽽采⽤叶⼦层包含⼀个指向表中的记录在数据页中的指针⽅式。⾮聚集索引层次多,不会造成数据重排
⾮聚集索引类似在新华字典上通过偏旁部⾸来查询汉字,检索表也许是按照横、竖、撇来排列的,但是由于正⽂中是a~z的拼⾳顺序,所以就类似于逻辑地址于物理地址的不对应。同时适⽤的情况就在于分组,⼤数⽬的不同值,频繁更新的列中,这些情况即不适合聚集索引。有哪些锁(乐观锁悲观锁),select 时怎么加排它锁?
悲观锁(Pessimistic Lock)
悲观锁的特点是先获取锁,再进⾏业务操作,即“悲观”的认为获取锁是⾮常有可能失败的,因此要先确保获取锁成功再进⾏业务操
悲观锁的特点是先获取锁,再进⾏业务操作
通常所说的“⼀锁⼆查三更新”即指的是使⽤悲观锁。通常来讲在数据库上的悲观锁需要数据库本⾝提供⽀持,即通过常⽤的作。通常所说的“⼀锁⼆查三更新”即指的是使⽤悲观锁。通常来讲在数据库上的悲观锁需要数据库本⾝提供⽀持,即通过常⽤的select … for update操作来实现悲观锁。当数据库执⾏select for update时会获取被select中的数据⾏的⾏锁,因此其他并发执⾏的select … for update操作来实现悲观锁
select for update如果试图选中同⼀⾏则会发⽣排斥(需要等待⾏锁被释放),因此达到锁的效果。select for update获取的⾏锁会在当前事务结束时⾃动释放,因此必须在事务中使⽤。
这⾥需要注意的⼀点是不同的数据库对select for update的实现和⽀持都是有所区别的,例如oracle⽀持select for update no wait,表⽰如果拿不到锁⽴刻报错,⽽不是等待,MySQL就没有no wait这个选项。另外MySQL还有个问题是select for update语句执⾏中所
MySQL还有个问题是select for update语句执⾏中所有扫描过的⾏都会被锁上,这⼀点很容易造成问题。因此如果在MySQL中⽤悲观锁务必要确定⾛了索引,⽽不是全表扫描。
有扫描过的⾏都会被锁上,这⼀点很容易造成问题。因此如果在MySQL中⽤悲观锁务必要确定⾛了索引,⽽不是全表扫描
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论