MYSQL面试常见问题

mysql搜索引擎

MyISAM:不支持事务、外键,非聚簇索引(B+数 根据主键索引查到到物理地址,根据物理地址查对应数据)、支持全文索引,最小锁粒度是表锁(这也是Mysql常用Innodo的关键原因) 存储文件: .frm(表的定义)  .myd(数据扩展文件)  myi(索引文件)

Innodb:支持事务、外键,聚簇索引(索引和数据存储在一起)、不支持全文索引(但是可以使用插件来支持全文索引sphinx),最小锁粒度是行锁。 存储文件: frm(表定义文件)  ibd(数据和索引存储文件,聚簇索引 会将索引和整行数据存储到叶子节点)

mysql索引

聚簇索引(主键索引):将索引行数据全部存储到索引表中(索引的叶子节点)(一个表中只有一个聚簇索引  默认是主键,如果没有设定主键 会找到第一个唯一索引作为聚簇索引,如果前者也不满足,InnoDB会生成一个隐藏的聚集索引GEN_CLUST_INDEX)


普通索引:只会存储索引列的值(会记录行号)


覆盖索引:查询列和索引列是一致的(推荐使用覆盖索引,因为一次查询就可以查询到对应数据,如果不使用覆盖索引需要俩次查询才可以查到对应的数据)


联合索引:遵循最左前缀规则(比如索引顺序ab a是有序的  a=1的时候b才是有序的,如果where b=1  就不会走索引  in  or  like  函数计算 都会导致索引失效)


辅助索引(除聚簇索引外都叫辅助索引):根据索引字段查到对应主键值  根据主键值去聚簇索引查到对应行数据

索引的数据结构

二叉查找树:左子树小于根的键值  右子树大于根的键值


平衡二叉查找树:用来解决二叉查找树的缺点(平衡问题,俩个子树最大高度差别是1 如果超过1通过自旋的方式来保证平衡),无法保证树的高度,树越高查询效率越低,进行范围查找还需要多次回表查询


B树:解决平衡二叉查找树的缺点(减少树的高度,提高查询效率),每个节点可以存储俩个数据,进行范围查找还需要多次回表查询


B+树:解决范围查询回表查询,叶子节点用链表连接起来

mysql隔离级别

读未提交:事务读取其他事务未提交的数据(最低级别,解决不了任何事务传播行为)


读已提交:事务只能读取其他事务提交的数据(解决了脏读)


可重复读:事务多次读取同一个字段的值相同,在操作期间,禁止其他事务对这个字段进行更改(update)(解决了脏读、不可重复读、幻读(innoDb除外,通过快照读和当前读))


可串行化:确保一个事务可以从一个表中读取相同的行,在没结束前,所有增加删除查询都被禁止,所以性能很低(最高级别(解决一切传播行为),增加了读锁)

mysql事务传播行为

脏读:一个事务读取另一个事务未提交的数据


不可重读:并发更新的时候  一个事务俩次读取的数据不一致


幻读:并发增加、删除对数据量产生变化的时候,一个事务前后读取的数据量不一致

mysql锁机制

行锁:锁住一行数据,事务提交以后释放锁


表锁:索引失效会有行锁升级为表锁,锁住整个表


间歇锁:范围查到时,根据范围锁住行数据  

mysql事务四大特性(ACID)

原子性:要么全部成功、要么全部失败,主要是采用Undolog 来实现(如果一个sql执行失败,要回滚到上一个版本,undolog会记录sql执行过程,回滚的时候根据相反规则  比如执行insert回滚会执行delete)

一致性:事务执行成功之后,数据库完整性没有被破坏,执行的合法性,比如数据库表主键不能被破坏、字段大小不能改变(原子性、隔离性、持久性 来最终保证一致性)

隔离性:写-写操作(通过锁来实现,保证一行数据只有一个事务在操作,提交事务之后释放锁,另外一个事务才可以拿到)  读-写(mvcc)

持久性:事务一旦提交,数据就是持久性的,不会被破坏 永久保存到数据库中,主要采用的redolog(数据库是把数据存储到磁盘中,每次查询都会产生IO操作,为了减少IO,数据库引用了buffer(缓存),每次查询先从buffer查询,查不到在查询磁盘数据,在写入到buffer中,每次插入数据的时候会先插入buffer里,后面会根据随机IO写入到磁盘中,这样会产生数据丢失的问题,如果buffer中的数据还未写入到磁盘中,mysql宕机了。redolog是会记录每次数据操作的日志通过顺序IO写入到磁盘中,日志写入和磁盘写入是同步进行的,这样就不会担心数据丢失的问题)

mysql MVCC机制(多版本并发控制,提高数据库并发性能)

注释:同一行数据发生读写操作时,会上锁导致阻塞,mvcc解决了这个问题(这里的读是指的快照读而不是当前读,当前读是上锁  悲观锁)

当前读:读取的数据都是当前数据库最新的数据,会对当前数据上锁,导致其他读操作阻塞 delete  update insert for update(排他锁)   select  lock in share mode(共享锁)  这些操作都是当前读   对数据进行修改需要先读取当前数据


快照读:基于多版本并发控制实现的,即MVCC 读取的数据可能不是最新数据  是历史数据  即不加锁的select(事务隔离级别不是:可串行化)

mvcc组成:undolog(事务日志)  版本链(根据事务自增id和上一个事务数据指针组成的)  ReaDView(根据版本链选取哪条数据)


ReaDView读视图组成:
m_ids:当前活跃事务编号集合(未提交的事务)
min_trx_id:最小活跃事务编号
max_trx_id:预分配事务编号,当前最大事务编号+1
creator_trx_id:创建readview 的事务id

readView是怎么判断从版本链中select数据:
       trx_id:当前事务id
1、 trx_id = creator_trx_id  可以访问
2、 trx_id  < min_trx_id  可以访问
3、 trx_id  > max_trx_id 不可以访问
4、 min_trx_id <= trx_id <= max_trx_id   trx_id在m_ids中不可以访问  反之可以访问

RC(读已提交):会产生不可重复读,同一个事务里面每次select都会生成新得readview,这样就会产生俩次select的值不重复的问题)


RR(可重复读):同一个事务里,第一次select会生成readview,以后每次select都会复用这个readview,这样就解决了不可重复读的问题,也同样解决了幻读问题,因为我一直操作第一个生成的readview,其他事务操作并不影响,但是如果俩次快照读增加了当前读切覆盖到其他事务新增的数据,这样就会产生幻读。(当前读是通过间歇锁来解决幻读的,根据范围锁住所有数据,其他事务不可操作)

技术问题:

NO1:

问题:count(字段)< count(uid)< count(1) <= count(*) 性能排序
解答:count(1)和count(*)都是通过遍历主键索引数进行++操作  性能基本相同   count(uid)也是根据遍历主键索引数就是++  但是他会返回主键uid  所以说慢一些 count(字段)每次进行++操作需要判空  所以性能最低

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值