欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > MySQL面试题

MySQL面试题

2025/3/18 0:20:19 来源:https://blog.csdn.net/2301_78671299/article/details/143799535  浏览:    关键词:MySQL面试题

MySQL是一款开源关系型数据库管理系统,它利用结构化查询语言(SQL)来存储、检索和管理数据。

以MySQL递进的形式逐步理解MySQL面试题,是什么,怎么用,为什么用。

MySQL存储引擎

1、InnoDB存储引擎(默认的MySQL存储引擎)

特点

DML操作遵循ACID模型,支持事务;

行级锁,提高并发访问性能;

支持外键FOREIGN KEY约束,保证数据的完整性和正确性。

使用场景

如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含了很多的更新、删除操作,那么InnoDB存储引擎是合适的。

2、MyISAM

不支持事务,不支持外键

支持表锁,不支持行锁

访问速度快

使用场景

如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎是合适的。

CREATE TABLE your_table_name (id INT PRIMARY KEY,name VARCHAR(100)
) ENGINE=InnoDB;

3、Memory存储引擎

表数据时存储在内存中,由于受到硬件问题、或断电问题的影响,只能将这些表作为临时表或缓存使用。

特点

内存存放

hash索引(默认)

使用场景

将所有数据保存在内存中,访问速度快,通常用于临时表及缓存

存储过程定义

存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,用户可以指定存储过程的名字并给定参数(需要时)来调用执行。

delimiter//
create procedure CalculateSquare(in num int,out result int)
beginset result = num * num;
end //
delimiter;

delimiter用于更改命令结束符,以便在存储过程中使用begin...end语句,通过使用//作为新的结束符,并在存储过程中定义结束后将其改回;。

create procedure用于创建新的存储过程。

CalculateSquare是存储过程的名称。

(In num int,out result int)定义了输入和输出参数。在这个例子中,num是输入参数,result是输出参数。

begin... end之间的部分是存储过程的主体,即要执行的SQL语句。

调用存储过程

要调用上述存储过程并获取结果,需要使用CALL语句,并指定一个变量来接收输出参数的值。

SET @input = 5;
SET @output = 0;
CALL CalculateSquare(@input,@output);
SELECT @output;

MySQL语句的执行顺序

FROM子句->on->join->where->group by->having->select->distinct->union(all)->order by ->limit

数据约束

主键(primary key):物理上存储的顺序

非空(not null):此字段不允许填写空值

唯一(unique):此字段值不允许重复

默认值(default):当不填写此值时会使用默认值

外键(foreign key):维护两个表之间的联系

操作数据库SQL语句

操作数据库命令

查看所有数据库:show databases;
使用数据库:use 数据库名;
查看当前使用的数据库:select database();
创建数据库:create database 数据库名 charset=utf8;
删除数据库:drop database 数据库名;

操作数据表

(操作数据表之前要通过use打开对应的数据库)
常见数据表操作命令:查看当前数据库所有的表:show tables;
查看表结构:desc 表名;
查看表的创建语句:show create table 表名;
创建数据库表:格式:create table 表名(字段名1 类型 约束,字段名2 类型 约束,
);

删除数据库表

drop table 表名;
drop table if exists 表名;

在数据表中添加一行/多行数据

insert into 表名 values (),();
insert into 表名 (字段1,字段2,...)values (值1,值2,...)(值1,值2,...)

简单查询

select * from 表名;

修改数据

update 表名 set 字段名1=值1,字段名2=值2 where 条件

删除数据

delete from 表名 where 条件
truncate table 表名 (只删除数据)
drop table 表名 (删除所有数据和表结构)
说明:
delete --删除数据时,若新增数据,新增的id是删除的id号的后一个
truncate --删除数据后,若新增数据,是从id=1开始的

操作数据库联合查询

内连接

语法一:
select * from 表1 inner join 表2 on 表1.字段 = 表2.字段
语法二:(隐式内连接)
select * from 表1,表2 where 表1.字段=表2.字段 

左连接

语法:select * from 表1 left join 表2 on 表1.字段=表2.字段;

右连接

select * from 表1 right join 表2 on 表1.字段=表2.字段

mysql数据库优化

1、索引优化

确保使用适当索引,使用explain查询

2、查询优化

避免select*,只选取需要的列

3、数据库结构优化

使用合适的数据类型

4、配置优化

5、硬件优化

6、定时优化

7、日志和监控

开启慢查询日志来查找需要优化的查询

SQL优化

1、避免使用select*

2、使用索引

3、选择合适的数据类型

5、批量查询

减少交互次数和服务器资源开销,提高整体效率。

MySQL索引

索引是帮助MySQL高效获取数据的数据结构。

索引的优缺点

优点:

提高数据的检索效率,降低数据库的I/O成本

通过索引对数据库进行排序,降低了数据的成本,降低了CPU的消耗

被索引的列会自动进行排序,包括单列排序和组合排序,只是组合索引的排序要复杂一些。

缺点:

索引会占据磁盘的空间

索引虽然会提高查询效率,但是会降低更新表的效率。比如每次对表进行增删该操作,MySQL不仅要保存数据,还有保存或者更新对应的索引文件。

索引的使用场景

需要创建索引

1、主键自动建立唯一索引

2、频繁作为查询条件的字段应该创建索引

不需要建立索引

1、表记录太少的

2、经常进行增删改的表

创建索引

单值索引

一个索引只包含单个列,一个表可以有多个单值索引。

1、建表时可随表一起建立单值索引。

2、单独创建和删除单值索引。

创建:alter table 表名 add index 索引名(字段)或create index 索引名 on 表名(字段)

删除:drop index 索引名 on 表名

复合索引

一个索引包含多个列

1、建表时可随表一起建立复合索引

2、单独创建和删除复合索引

创建:create index 索引名 on 表名 (字段1,字段2)或alter table 表名 add index 索引名 (字段1,字段2)

删除:drop index 索引名 on 表名

索引什么时候失效

1、列类型不匹配,如果查询中使用的列与索引列的类型不匹配,例如字符串类型上使用了数值比较,那么索引将无法正常工作。

2、函数操作

3、索引列值为空,如果查询条件中使用is null或is not null操作,而索引列上存在null,那么索引将无法正常工作。

4、类型转换,如果查询中使用了某种类型转换,例如在查询中将字符串转换为数字,那么索引将不再有效。

5、当使用OR语句时,索引可能会失效。

什么是索引回表,如何避免

回表的情况

当查询涉及的列不完全在索引中,或者查询请求的列没有在索引里时,数据库会首先通过索引定位到数据所在行,然后再去对应表中查找这些完整记录。

这种过程称为“回表”,因为它所需要从索引返回到原始的数据表中去获取数据。

回表可能会导致性能下降,因为它需要额外的IO操作,从索引到表的访问。

优化:为了避免回表,可以考虑创建覆盖索引,这样数据库可以直接从索引中返回结果,无需访问表。

B+树与B树的主要区别

1、所有键值存储在叶子节点:B+树的内部节点只存储键值用于导航,而不存储实际数据。所有实际数据存储在叶子节点中。

2、叶子节点之间有链表结构:B+树的叶子节点通过指针串联成一个双向链表,以方便范围查询和顺序遍历。

3、内节点不存储实际数据:内节点只用于引导查找路径,数据只保存在叶子节点。

B+树的优势

范围查找性能优越:由于B+树的叶子节点通过链表相连,范围查找操作非常高效。只需从起始节点找到目标范围的第一个叶子节点,然后通过链表依次遍历即可。

磁盘I/O效率高:B+树的内部节点只存储键值,用于导航查找路径,节省了内存空间,并且每次查询只需要访问叶子节点,减少了磁盘I/O操作。

支持顺序遍历:B+树的叶子节点有序排列并通过链表连接,可以高效地进行顺序遍历,特别适合范围查询和排序查询的场景。

什么是事务

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有操作作为一个整体向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。

事务的操作

MySQL的事务操作主要有三种:

1、开启事务:Start Transaction或begin

2、提交事务:commit

成功结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步。

3、回滚事务:rollback

失败结束,将所有的DML语句操作历史记录全部清空。

设置MySQL的自动提交模式:

set autocommit=0 禁止自动提交

set autocommit=1 开启自动提交

事务的特性

原子性:事务是不可分割的最小操作单位,要么全部成功,要么全部失败。

一致性:事务完成时,必须所有的数据都保持一致性状态。

隔离性:数据库系统提供隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。

持久性:事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

事务出现的问题

脏读:当一个事务正在访问数据,并对数据进行修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据然后使用了这个数据。

不可重复读:值在一个事务内,多次读取同一数据。这个事务还没结束,另外一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。

幻读:在一个事务内多次查询某个符合条件的记录数量,如果前后两次查询到的记录数量不一样情况,意味着发生了幻读现象。

丢失更新:两个事务同时获取同一条记录,例如A先修改记录,B也修改记录(B不知道A修改过),B提交数据后B的修改结果覆盖了A的修改结果。

事务的隔离级别

1、读未提交(Read uncommitted)

一个事务可以读取另一个事务未提交的数据,最低级别,会造成脏读。

2、读已提交(Read committed)

一个事务要等另一个事务提交后才能读取数据,可避免脏读,会造成不可重复读。

3、可重复读(Repeatable read)

开始读取数据是,不在允许修改操作,可避免脏读,不可重复读发生,但会造成幻读。

4、串行化(Serializable)

MySQL默认隔离级别是Repeatable read

事务的传播机制

required:支持当前事务,如果没有事务,就新建一个事务。

supports:支持当前事务,如果没有事务,就以非事务的方式执行。

mandatory:支持当前事务,如果没有事务,就抛出异常。

requires_new:新建事务,如果当前存在事务,把当前事务挂起。

not_supported:以非事务方式执行,如果当前存在事务,就把当前事务挂起。

never:以非事务的方式执行,如果当前存在事务,则抛出异常。

nested:支持当前事务,如果当前事务存在,则嵌套事务,如果没有事务,就新建一个事务。

MVCC

多版本并发控制,在MySQL的InnoDB中处理并发时,不加锁和非阻塞并发读,提高读性能的一种机制。MVCC维持了数据的多个版本,让并发读写时没有冲突。

目的:就是多版本并发控制,在数据库中的实现,就是为了解决脏读和不可重复读等事务之间读写问题而诞生的,MVcc在某些场景中替代了相对的低效的锁(共享锁,排他锁),在保证了隔离性的基础上,提升了读取效率和并发性。

它的实现原理主要是依赖记录中的 3个隐式字段,undo log ,read view 来实现的。

后面三个隐含字段分别对应该行的隐含ID(DB_ROW_ID)、事务号(DB_TRX_ID,最新更新这条记录的事务ID)和回滚指针(DB_ROLL_PT,指向当前记录项的回滚的undo log记录 )。

MySQL的锁

全局锁

//使用全局锁
flush tables with read lock

执行后,整个数据库就处于只读状态,这时其它线程操作都会被阻塞。

//释放全局锁
unlock tables

会话断开,全局锁会被自动释放。

应用场景

全局锁主要应用于全库逻辑备份,这样在备份期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期不一样。

缺点

加全局锁,业务只能读数据,而不能更新数据,这样会造成业务停滞。

解决

如果数据库的引擎支持的事务支持可重复读的隔离级别,那么在备份数据库之前开启事务,会先创建Read View,然后整个事务执行期间都在用这个Read View,而且由于MVCC的支持,备份期间业务依然可以对数据进行更新操作。

表锁

//表级别的共享锁,也就是读锁
lock tables table_name read;
//表级别的排它锁,也就是写锁
lock tables table_name write;//释放锁
unlock tables

1、意向锁,当执行插入、更新、删除操作,需要先对表加上意向独占锁,然后对记录加独占锁。

意向锁的目的是为了快速判断表里是否有记录被加锁。

2、自增锁,当事务插入数据到自增列时就会触发。当某个事务在往表中插入数据时,另外一个事务必须等待上个事务执行完毕,实现主键的连续自增。

行级锁

1、Record Lock,记录锁,也就是把一条记录锁上。

2、Gap Lock,间隙锁,锁定一个范围,但是不包含记录本身。只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下的幻读。

3、Next-Key Lock,记录锁和间隙锁组合,锁定一个范围,并且锁定记录本身。

4、插入意向锁,有insert操作在行插入之前设置的一种间隙锁,当多个事务插入记录到相同索引间隙时彼此并不需要互相等待,除非插入到相同的位置。

MySQL的主从复制

MySQL主从复制是一种用于实现数据库高可用和负载均衡的机制,它允许一个MySQL主服务器(主库)将数据同步到一个或多个从服务器(从库)。这个过程可以实时或近实时进行,主要用于提高系统的读取性能、故障转移和数据备份。

怎么保证主从库中数据的一致性

异步复制:虽然MySQL默认使用异步复制,在这种模式下,主库提交事务不会后不会等待从库确认,这可能导致数据不一致。

半同步复制:在这种模式下,主库提交事务后等待至少一个从库确认接收到并写入到中继日志中,才返回给客户端。这提高了数据的一致性,但可能会引入一定延迟。

全同步复制:要求所有的从库都接收到主库的数据并且执行完成其中事务后,主库才会返回客户端,虽然这种模式下数据强一致性得到保证,但性能损耗较大。

处理数据库百万条数据,按年月日分别查询排序

1、索引优化

创建日期索引,复合索引

2、查询优化

使用范围查询,排序,限制结果集

3、分区表

按日期分区

4、缓存和视图化

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词