Mysql常见面试题

 

 

CHAR 和 VARCHAR的区别?

CHAR 是固定长度的字符类型,VARCHAR 则是可变长度的字符类型,下面讨论基于在 MySQL5.0 以上版本中。

共同点

CHAR(M) 和 VARCHAR(M) 都表示该列能存储 M 个字符注意不是字节!!

CHAR类型特点

  • CHAR 最多可以存储 255 个字符 (注意不是字节),字符有不同的编码集,比如 UTF8 编码 (3字节)、GBK 编码 (2字节) 等。

  • 对于 CHAR(M) 如果实际存储的数据长度小于M,则 MySQL 会自动会在它的右边用空格字符补足,但是在检索操作中那些填补出来的空格字符会被去掉。

VARCHAR类型特点

  • VARCHAR 的最大长度为 65535 个字节

  • VARCHAR 存储的是实际的字符串加1或2个字节用来记录字符串实际长度,字符串长度小于255字节用1字节记录,超过255就需要2字节记录。[^12 ]


char 和 varchar 的区别是什么?

char(n) :固定长度类型,比如订阅 char(10),当你输入"abc"三个字符的时候,它们占的空间还是 10 个字节,其他 7 个是空字节。

char 优点:效率高;缺点:占用空间;适用场景:存储密码的 md5 值,固定长度的,使用 char 非常合适。

varchar(n) :可变长度,存储的值是每个值占用的字节再加上一个用来记录其长度的字节的长度。

所以,从空间上考虑 varcahr 比较合适;从效率上考虑 char 比较合适,二者使用需要权衡。

 

VARCHAR(50) 能存放几个 UTF8 编码的汉字?

存放的汉字个数与版本相关。

mysql 4.0以下版本,varchar(50) 指的是 50 字节,如果存放 UTF8 格式编码的汉字时(每个汉字3字节),只能存放16 个。

mysql 5.0以上版本,varchar(50) 指的是 50 字符,无论存放的是数字、字母还是 UTF8 编码的汉字,都可以存放 50 个。

int(10) 和 bigint(10)能存储的数据大小一样吗?

不一样,具体原因如下:

  • int 能存储四字节有符号整数。

  • bigint 能存储八字节有符号整数。

所以能存储的数据大小不一样,其中的数字 10  代表的只是数据的显示宽度。[^13]

  • 显示宽度指明Mysql最大可能显示的数字个数,数值的位数小于指定的宽度时数字左边会用空格填充,空格不容易看出。

  • 如果插入了大于显示宽度的值,只要该值不超过该类型的取值范围,数值依然可以插入且能够显示出来。

  • 建表的时候指定 zerofill 选项,则不足显示宽度的部分用 0 填充,如果是 1 会显示成 0000000001

  • 如果没指定显示宽度, bigint 默认宽度是 20 ,int默认宽度 11。

MyISAM  与  InnoDB  存储引擎 5 大区别

  • InnoDB支持事务,而MyISAM不支持事务

  • InnoDB支持行级锁,而MyISAM支持表级锁

  • InnoDB支持MVCC, 而MyISAM不支持

  • InnoDB支持外键,而MyISAM不支持

  • InnoDB不支持全文索引,而MyISAM支持

一张表简单罗列两种引擎的主要区别,如下图:

InnoDB 引擎:MySQL 的5.5之后的默认引擎,InnoDB 引擎提供了对数据库事务的支持,并且还提供了行级锁和外键的约束,它的设计的目标就是处理大数据容量的数据库系统。MySQL 运行的时候,InnoDB 会在内存中建立缓冲池,用于缓冲数据和索引。由于锁的粒度小,写操作是不会锁定全表的,所以在并发度较高的场景下使用会提升效率的。

MyISAM 引擎:不提供事务的支持,也不支持行级锁和外键。因此当执行插入和更新语句时,即执行写操作的时候需要锁定这个表,所以会导致效率会降低。不过和 InnoDB 不同的是,MyIASM 引擎是保存了表的行数,于是当进行 select count(*) from table 语句时,可以直接的读取已经保存的值而不需要进行扫描全表。所以,如果表的读操作远远多于写操作时,并且不需要事务的支持的,可以将 MyIASM 作为数据库引擎的首选。

Myisam和InnoDB的区别⭐

  • 是否支持行级锁 : MyISAM 只有表级锁(table-level locking),而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁,适合高并发操作。
  • 是否支持外键: MyISAM不支持,而InnoDB支持
  • 是否支持事务:MyISAM不支持,而InnoDB支持
  • 缓存:MyISAM只缓存索引,InnoDB缓存索引和真实数据,所以对内存要求高
  • 崩溃恢复:MyISAM 崩溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。

数据库删除操作中的 delete、drop、 truncate 区别在哪?

  • 当不再需要该表时可以用 drop 来删除表;

  • 当仍要保留该表,但要删除所有记录时, 用 truncate来删除表中记录。

  • 当要删除部分记录时(一般来说有 WHERE 子句约束) 用 delete来删除表中部分记录。

使用 MySQL 视图有何优点?

  1. 操作简单方便。视图用户完全不需要关心视图对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。

  2. 数据更加安全。视图用户只能访问视图中的结果集,通过视图可以把对表的访问权限限制在某些行和列上面。

  3. 数据隔离。屏蔽了源表结构变化对用户带来的影响,源表结构变化视图结构不变。

什么是存储过程?

一条或多条sql语句集合,有以下一些特点:

  • 存储过程能实现较快的执行速度。

  • 存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。

  • 存储过程可被作为一种安全机制来充分利用。

  • 存储过程能够减少网络流量

存储过程和函数好像差不多,你说说他们有什么区别?

存储过程和函数是事先经过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。

相同点

  • 存储过程和函数都是为了可重复的执行操作数据库的 SQL 语句的集合。

  • 存储过程和函数都是一次编译后缓存起来,下次使用就直接命中已经编译好的 sql 语句,减少网络交互提高了效率。

不同点

  • 标识符不同,函数的标识符是 function,存储过程是 procedure。

  • 函数返回单个值或者表对象,而存储过程没有返回值,但是可以通过OUT参数返回多个值。

  • 函数限制比较多,比如不能用临时表,只能用表变量,一些函数都不可用等,而存储过程的限制相对就比较少。

  • 一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强

  • 函数的参数只能是 IN 类型,存储过程的参数可以是IN OUT INOUT三种类型。

  • 存储函数使用 select 调用,存储过程需要使用 call 调用。

where与having的区别

  • 用的地方不一样

    where可以用于select、update、delete和insert into values(select * from table where ..)语句中。

    having只能用于select语句中

  • 执行的顺序不一样

    where的搜索条件是在执行语句进行分组之前应用

    having的搜索条件是在分组条件后执行的

    即如果where和having一起用时,where会先执行,having后执行

什么是事务?

事务是逻辑上的一组操作,要么都执行,要么都不执行。

事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。

 

事务的四大特性(ACID)

事物的特性

  1. 原子性(Atomicity): 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
  2. 一致性(Consistency): 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
  3. 隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
  4. 持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

并发事务带来哪些问题?

在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题。

  • 脏读(Dirty read): 当一个事务B正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务A也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务A读到的这个数据是“脏数据”,事务A读到的数据是“临时的,无效的",依据“脏数据”所做的操作可能是不正确的。
  • 丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
  • 不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,受到其他事务提交数据的影响,因此称为不可重复读。一般多发生于update情况下
  • 幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。多发生于插入或删除情况

不可重复读和幻读区别:

不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。

Mysql常见面试题_第1张图片

事务隔离级别有哪些?MySQL的默认隔离级别是?

SQL 标准定义了四个隔离级别:

  • READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据的变更,可能会导致脏读、幻读或不可重复读
  • READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。(oracle默认级别)
  • REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,读取到相同的值,在这个事务持续期间,禁止其他事务对则合格字段进行更新修改,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)
  • SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读

Mysql常见面试题_第2张图片

Mysql常见面试题_第3张图片

 

关系型数据库遵循ACID规则

事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性:

1、A (Atomicity) 原子性

原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。

比如银行转账,从A账户转100元至B账户,分为两个步骤:1)从A账户取100元;2)存入100元至B账户。这两步要么一起完成,要么一起不完成,如果只完成第一步,第二步失败,钱会莫名其妙少了100元。


2、C (Consistency) 一致性

一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。

例如现有完整性约束a+b=10,如果一个事务改变了a,那么必须得改变b,使得事务结束后依然满足a+b=10,否则事务失败。


3、I (Isolation) 隔离性

所谓的隔离性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。

比如现在有个交易是从A账户转100元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的100元的。


4、D (Durability) 持久性

持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。


事务的四大特性(ACID)
 

原子性(Atomicity): 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;

一致性(Consistency): 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;

隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;

持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

 原子性是指事务的原子性操作,对数据的修改要么全部执行成功,要么全部失败,实现事务的原子性,是基于日志的Redo/Undo机制。

 一致性是指执行事务前后的状态要一致,可以理解为数据一致性。隔离性侧重指事务之间相互隔离,不受影响,这个与事务设置的隔离级别有密切的关系。

 持久性则是指在一个事务提交后,这个事务的状态会被持久化到数据库中,也就是事务提交,对数据的新增、更新将会持久化到书库中。

原子性、隔离性、持久性都是为了保障一致性而存在的,一致性也是最终的目的。
 

Mysql常见面试题_第4张图片

 

乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。

数据库的乐观锁需要自己实现,在表里面添加一个 version 字段,每次修改成功值加 1,这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁。

(如SVN、GIT提交代码就是这样的)

悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。

一般是 where id=XX for update 来实现 (一般银行转账、工单审批)

优缺点:

乐观锁:性能高、重试失败成本不高建议乐观

悲观锁:性能低,但安全,失败成功高建议悲观,使用不当有死锁风险

mysql 索引是怎么实现的?

索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。 MySQL 中的索引,不同的数据引擎实现有所不同,但目前主流的数据库引擎的索引都是 B+ 树实现的 。

B树和B+树的概念和区别

1)先说一下B-树是一种多路搜索树,关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;B+树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。 2)在B-树中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而B+树中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。从这个角度看B-树的性能好像要比B+树好,而在实际应用中却是B+树的性能要好些

https://blog.csdn.net/QGhurt/article/details/108201838

为什么选择B+树作为索引结构⭐

  • 因为B+树的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比B-树多,树高比B-树小,这样带来的好处是减少磁盘访问次数。尽管B+树找到一个记录所需的比较次数要比B-树多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中B+树的性能可能还会好些。
  • B+树的叶子节点使用指针连接在一起,方便顺序遍历和范围查询,这也是优于hash索引的地方。
  • B+树的查询效率更加稳定,每次查询的效率一样。

Hash索引底层是哈希表,哈希表是一种以key-value存储数据的结构,所以多个数据在存储关系上是完全没有任何顺序关系的,所以,对于区间查询是无法直接通过索引查询的,就需要全表扫描。所以,哈希索引只适用于等值查询的场景。而B+ 树是一种多路平衡查询树,所以他的节点是天然有序的(左子节点小于父节点、父节点小于右子节点),所以对于范围查询的时候不需要做全表扫描

  • 二叉查找树:解决了排序的基本问题,但是由于无法保证平衡,可能退化为链表。
  • 平衡二叉树:通过旋转解决了平衡的问题,但是旋转操作效率太低。
  • 红黑树:通过舍弃严格的平衡和引入红黑节点,解决了 AVL旋转效率过低的问题,但是在磁盘等场景下,树仍然太高,IO次数太多。

redolog,undolog,binlog

  • undoLog 也就是我们常说的回滚日志文件 主要用于事务中执行失败,进行回滚,以及MVCC中对于数据历史版本的查看。由引擎层的InnoDB引擎实现,是逻辑日志,记录数据修改被修改前的值,比如"把id='B' 修改为id = 'B2' ,那么undo日志就会用来存放id ='B'的记录”。当一条数据需要更新前,会先把修改前的记录存储在undolog中,如果这个修改出现异常,,则会使用undo日志来实现回滚操作,保证事务的一致性。当事务提交之后,undo log并不能立马被删除,而是会被放到待清理链表中,待判断没有事物用到该版本的信息时才可以清理相应undolog。它保存了事务发生之前的数据的一个版本,用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。

     

  • redoLog 是重做日志文件是记录数据修改之后的值用于持久化到磁盘中。redo log包括两部分:一是内存中的日志缓冲(redo log buffer),该部分日志是易失性的;二是磁盘上的重做日志文件(redo log file),该部分日志是持久的。由引擎层的InnoDB引擎实现,是物理日志,记录的是物理数据页修改的信息,比如“某个数据页上内容发生了哪些改动”。当一条数据需要更新时,InnoDB会先将数据更新,然后记录redoLog 在内存中,然后找个时间将redoLog的操作执行到磁盘上的文件上。不管是否提交成功我都记录,你要是回滚了,那我连回滚的修改也记录。它确保了事务的持久性

     

  • binlog由Mysql的Server层实现,是逻辑日志,记录的是sql语句的原始逻辑,比如"把id='B' 修改为id = ‘B2’。binlog会写入指定大小的物理文件中,是追加写入的,当前文件写满则会创建新的文件写入。 产生:事务提交的时候,一次性将事务中的sql语句,按照一定的格式记录到binlog中。用于复制和恢复在主从复制中,从库利用主库上的binlog进行重播(执行日志中记录的修改逻辑),实现主从同步。业务数据不一致或者错了,用binlog恢复。

binlog和redolog的区别

  1. redolog是在InnoDB存储引擎层产生,而binlog是MySQL数据库的上层服务层产生的。
  2. 两种日志记录的内容形式不同。MySQL的binlog是逻辑日志,其记录是对应的SQL语句。而innodb存储引擎层面的重做日志是物理日志。
  3. 两种日志与记录写入磁盘的时间点不同,binlog日志只在事务提交完成后进行一次写入。而innodb存储引擎的重做日志在事务进行中不断地被写入,并日志不是随事务提交的顺序进行写入的。
  4. binlog不是循环使用,在写满或者重启之后,会生成新的binlog文件,redolog是循环使用。
  5. binlog可以作为恢复数据使用,主从复制搭建,redolog作为异常宕机或者介质故障后的数据恢复使用。

Mysql的日志:https://blog.csdn.net/QGhurt/article/details/108200939

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Mysql,Java面试,mysql,数据库)