mysql面试相关

1、列举常见的关系型数据库和非关系型都有那些?
常见关系型数据库:mysql oracle db2

非关系型数据库:mongodb redis


2、MySQL常见数据库引擎及比较?

常用引擎:
myisam:不支持事务,支持表锁
innodb:支持事务,支持行锁和表锁,默认采用航级锁。


3、简述数据三大范式?

第一:确保每列保持原子性,即每个字段必须是不可拆分的最小单元
例如:创建一个地址的字段时,就应该将其划分为省市区这三个字段,这就满足了上述的原子性。


第二:表中的每列都和主键相关,一个表里只能存在一种数据,不可把多种数据保存在同一张数据库表中。
例如:即订单里存在客户和商品的信息,建议将客户和商品的数据拆分开
即创建两张表 ,一个放订单和客户的信息,一个放订单和商品的信息!

第三:确保每列都和主键直接相关。而不是间接相关。
例如:订单数据表,将客户编号作为一个外键关联字段和订单表建立联系。
而不可以在订单表中添加客户的其他信息。(例如姓名,公司等)

4、什么是事务?MySQL如何支持事务?

是应用程序中一系列严密的操作,所有操作必须成功完成,否则该事务中每个操作都会被撤销,回到上一个状态。指的是作为单个逻辑单元执行的一系列操作。

mysql的事务:存在4个特性:acid 保证数据的安全

下面为python里的开启方式:

start transaction:
try:
update db set money=100 where name='erha';
update db set money=0 where name = 'enhen';
except:
rollback
else:
commit

原生的事务:

begin;

....

commit;


5、简述数据库设计中一对多和多对多的应用场景?
一对多:一个用户存在多个订单
多对多:一个订单里有多个商品,一个商品被多个订单包含

6、数据库中锁的划分:

锁的介绍:类似于python里的互斥锁一般,是控制防止一个用户在占用某种资源的时候,其他用户做出影响本次用户数据的操作或者导致数据费完整性和非一致性问题发生的一种手段。

1)、根据锁的级别 划分为

共享锁:针对同一条数据,多个读操作可以同时进行,同时为同一个数据 加上共享锁,而不会互相影响,共享锁只针对于update的时候才去使用,在未对update操作提交之前,其他事务只能获取最新的记录而不能去修改数据。 select * from test where id = 3 lock in share mode;

排它锁:当前的写操作没有完成前,阻断其他的写锁和读锁。

mysql innodb引擎默认的修改语句:update,delete,insert都会 自动加上排他锁

2)、根据锁的粒度划分;
行锁:开销大,加锁慢,会出现死锁,锁定力度最小,锁的冲突概率最低,并发高 lock tables unlock tables
表锁:开销小,加锁块,不会出现死锁,加锁力度大,冲突概率高,并发度低
页面锁:开销和加锁时间介于表所和行锁之间,会出现死锁,锁定力度在二者之间,并发度一般。

3)、悲观锁和乐观锁
共享锁和排他锁都属于悲观锁。
悲观锁:每次去那数据的时候都会认为数据会被别人修改,所以每次拿数据的时候需要加上锁,这样其他人只能等当前锁释放后才能对数据进行增删改查。
乐观所:认为每次拿数据的时候别人都不会修改,所以不会上锁,但是会在提交更新后判断一下在此期间别人有没有去更新这个数据。使用与读多写少的情况,提高吞吐量。




8、简述触发器、函数、视图、存储过程?

视图:通过定义一个虚拟的表,保存下来,下次直接使用,可以不需要重复查询。
create view 视图 as select * from xxxxx
在硬盘里,视图只存在表结构文件,没有表数据文件。
视图虽说用来查询,但是可以通过修改视图 里的数据来影响原始表的数据。因此尽量不要修改视图里的数据,同时,想去修改数据,还涉及到了跨部门沟通的问题,一般通过修改sql语句去替代。

触发器:在满足所设定的条件下,会在我们对数据库的增删改 的时候自动触发相应的sql语句!

create trigger 触发器名字 after insert on 表名 for each row
begin
sql语句
end 在增加数据之后触发

create trigger 触发器名字 before update on t1 for each row
begin
sql语句
end 在修改数据之前


事务:保证了我们操作的数据的安全。
四个特性:
原子性,一致性,隔离性,持久性
简称acid

使用:
start transaction; 开启事务
try:
update user set bala = 90 where name = 'asda';
update user set bala =80 where name = 'dasd';
except:
rollback; 回滚
else:
commit 只有提交后,数据才能真正写入硬盘


存储过程:
一组可编程的函数,为了完成特定功能的sql语句集,经过编译创建后保存在数据库中,用户可以通过使用指定的存储过程的名字并给定参数时区调用执行。
为什么要用:
1)将重复性很高的一些操作,封装到存储过程里,简化了对sql语句的操作
2)统一了接口,确保数据的安全
不过相对于oracle数据库而言,其的存储过程较弱,使用较少


mysql里的函数:
类似于存储过程,不过其存在返回值
可以自定义函数,也可以直接使用内置函数

常见的内置函数:
pi()圆周率
rand()0-1的随机数
round()四舍五入

聚合函数:
avg() 平均值
count()计数
min()
max()
sum()

日期函数:
curdata() 当前时间
curtime() 当前日期


9、MySQL索引种类

普通索引:进加速查询
唯一索引:加速查询+列值唯一(可以有null)
主键索引:加速查询+列值唯一(不可以有null)+表中只有一个
组合索引:多列值组成的索引
全文索引:对文本的内容进行分词


10、索引在什么情况下遵循最左前缀的规则?
不想写

11、主键和外键的区别?
主键是用来加速查询的,作为关键字同时唯一确定这条表记录的。二外键是用来关联表之间的关系的


外键的性能问题:

数据库只要维护外键的内部管理
外键等于把数据的一致性事务实现,全部交给数据库服务器完成
当涉及到外键字段的增删,更新操作后,需要触发相关操作去检查,而不得不消耗资源
外键还会因为需要请求对其他表内部加锁而容易出现死锁情况


12、MySQL常见的函数?

abs()
pi() 圆周率
avg()
sum()

13、列举创建索引但是无法命中索引的8种情况。

14、如何开启慢日志查询?

什么是慢查询:mysql提供的一种日志记录,用来记录响应时间超过阀值的sql语句。具体指超过long_query_timme的sql,会被记录到慢查询日志中。其默认值为10秒。
默认是不开启的,需要手动去设定这个参数,如果不是调优需要的话,一般不建议启动该参数。开启的话会带来一定的新能影响。


15、数据库导入导出命令(结构+数据)?

不想弄


16、数据库优化方案?

数据库结构设计:
对大型的数据需要提前进行分库分表 垂直切分,水平切分,分库

表结构设计的问题:
1)、能够使用数字类型的 字段尽量选择数字类型而不用字符串类型;
引擎在处理查询和连接会逐个标胶字符串里的 每一个字符,对于数字型的只要比较一次即可。
2)、对于char和varchar类型字符类型要合理使用。
前者查询块,但是占用空间多,密码、用户名等长度变化不大的字段可以选择char;后者查询相对较慢,但是节省空间,对于评论等长度变化大的数据可以选择varchar.
3)字段的长度在满足需要的前提下,应该尽量设的较短一些,可以提高查询的效率。建立索引的时候也可以减少资源的浪费。

查询的优化:
注意事项如下:
尽量使用简单的查询,避免使用表连接
使用子查询的时候会创建临时表,会比链接(join)和联合查询(union)慢。
查询的数据只有一行的时候,使用limit 1,数据过多的时候,适当设定limit,分页查询
不要使用order by rand() 其用来查询随机的表中一条记录

尽量避免查询的时候在where 后对字段进行null判断,会导致mysql放弃使用索引而使用全局扫描。可以在设置时,将null 改为默认值为0

读写分离框架的实现:
解决业务上读性能的瓶颈


使用缓存:
缓存的开发简单,成本比从库少很多,大部分的读都可以先去缓存里找。


17、char和varchar的区别?

char 为定长字段 ,即给定了位数,不够的话自动空格补全,显示的时候自动将末尾的空格去掉,但是在硬盘里还是按之前的数据存储
varchar 为变长字段

就上述而言,varchar节省硬盘空间,是利用到了给数据加报头来标识数据的长度。

二者的储存方式:char对英文ascii占用1个字节,汉子占用两个字节
varchar英文与汉字均占用两个字节,二者存储的数据类型均非unicode数据类型

18、简述MySQL的执行计划?

explain + 查询的sql语句 可以显示sql执行信息的参数,根据参数可以进行sql优化。

19、在对name做了唯一索引前提下,简述以下区别:

select * from tb where name = ‘Oldboy-Wupeiqi’ 

select * from tb where name = ‘Oldboy-Wupeiqi’ limit 1

20、1000w条数据,使用limit offset 分页时,为什么越往后翻越慢?如何解决?

limit m n 表示从第m行+1 开始,往后取 n条数据
limit m offset n 表示从第n+1行开始,往后取m条数据


解决思路:先查主键,在分页
select * from db where id in (select id from db limit 10 offset 20)

即查询的时候最好通过传递pk值去减少offset的值,主键最好为int,且具备自增。也可以添加order by,orderby字段需要建立索引。

limit分页优化方法:
1)、子查询优化法
找出第一条数据,大于等于这条数据的id就是想要获取的数据
缺点:数据必须为连续的,可以说不能存在where条件,因其会筛选数据,导致数据失去连续性。一般而言,偏移量在1000以上使用子查询可以有效提高性能

2)、limit限制优化法
把limit偏移量限制为低于摸个数。超过这个数据没得数据。记得alibab的dba是这样做的。

20、使用索引的好处与弊端:
概念:给表加上主键,就将其格式装换为索引平衡树的概念

加上索引查询会变快,比直接按常规逻辑查询快上很多。

缺陷:会导致写入、修改、删除变慢

二者是一种平衡的,增删改数据都会改变平衡树中各节点的索引数据内容,破坏树的结构。每次数据改变后,通过某种机制去重新梳理树的结构以保证其的正确,会带来不小的性能开销。

20、聚焦索引 和非聚焦索引:

聚焦索引;利用主键值直接在平衡树里按主键节点查询到数据
非聚焦索引:先找到记录对应的主键值,在使用主键 的值通过聚焦索引去找到需要的数据。
即:聚焦索引(主键)是通往真实数据的唯一路径。


21、什么是索引合并?

22、什么是覆盖索引?

23、简述数据库读写分离?

其实就是将数据库分为了主从库,一个用来写数据,其他多个完成读的操作。
二者之间通过某种机制实现数据同步,常见的数据库架构。

大多数互联网业务,读多写少,数据库的读会先成为数据库的瓶颈,往往希望提高数据库的读性能,清除读写锁冲突从而提升数据库的写性能,采用读写分离架构。

一句话,读写分离是用来解决数据库的读性能瓶颈的。
在实际的应用场景下,数据量大,高并发,高可用,高一致性,需要注意:
区分数据库是读,还是写,研发的难度增加
还得要实现读连接池的故障自动转移
主从的一致性需要考虑。


可以的话,先去考虑使用缓存。这是一种常见的架构。读写分离是通过读多个数据库分担数据库读压力,缓存是通过对缓存的使用来减少读数据库的读压力。

为什么:缓存的使用成本比从库少,
缓存的开发容易,大部分的读操作都可以先去缓存,找不到再去数据库查找。


如果退一步说,使用缓存后任然无法解决读的瓶颈时,可以选择读写分离架构。

说道缓存,必须考虑的是高可用性,不然缓存一旦挂了,所有的流量同时聚集在数据库上,会造成缓存雪崩的现象。

常见的数据库瓶颈其实是数据容量的瓶颈。例如 订单表,数量只增不减,历史数据要留存,非常容易造成性能的瓶颈,对于这样的问题,读写分离和缓存往往都不合适,合理的做法应该是数据库库水平切分。
作为一种常见的数据库架构,是一种通过算法,将数据库进行分割的架构。
一个水平切分集群中的每个数据库,通常为一个分片。每个分片的数据没有重合,所有分片里的数据并集组成全部的数据。 提高数据库的写性能,降低单库容量,采用水平切分。

24、简述数据库分库分表?(水平、垂直)

数据库分库:把一堆数据放到不同的数据库中保存

数据库分表:
垂直切分:不同功能,不同模块的数据放到不同的表中,同一模块的数据量太大会照成性能瓶颈。
水平切分:垂直切分解决不了大表的瓶颈,同一个表中数据量过大,需要对其水平切分
简单理解:垂直切分是分为不同的模块表
水平切分是同一模块下的多个表


25、sql注入攻击原理,代码成面实现防止sql注入

原理:通过前段的表单提交的数据中携带sql语句,欺骗服务器,在后端对数据库进行存储时,执行恶意的sql语句。

出现的地方:
在使用pymysql模块时,操作数据库是是使用字符串拼接产生的sql语句,就会出现sql注入漏洞。

防止:
使用pymysql时,不要使用字符串拼接,而是使用execute的方法,pymysql
的模块已经对数据进行了处理,不会出现sql注入
永远不要相信前端提交的任何数据,要严格校验
不要把机密的信息中介存放,而要进过加密以后存放。
不要使用管理员权限的数据库进行连接,为每个应用使用单独的权限进行数据库连接。

原文地址:https://www.cnblogs.com/changwenjun-666/p/11406065.html