mysql面试题总结

  1. Mysql中的myisam与innodb的区别?
  2. InnoDB存储引擎的四大特性?
  3. 什么是事务?
  4. 数据库事务的四大特性?
  5. 不考虑事务的隔离性,会发生几种问题?
  6. MySQL数据库提供的四种隔离级别?
  7. 有多少种日志?
  8. 事务是如何经过日志来实现的?
  9. 数据库的乐观锁和悲观锁是什么?
  10. 什么是存储过程?有哪些优缺点?
  11. 存储过程与触发器的区别?
  12. 索引是什么?有什么做用以及优缺点?
  13. 说一说MySQL数据库几个基本的索引类型?
  14. 使用索引查询必定能提升查询的性能吗?为何?
  15. 为数据表创建索引的原则有哪些?
  16. 什么状况下应不建或少建索引?
  17. 什么是mysql联合索引?
  18. 说一说 B+树索引、哈希索引?
  19. B树和B+树的区别?
  20. 为何说B+比B树更适合实际应用中操做系统的文件索引和数据库索引?
  21. 汇集索引和非汇集索引区别?
  22. 说一说drop、deletetruncate的区别?
  23. drop、deletetruncate分别在什么场景之下使用?
  24. 超键、候选键、主键、外键分别是什么?
  25. mysql为何用自增列做为主键?
  26. MySQL中的varchar和char的区别以及varchar(50)中的50表明的涵义?
  27. 什么是视图?视图的使用场景有哪些?
  28. 数据库三大范式?
  29. sql优化
  30. 非关系型数据库和关系型数据库区别,优点比较?
  31. 什么是 内链接、外链接、交叉链接、笛卡尔积等?
  32. SQL语言分类
  33. like %和-的区别
  34. count(*)、count(1)、count(column)的区别
  35. 大家数据库是否支持emoji表情,若是不支持,如何操做?
  36. 你是如何监控大家的数据库的?大家的慢日志都是怎么查询的?

 

 

一、Mysql中的MyISAM与InnoDB的区别?

(1)InnoDB存储引擎支持事务,而MyISAM不支持事务;html

(2)InnoDB支持行级锁,而MyISAM只支持表级锁;前端

( InnoDB行锁是经过给索引加锁实现的,即只有经过索引条件检索数据,InnoDB才使用行级锁,不然将使用表级锁!行级锁在每次获取锁和释放锁的操做须要比表级锁消耗更多的资源。mysql

MySQL表级锁有两种模式:表共享读锁和表独占写锁。就是说对MyIASM表进行读操做时,它不会阻塞其余用户对同一表的读请求,但会阻塞对同一表的写操做;而对MyISAM表的写操做,会阻塞其余用户对同一表的读和写操做。)程序员

(3)InnoDB支持外键,而MyISAM不支持外键;面试

(4)InnoDB不保存数据库表中表的具体行数,而MyISAM会保存;算法

( 也就是说,执行 select count(*) from table 时,InnoDB要扫描一遍整个表来计算有多少行,而MyISAM只须要读出保存好的行数便可(内部维护了一个计算器,能够直接调取)。【注】:当count(*)语句包含where条件时,两种表的操做是同样的。也就是上述介绍到的InnoDB使用表锁的一种状况。)sql

 

  对于select ,update ,insert ,delete 操做:mongodb

  若是执行大量的SELECT,MyISAM是更好的选择(由于MyISAM不支持事务,使得MySQL能够提供高速存储和检索,以及全文搜索能力)数据库

  若是执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表(由于InnoDB支持事务,在一些列增删改中只要哪一个出错还能够回滚还原,而MyISAM就不能够了)编程

二、InnoDB存储引擎的四大特性?

插入缓冲、二次写、自适应哈希索引、预读

(1)插入缓冲

  通常状况下,主键是行惟一的标识符。一般应用程序中行记录的插入顺序是按照主键递增的顺序进行插入的。所以,插入汇集索引通常是顺序的,不须要磁盘的随机读取。由于,对于此类状况下的插入,速度仍是很是快的。

  若是索引是非汇集的且不惟一,在进行插入操做时,数据的存放对于非汇集索引叶子节点的插入不是顺序的,这时须要离散地访问非汇集索引页,因为随机读取的存在而致使了插入操做性能降低。(这是由于B+树的特性决定了非汇集索引插入的离散性。)

  插入缓冲对于非汇集索引的插入和更新操做,不是每一次直接插入索引页中,而是先判断插入的非汇集索引页是否在缓存池中。若是在,则直接插入;若是不在,则先放入一个插入缓冲区中,好似欺骗数据库这个非汇集的索引已经插入到叶子结点了,而后再以必定的频率执行插入缓冲和非汇集索引页子节点的合并操做,这时一般能将多个插入合并到一个操做中(由于在一个索引页中),这就大大提升了对非汇集索引执行插入和修改操做的性能

    插入缓冲的使用要知足两个条件

  • 索引是辅助索引
  • 索引不是惟一的
    • (辅助索引不能是惟一的,由于在把它插入到插入缓冲时,咱们并不去查找索引页的状况。若是去查找确定又会出现离散读的状况,插入缓冲就失去了意义。)

    存在的问题:

      在写密集的状况下,插入缓冲会过多的占用缓冲池内存,默认状况下最大能够占用1/2的缓冲池内存。

(2)二次写

当数据库宕机时,可能发生数据库正在写一个页面,而这个页只写了一部分的状况,咱们称之为部分写失效。当写入失效发生时,先经过页的副原本还原该页,再重作日志,这就是两次写

doublewrite步骤:

  1. 当一系列机制(main函数触发、checkpoint等)触发数据缓冲池中的脏页进行刷新时,并不直接写磁盘,而是会经过memcpy函数将脏页拷贝到内存中的doublewrite buffer,以后经过doublewrite buffer再分两次、每次1MB顺序写入共享表空间的物理磁盘上。
  2. 而后立刻调用fsync函数,同步脏页进磁盘。在这个过程当中,doublewrite页的存储是连续的,所以写入磁盘为顺序写,性能很高在完成doublewrite页的写入后,再将doublewrite buffer中的页写入到各个表空间文件中,此时的写入则是离散的。

  若是操做系统在将页写入磁盘的过程当中崩溃了,在恢复过程当中,InnoDB存储引擎能够从共享表空间中的doublewrite中找到该页的一个副本,将其拷贝到表空间文件,再应用重作日志,就完成了恢复过程。由于有副本因此也不担忧表空间中数据页是否损坏。

(3)自适应哈希索引

  InnoDB存储引擎会监控对表上索引的查找,若是观察到创建哈希索引能够带来速度的提高,则创建哈希索引,因此称为自适应的。自适应哈希索引经过缓冲池的B+树构造而来,所以创建的速度很快,并且不须要将整个表都建哈希索引,InnoDB存储引擎会自动根据访问的频率和模式来为某些页创建哈希索引。

  (4)预读

  InnoDB 提供了两种预读的方式,一种是 Linear read ahead,由参数innodb_read_ahead_threshold控制,当你连续读取一个 extent 的 threshold 个 page 的时候,会触发下一个 extent 64个page的预读。另一种是Random read-ahead,由参数innodb_random_read_ahead控制,当你连续读取设定的数量的page后,会触发读取这个extent的剩余page。
  InnoDB 的预读功能是使用后台线程异步完成的。

3. InnoDB如何保证事务的四大特性?

  MySQL的存储引擎InnoDB使用重作日志(redo log)保证一致性与持久性回滚日志(undo log)保证原子性使用各类锁来保证隔离性

4. MySQL中的重作日志(redo log),回滚日志(undo log),以及二进制日志(binlog)?

MySQL中有六种日志文件,分别是:

重作日志(redo log)
回滚日志(undo log)
二进制日志(binlog)
错误日志(errorlog)
慢查询日志(slow query log)
通常查询日志(general log)
中继日志(relay log)

其中重作日志和回滚日志与事务操做息息相关,二进制日志也与事务操做有必定的关系。

事务是如何经过日志来实现的?

  Undo 记录某 数据 被修改 的值,能够用来在事务失败时进行 rollback;
  Redo 记录某 数据块 被修改 的值,能够用来恢复未写入 data file 的已成功事务更新的数据。
即,

  • Redo Log 保证事务的持久性
  • Undo Log 保证事务的原子性(在 InnoDB 引擎中,还用 Undo Log 来实现 MVCC)
  好比某一时刻数据库 DOWN 机了,有两个事务,一个事务已经提交,另外一个事务正在处理。数据库重启的时候就要根据日志进行前滚及回滚,把已提交事务的更改写到数据文件,未提交事务的更改恢复到事务开始前的状态。即 经过 redo log 将全部已经在存储引擎内部提交的事务应用 redo log 恢复全部已经 prepared 可是没有 commit 的事务将会应用 undo log 作回滚

重作日志(redo log):

  redo log在事务没有提交前,会记录每个修改操做变动后的数据。主要是防止在发生故障的时间点,尚有脏页未写入磁盘。在重启mysql服务的时候,根据redo log进行重作,从而达到事务的持久性这一特性。(做用

  在事务提交前,只要将 Redo Log 持久化便可,不须要将数据持久化。当系统崩溃时,系统能够根据redo Log的内容,将全部数据恢复到最新的状态。(持久化:先将重作日志写入缓存,再刷新(fsync)到磁盘

  重作日志是物理日志,记录的是对于每一个页的修改。事务开始后Innodb存储引擎先将重作日志写入缓存(innodb_log_buffer)中。而后会经过如下三种方式将innodb日志缓冲区的日志刷新到磁盘。

  1. Master Thread每秒一次执行刷新Innodb_log_buffer到重作日志文件。
  2. 每一个事务提交时会将重作日志刷新到重作日志文件。
  3. 当重作日志缓存可用空间少于一半时,重作日志缓存被刷新到重作日志文件

  当事务提交时,必须先将该事务的全部日志写入到重作日志文件进行持久化

一、内容:

      物理格式的日志,记录的是物理数据页面的修改的信息,其redo log是顺序写入redo log file的物理文件中去的。

二、redo log是何时写盘的?

  是在事物开始以后逐步写盘的。

  事务开始以后就产生redo log,redo log的写盘并非随着事务的提交才写入的,而是在事务的执行过程当中,便开始写入redo log文件中。(先将重作日志写入缓存,将日志缓冲区的日志刷新到磁盘,写入磁盘的方式有上面3种)

【注】即便某个事务尚未提交,Innodb存储引擎仍然每秒会将重作日志缓存刷新到重作日志文件。这一点是必需要知道的,由于这能够很好地解释再大的事务的提交(commit)的时间也是很短暂的。

三、何时释放:

      当对应事务的脏页写入到磁盘以后,redo log的使命也就完成了,重作日志占用的空间就能够重用(被覆盖)。

回滚日志(undo log):

  保存了事务发生以前的数据的一个版本,能够用于回滚,同时能够提供多版本并发控制下的读(MVCC),也即非锁定读。(做用

  事务发生异常须要回滚,这时就须要回滚日志。回滚日志不一样于重作日志,它是逻辑日志对数据库的修改都逻辑的取消了。当事务回滚时,它实际上作的是与先前相反的工做。对于每一个INSERT,InnoDB存储引擎都会完成一个DELETE;对于每一个UPDATE,InnoDB存储引擎都会执行一个相反的UPDATE。

  未提交的事务和回滚了的事务也会产生重作日志。InnoDB存储引擎会重作全部事务包括未提交的事务和回滚了的事务,而后经过回滚日志回滚那些未提交的事务。使用这种策略须要回滚日志在重作日志以前写入磁盘,使得持久化变得复杂起来。为了下降复杂度,InnoDB存储引擎将回滚日志做数据,记录回滚日志的操做也会记录到重作日志中。这样回滚日志就能够像数据同样缓存起来,而不用在重写日志以前写入磁盘了。

一、内容

      逻辑格式的日志在执行undo的时候,仅仅是将数据从逻辑上恢复至事务以前的状态,而不是从物理页面上操做实现的,这一点是不一样于redo log的。

二、何时产生?

      事务开始以前,将当前是的版本生成undo log,undo 也会产生 redo 来保证undo log的可靠性

三、何时释放?

      当事务提交以后,undo log并不能立马被删除,而是放入待清理的链表,由purge线程判断是否由其余事务在使用undo段中表的上一个事务以前的版本信息,决定是否能够清理undo log的日志空间

 

二进制日志(bin log):

一、做用:

      用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。 用于数据库的基于时间点的还原。

二、内容:

逻辑格式的日志,能够简单认为就是执行过的事务中的sql语句。

      但又不彻底是sql语句这么简单,而是包括了执行的sql语句(增删改)反向的信息,也就意味着delete对应着delete自己和其反向的insert;update对应着update执行先后的版本的信息;insert对应着delete和insert自己的信息。

在使用mysqlbinlog解析binlog以后一些都会真相大白。
所以能够基于binlog作到相似于oracle的闪回功能,其实都是依赖于binlog中的日志记录。

三、何时产生:

      事务提交的时候,一次性将事务中的sql语句(一个事物可能对应多个sql语句)按照必定的格式记录到binlog中。这里与redo log很明显的差别就是redo log并不必定是在事务提交的时候刷新到磁盘,redo log是在事务开始以后就开始逐步写入磁盘。

      所以对于事务的提交,即使是较大的事务,提交(commit)都是很快的,可是在开启了bin_log的状况下,对于较大事务的提交,可能会变得比较慢一些。这是由于binlog是在事务提交的时候一次性写入的形成的,这些能够经过测试验证。

四、何时释放:

binlog的默认是保持时间由参数expire_logs_days配置,也就是说对于非活动的日志文件,在生成时间超过expire_logs_days配置的天数以后,会被自动删除。

 

binlog与redolog的区别?

  在MySQL数据库中还有一种二进制日志,其用来基于时间点的还原及主从复制。从表面上来看其和重作日志很是类似,都是记录了对于数据库操做的日志。可是,从本质上来看有着很是大的不一样。 首先重作日志是在InnoDB存储引擎层产生的,而二进制日志是在MySQL数据库的上层产生的。其次,两种日志记录的内容形式不一样。二进制日志是一种逻辑日志,其记录的是对应的SQL语句。而重作日志是物理日志,记录的是每一个页的修改。此外,两种日志记录写入磁盘的时间点不一样,二进制日志只在事务提交完成后进行一次写入,重作日志在事务进行时不断地写入。

 
 
 

三、什么是事务?

  事务就是一个操做序列,这些操做要么都执行,要么都不执行,它是一个不可分割的工做单位。事务是数据库维护数据一致性的单位,在每一个事务结束时,都能保持数据一致性。

四、数据库事务的四大特性?

  原子性、一致性、隔离性、持久性  (ACID)

  • 原子性:是指整个数据库事务是不可分割的单位。只有使事务中的全部数据库操做都成功,才算整个事务成功。若是事务中任何一个sql语句执行失败,那么已经执行的sql语句也必须撤销,事务状态退回到执行事务以前的状态。
  • 一致性:一致性是指事务必须使数据库从一个一致性状态变换到另外一个一致性状态。在事务开始以前和事务结束以后,事务的完整性约束没有被破坏。
  • 隔离性:一个事务的影响在该事务提交前对其余事物都不可见。——这经过锁来实现
  • 持久性:事务一旦提交,其结果就是永久性的。

(隔离性由锁来实现;原子性、一致性和持久性经过数据库的redo和undo来完成。)

五、不考虑事务的隔离性,会发生几种问题?

  经过锁能够实现事务隔离性的要求,使得事务能够并发地工做。由于事务隔离性的要求,锁会带来3种问题:丢失更新、脏读、不可重复读。

丢失更新:

  指一个事务正在访问修改数据,与此同时另外一个事务也在访问修改此数据,两个事务互相不知道对方的存在。假如在是事务A修改数据前事务B已经修改过1次数据,那么事务A最终只能查询到假数据,丢失了更新操做。

解决方案:

悲观锁的方式: 加锁,建议最后一步更新数据的时候加上排它锁,不要在一开始就加锁。执行到了最后一步更新,首先作一下加锁的查询确认数据有没有没改变,若是没有被改变,则进行数据的更新,不然失败。 必定要是作加锁的查询确认,由于若是你不加锁的话,有可能你在作确认的时候数据又发生了改变。

乐观锁的方式:使用版本控制实现。

脏读:

一个事务读取了另外一个事务未提交的数据,那这个读取就是脏读。

解决方法 : 把数据库的事务隔离级别调整到read commited。

不可重复读:

  不可重复读是指在一个事务内屡次读同一数据,在这个事务尚未结束时,另一个事务也访问并修改该同一数据,那么在第一个事务的两次读数据之间,因为第二个事务的修改,第一个事务两次读到的数据多是不同的。这样就发生了在一个事务内两次读到的数据是不同的,所以称为不可重复读。

  如何避免:InnoDB存储引擎中,经过使用Next-Key Lock算法来避免不可重复读的问题。在Next-Key Lock算法下,对于索引的扫描,不只仅是锁住扫描到的索引,并且还能锁住这些索引覆盖的范围。所以对于这个范围内的插入都是不容许的。InnoDB存储引擎的默认事务隔离级别是READ REPEATABLE,采用Next-Key Lock算法,就避免了不可重复读的现象。

解决办法:把数据库的事务隔离级别调整到 REPEATABLE READ , 读取时候不容许其余事务修改该数据,无论数据在事务过程当中读取多少次,数据都是一致的。

幻读:

  是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的所有数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,之后就会发生操做第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉同样。

如何避免:Repeatable read及以上级别经过间隙锁来防止幻读的出现,即锁定特定数据的先后间隙让数据没法被插入。

六、MySQL数据库提供的四种隔离级别?

  • read uncommitted(读未提交)
  • read committed(读已提交)
  • repeatable read(可重复读):InnoDB的默认隔离级别
  • serializable(串行)

  

七、有多少种日志?

  • 错误日志    :记录出错信息,也记录一些警告信息或者正确的信息。
  • 查询日志    :记录全部对数据库请求的信息,不论这些请求是否获得了正确的执行。
  • 慢查询日志:设置一个阈值,将运行时间超过该值的全部SQL语句都记录到慢查询的日志文件中。
  • 二进制日志:记录对数据库执行更改的全部操做。
  • 中继日志
  • 事务日志

八、事务是如何经过日志来实现的?

  • InnoDB中,事务日志经过重作(redo)日志文件和InnoDB存储引擎的日志缓冲来实现。当开始一个事务时,会记录该事务的一个LSN(日志序列号),当事务执行时,会往InnoDB的日志缓冲里插入事务日志,当事务提交时,必须将innoDB存储引擎的日志缓冲写入磁盘。也就是在写数据前,须要先写日志。这种方式称为预写日志方式

 InnoDB经过预写日志的方式来保证事务的完整性。这意味着磁盘上存储的数据页和内存缓冲池中的数据页是不一样步的,对于内存缓冲池中页的修改,先是写入重作日志文件,而后再写入磁盘,所以是一种异步的方式

  • 事务有时还须要撤销,这就须要undo。对数据库进行修改时,数据库不但会产生redo,并且会产生必定量的undo,若是你执行的事务或语句因为某种缘由失败了,或者若是你用一条rollback语句请求回滚,就能够利用这些undo信息将数据回滚到修改以前的样子。

九、数据库的乐观锁和悲观锁是什么?

乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。

悲观锁:假定会发生并发冲突,屏蔽掉一切可能违反数据完整性的操做,在读取的时候就对数据进行加锁, 在该用户读取数据的期间,其余任何用户都不能来修改该数据,可是其余用户是能够读取该数据的, 只有当本身读取完毕才释放锁。

乐观锁:假定不会发生并发冲突,只在提交的时候检查是否发生并发冲突。

  事务和锁的存在都是为了更好地解决并发访问形成的数据不一致性问题。乐观锁和悲观锁都是为了解决并发控制问题,乐观锁能够看作一种在最后提交时检测冲突的手段,而悲观锁是一种避免冲突的手段。

(1)乐观锁:假设不会发生并发冲突,只在提交的时候检查是否发生并发冲突。能够使用版本号机制CAS算法实现。

  版本号机制:通常在数据表中加一个数据版本号version字段,表示数据被修改的次数,当数据被修改时version值加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若当前读取到的version值与第一次读取到的数据库version值相等时才更新,不然重试更新操做,直到更新成功。

  例子:

假设数据库中账户信息表中有一个 version 字段,当前值为 1 ;而当前账户余额字段( balance )为 100 。

  1. 操做员A此时将其读出( version=1 ),并从其账户余额中扣除 50(100-50 =50);
  2. 在操做员A操做的过程当中,操做员B也读入此用户信息( version=1 ),并从其账户余额中扣除20 (100-20=80 )。
  3. 操做员A完成了修改工做,将数据版本号加一( version=2 ),连同账户扣除后余额( balance=50 ),提交至数据库更新,此时因为提交数据版本大于数据库记录当前版本,数据被更新,数据库记录 version 更新为 2 ;
  4. 操做员B完成了操做,也将版本号加一( version=2 )试图向数据库提交数据( balance=80 ),但此时比对数据库记录版本时发现,操做员 B 提交的数据版本号为 2 ,数据库记录当前版本也为 2 ,不知足 “ 当前最后更新的version与操做员第一次的版本号相等 “ 的乐观锁策略,所以,操做员B的提交被驳回。

  CAS机制:即compare and swap(比较与交换),无锁编程,在不使用锁的状况下实现多线程之间的变量同步,也就是在没有线程被阻塞的状况下实现变量的同步,所以也叫非阻塞同步。

  CAS过程是这样:它包含3个参数:内存值V(要更新变量的值),旧的预期值A,要修改的值B。当且仅当预期值A的值等于内存值V时,才会将内存值V修改成B,不然不会执行任何操做(V值和A值不一样,则说明已经有其余线程作了更新)。通常状况下是一个自旋操做,即不断的重试。

  例子:

  1. 假设 t1,t2 线程同时更新同一变量56的值。
  2. 由于t1和t2线程都同时去访问同一变量56,因此他们会把主内存的值彻底拷贝一份到本身的工做内存空间,因此t1和t2线程的预期值都为56。
  3. 假设t1在与t2线程竞争中线程t1能去更新变量的值,而其余线程都失败。(失败的线程并不会被挂起,而是被告知此次竞争中失败,并能够再次发起尝试)。t1线程去更新变量值改成57,而后写到内存中。此时对于t2来讲,内存值变为了57,与预期值56不一致,就操做失败了(想改的值再也不是原来的值)。

乐观锁的优点和劣势 :
优点:若是数据库记录始终处于悲观锁加锁状态,能够想见,若是面对几百上千个并发,那么要不断的加锁减锁,并且用户等待的时间会很是的长, 乐观锁机制避免了长事务中的数据库加锁解锁开销,大大提高了大并发量下的系统总体性能表现。因此若是系统的并发很是大的话,悲观锁定会带来很是大的性能问题,因此建议就要选择乐观锁定的方法, 而若是并发量不大,彻底能够使用悲观锁定的方法。乐观锁也适合于读比较多的场景。
劣势: 乐观锁只能在提交数据时才发现业务事务将要失败,若是系统的冲突很是的多,并且一旦冲突就要由于从新计算提交而形成较大的代价的话,乐观锁也会带来很大的问题。并且乐观锁也没法解决脏读的问题 。

(2)悲观锁:假定会发生并发冲突,在读取的时候就对数据进行加锁, 在该用户读取数据的期间,其余任何用户都不能来修改该数据,可是其余用户是能够读取该数据的, 只有当本身读取完毕才释放锁。

  在数据库中能够使用Repeatable Read的隔离级别(可重复读)来实现悲观锁,它彻底知足悲观锁的要求(加锁)。Java中synchronizedReentrantLock等独占锁就是悲观锁思想的实现。

     悲观锁的优点和劣势 :
    优点:  能避免冲突的发生 。
    劣势 :开销较大,并且加锁时间较长,对于并发的访问性支持很差。

两种锁的使用场景:

  若是冲突不多,或者冲突的后果不会很严重,那么一般状况下应该选择乐观锁,由于它能获得更好的并发性;

  若是冲突太多或者冲突的结果对于用户来讲痛苦的,那么就须要使用悲观策略,它能避免冲突的发生。

  通常乐观锁适用于写比较少的状况下(多读场景),即冲突真的不多发生的时候;悲观锁适用于多写的状况,多写的状况通常会常常产生冲突。

 

数据库中的乐观锁,悲观锁

面试必备之乐观锁与悲观锁

9. 共享锁与排它锁?

  共享锁和排它锁是具体的锁,是数据库机制上的锁。

  • 共享锁(读锁): 在同一个时间段内,多个用户能够读取同一个资源,读取的过程当中数据不会发生任何变化。读锁之间相互不阻塞, 多个用户能够同时读,可是不能容许有人修改。 
  • 排它锁(写锁): 在任什么时候候只能有一个用户写入资源,当进行写锁时会阻塞其余的读锁或者写锁操做,只能由这一个用户来写,其余用户既不能读也不能写。

 

加锁会有粒度问题,从粒度上从大到小能够划分为

  • 表锁:开销较小,一旦有用户访问这个表就会加锁,其余用户就不能对这个表操做了,应用程序的访问请求遇到锁等待的可能性比较高。
  • 页锁:是MySQL中比较独特的一种锁定级别,锁定颗粒度介于行级锁定与表级锁之间,因此获取锁定所须要的资源开销,以及所能提供的并发处理能力也一样是介于上面两者之间。另外,页级锁定和行级锁定同样,会发生死锁。
  • 行锁:开销较大,能具体的锁定到表中的某一行数据,可是能更好的支持并发处理, 会发生死锁。

十、什么是存储过程?什么是触发器?

存储过程:

(1)定义:

存储过程是一组SQL命令集合,通过预编译存放在系统中。也就是将经常使用的或很复杂的工做,预先用SQL语句写好并用一个指定的名称存储起来,之后只要调用它就能够完成相应的功能。 

(2)存储过程的种类:

  存储过程通常分为“系统存储过程”与“用户存储过程”。系统存储过程通常以sp_开头,用户不能够编辑修改,只能调用;用户存储过程是用户编写的处理数据的存储过程。

(3)存储过程的建立和使用: 

create procedure proc1 --建立一个存储过程
as begin
    --在存储过程当中处理SQL
    select * from bank
end

【注】若是有参数,存储过程的参数是在as关键字以前,as以后的是局部变量,2种变量在存储过程当中均可以使用,可是命名时不能够冲突。例:

create procedure proc2
@mobile varchar(50),@sendMsg varchar(50)
as
begin
    print @mobile  ---输出mobile这个参数
end

(4)存储过程与通常的SQL语句有什么区别呢? (存储过程的优势: )

  1. 存储过程只在创造时进行编译,之后每次执行存储过程都不需再从新编译,而通常SQL语句每执行一次就编译一次,因此使用存储过程可提升数据库执行速度。 
  2. 当对数据库进行复杂操做时(如对多个表进行Update,Insert,Query,Delete时),可将此复杂操做用存储过程封装起来与数据库提供的事务处理结合一块儿使用。 
  3. 存储过程能够重复使用,可减小数据库开发人员的工做量 。
  4. 安全性高,可设定只有某此用户才具备对指定存储过程的使用权。

  缺点:对于简单的sql语句不必使用存储过程,存储过程适合用于对数据库进行复杂的操做。

触发器:

(1)定义:

  触发器(Trigger)是个特殊的存储过程,它不是由用户主动发起调用的,而是当发生某一事件而触发,由系统自动调用。好比当用户在数据库中新增一条商品记录,咱们但愿同时在库存中作登记,而库存登记不是人工去录入,是在发生新增商品记录这一事件时发生,由系统自动完成录入,这个工做就能够交给一个特殊的存储过程来完成,这个存储过程就是触发器。

(2)触发器的工做机制: 

  触发器是建在表上的,当这个表发生新增、修改、删除操做时,若是这个表上有触发器,就会被自动调用。在这个事件的过程当中,系统会产生一个临时表,这个临时表只有一行记录:

  • 当执行新增操做时,临时表的名字叫inserted
  • 当执行删除操做时,临时表的名字叫deleted
  • 当执行修改操做时,会同时产生2个临时表,一个是inserted,存放的是新的数据,一个是deleted,存的是旧的数据

  当须要触发器连带操做登记库存时就能够从inserted表或者deleted表中得到变量,更新到库存表中数据。

(3)做用:维护表的完整性,记录表的修改来审计表的相关信息。分为:

  • DML触发器:当数据库服务器中发生数据操做语言事件时执行的存储过程,分为:After触发器和instead of触发器。
  • DDL触发器:特殊的触发器,在响应数据定义语言(DDL)语句时触发,通常用于数据库中执行管理任务。DDL触发器是响应create、after、或drop开头的语句而激活。

触发器用处仍是不少的,好比校内网、开心网、Facebook,你发一个日志,自动通知好友,其实就是在增长日志时作一个后触发,再向通知表中写入条目。由于触发器效率高。

(4)建立触发器的SQL语法:

create trigger 触发器名称   --触发器名称
on 表名                 --建在那个表上
for insert|update|delete    --是插入事件处理仍是修改事件处理仍是删除事件处理
as                       --如下是触发器基本格式
begin
end

调用存储过程:call procedure_name(参数,参数...)

(5)触发器优势:

  • 自动执行:触发器不用像存储过程同样须要手动调用,是自动触发的,只有当对表进行更新,删除等操做的时候会当即触发
  • 级联更新:触发器能够经过数据库中的相关表进行层叠更改,这比直接将代码写在前端的作法更安全合理。
  • 强化约束:触发器能够引用其余表的列,可以实现比check约束更为复杂的约束。
  • 跟踪变化:触发器能够阻止数据库中未经容许的指定更新和变化。
  • 强制业务逻辑:触发器可用于执行管理任务,并强制影响数据库的复杂业务规则。

  缺点:不一样数据库,语法差异很大,移植困难,换了数据库,须要从新编写;很差管理,把过多业务逻辑写在存储过程很差维护,不利于分层管理,容易混乱,通常存储过程适用于个别对性能要求较高的业务。

 

参考:什么是存储过程、触发器的解释

  sql的存储过程与触发器的区别,以及各自的优缺点

  SQL高级--储存过程和触发器

十一、存储过程与触发器的区别?与函数的区别?

存储过程与触发器:

它们都是sql语句集,不一样的是:

存储过程是须要用户调用的(经过存储过程名字直接调用),而触发器不是由用户主动发起调用的,而是当发生某一事件而触发,由系统自动调用。在insert、delete和update命令以前或以后自动调用sql命令或者存储过程。

 

函数:

 函数:MySQL中提供了许多内置函数,还能够自定义函数(实现程序员须要sql逻辑处理)

自定义函数建立语法:

  建立:CREATE FUNCTION 函数名称(参数列表)  

          RETURNS 返回值类型  函数体

   修改: ALTER FUNCTION 函数名称 [characteristic ...]

   删除:DROP FUNCTION [IF EXISTS] 函数名称

   调用:SELECT 函数名称(参数列表)

 

存储过程和函数的区别:

  1.  通常来讲,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。
  2. 对于存储过程来讲能够返回参数,而函数只能返回值或者表对象。
  3.  存储过程通常是做为一个独立的部分来执行,而函数能够做为查询语句的一个部分来调用,因为函数能够返回一个表对象,所以它能够在查询语句中位于FROM关键字的后面。

十二、索引是什么?有什么做用以及优缺点?

索引是对数据库表中一或多个列的值进行排序的结构,利用索引可快速访问数据库表的特定信息。

  举个例子:假设有一张数据表Emplyee,该表有三列:Employee_name,Employee_age,Employee_address,表中有几万条记录。如今要执行下面这条查询语句:Select * from Employee where Employee_name='Jesus'。

  若是没有数据库索引功能,数据库系统会全表扫描,逐行的遍历整张表,对于每一行都要检查其Employee_Name字段是否等于“Jesus”。而数据库索引功能索引的最大做用就是加快查询速度,它能从根本上减小须要扫表的记录/行的数量。

优势:

  • 索引加快数据库的检索速度
  • 经过建立惟一性索引,能够保证数据库表中每一行数据的惟一性;
  • 加速表和表之间的链接;
  • 使用分组和排序子句进行数据检索时,能够显著减小查询中分组和排序的时间。

缺点:

  • 建立索引和维护索引须要耗费时间,这个时间随着数据量的增长而增长;
  • 索引须要占用物理空间,不光是表须要占用数据空间,每一个索引也须要占用物理空间;
  • 当对表进行增、删、改、的时候索引也要动态维护,这样就下降了数据的维护速度。

1三、说一MySQL数据库几个基本的索引类型?

普通索引、惟一索引、主键索引、联合索引、全文索引

  • 惟一索引:索引列的值必须惟一,但容许有空值。若是是组合索引,则列值的组合必须惟一。
  • 主键索引:是一种特殊的惟一索引,一个表只能有一个主键,不容许有空值。 为表定义主键将自动建立主键索引。(数据库表某列或列组合,其值惟一标识表中的每一行。该列称为表的主键。)
  • 联合索引:指对表上的多个列作索引。只有在查询条件中使用了建立索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀原则。
  • 全文索引:主要用来查找文本中的关键字,而不是直接与索引中的值相比较。目前只有char、varchar,text 列上能够建立全文索引。

http://www.javashuo.com/article/p-kijtdxkb-k.html

1四、使用索引查询必定能提升查询的性能吗?为何?

一般,经过索引查询数据比全表扫描要快。可是咱们也必须注意到它的代价:

  索引须要空间来存储,也须要按期维护,每当有记录在表中增减或索引列被修改时,索引自己也会被修改。这意味着每条记录的INSERT、DELETE、UPDATE将为此多付出4,5 次的磁盘I/O。由于索引须要额外的存储空间和处理,那些没必要要的索引反而会使查询反应时间变慢。使用索引查询不必定能提升查询性能,索引范围查询(INDEX RANGE SCAN)适用于两种状况:

  • 若是某个字段的取值范围很广,几乎没有重复,即高选择性,则此时使用B+树索引是最适合的,例如姓名。
  • 基于一个范围的检索,通常查询返回结果集小于表中记录数的20%。(MySQL数据库的优化器会预估查询可能获得的行,若是大于某一个值,则B+树会选择全表的扫描。这个值通常在20%(即当取出的数据量超过表中数据的20%,优化器就不会使用索引))

1五、为数据表创建索引的原则有哪些?

  • 在最频繁使用的、用以缩小查询范围的字段上创建索引。
  • 在频繁使用的、须要排序的字段上创建索引。

1六、什么状况下应不建或少建索引?

  • 对于那些在查询中不多使用或者参考的列不该该建立索引。(既然这些列不多使用到,所以有索引或者无索引并不能提升查询速度。相反,因为增长了索引,反而下降了系统的维护速度和增大了空间需求。)
  • 对于那些只有不多数据值的列也不该该增长索引。(因为这些列的取值不多,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即须要在表中搜索的数据行的比例很大。增长索引,并不能明显加快检索速度。)
  • 对于那些定义为text, image和bit数据类型的列不该该增长索引。(这是由于,这些列的数据量要么至关大,要么取值不多。)
  • 当修改性能远远大于检索性能时,不该该建立索引。(这是由于,修改性能和检索性能是互相矛盾的。当增长索引时,会提升检索性能,可是会下降修改性能。当减小索引时,会提升修改性能,下降检索性能。)

1七、什么是mysql联合索引?

   联合索引是指对表上的多个列作索引。在mysql创建联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配。

最左前缀匹配原则

  最左优先,在检索数据时从联合索引的最左边开始匹配。

 

  对列col一、列col2和列col3建一个联合索引:KEY test_col1_col2_col3 on test(col1,col2,col3);

  联合索引 test_col1_col2_col3 至关于创建了(col1)、(col1,col2)、(col,col2,col3)三个索引。

(1)SELECT * FROM test WHERE col1="1" AND clo2="2" AND clo4=|"4"

  上面这个查询语句执行时会依照最左前缀匹配原则,检索时会使用索引(col1,col2)进行数据匹配。

(2)索引的字段能够是任意顺序的,如:

  SELECT * FROM test WHERE col1=“1” AND clo2=“2”   SELECT * FROM test WHERE col2=“2” AND clo1=“1”

  这两个查询语句都会用到索引(col1,col2),mysql建立联合索引的规则是首先会对联合合索引的最左边的,也就是第一个字段col1的数据进行排序,在第一个字段的排序基础上,而后再对后面第二个字段col2进行排序。其实就至关于实现了相似 order by col1 col2这样一种排序规则。

  有人会疑惑第二个查询语句不符合最左前缀匹配:首先能够确定是两个查询语句都保函索引(col1,col2)中的col一、col2两个字段,只是顺序不同,查询条件同样,最后所查询的结果确定是同样的。既然结果是同样的,到底以何种顺序的查询方式最好呢?此时咱们能够借助mysql查询优化器explain,explain会纠正sql语句该以什么样的顺序执行效率最高,最后才生成真正的执行计划。

(3)若是只查询col2:SELECT * FROM test WHERE col2=2;

  第一个col字段是绝对有序的,而第二字段就是无序的了。因此一般状况下,直接使用第二个字段col2进行条件判断是用不到索引的。固然是col2字段的索引数据也是有序的状况下才能使用咯,何时才是有序的呢?在col1字段是等值匹配的状况下,cid才是有序的。这也就是mysql索引规则中要求复合索引要想使用第二个索引,必须先使用第一个索引的缘由。(并且第一个索引必须是等值匹配)。

为何要使用联合索引?

  • 减小开销。建一个联合索引(col1,col2,col3),实际至关于建了(col1),(col1,col2),(col1,col2,col3)三个索引。每多一个索引,都会增长写操做的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减小开销!
  • 覆盖索引。对联合索引(col1,col2,col3),若是有以下的sql: select col1,col2,col3 from test where col1=1 and col2=2。那么MySQL能够直接经过遍历索引取得数据,而无需回表,这减小了不少的随机io操做。减小io操做,特别的随机io实际上是dba主要的优化策略。因此,在真正的实际应用中,覆盖索引是主要的提高性能的优化手段之一。
  • 效率高。索引列越多,经过索引筛选出的数据越少。有1000W条数据的表,有以下sql:select from table where col1=1 and col2=2 and col3=3,假设假设每一个条件能够筛选出10%的数据,若是只有单值索引,那么经过该索引能筛选出1000W10%=100w条数据,而后再回表从100w条数据中找到符合col2=2 and col3= 3的数据,而后再排序,再分页;若是是联合索引,经过索引筛选出1000w10% 10% *10%=1w,效率提高可想而知!

http://www.javashuo.com/article/p-najgcbdi-ke.html

  从本质上来讲,联合索引仍是一颗B+树,不一样的是联合索引的键值的数量不是1,而是大于等于2。

  对于查询 SELECT * FROM TABLE WHERE a=xxx and b=xxx,显然能够使用(a,b)这个联合索引。对于单个的a列查询 SELECT * FROM TABLE WHERE a=xxx 也是能够使用(a,b)索引。但对于b列的查询 SELECT * FROM TABLE WHERE b=xxx 不能够使用这颗B+树索引。由于叶节点上的b值为1,2,1,4,1,2,显然不是排序的,所以对于b列的查询使用不到(a,b)的索引。

   联合索引的第二个好处是,能够对第二个键值进行排序。例如,在不少状况下咱们都须要查询某个用户的购物状况,并按照时间排序,去除最近3次的购买记录,这是使用联合索引能够避免多一次的排序操做,由于索引自己在叶节点已经排序了。

  【注】:对于相同的第一个键值的数据,第二个键值是排好序的。

      对于单个列a的查询每每使用单个键的索引,由于其叶节点包含单个键值,能存放的记录更多。

1八、说一说 B+树索引、哈希索引?

Hash索引和B+树索引的特色:

  • Hash索引结构的特殊性,其检索效率很是高,索引的检索能够一次定位;

  • B+树索引须要从根节点到枝节点,最后才能访问到页节点这样屡次的IO访问。

Hash索引与B+树索引区别?

  • 若是是等值查询,那么哈希索引明显有绝对优点,由于只须要通过一次算法便可找到相应的键值;固然了,这个前提是,键值都是惟一的。若是键值不是惟一的,就须要先找到该键所在位置,而后再根据链表日后扫描,直到找到相应的数据;
  • 从示意图中也能看到,若是是范围查询检索,这时候哈希索引就毫无用武之地了,由于原先是有序的键值,通过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;
  • 同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);
  • 哈希索引也不支持多列联合索引的最左匹配规则
  • B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值状况下,哈希索引的效率也是极低的,由于存在所谓的哈希碰撞问题
https://www.zhihu.com/question/263964996

1九、B树和B+树的区别?

B+树是一种平衡查找树在B+树中,全部记录节点都是按键值的大小顺序存放在同一层的叶节点中,各叶结点指针进行链接。

(平衡二叉树AVL:首先符合二叉查找树的定义(最结点的值比根节点小,右结点的值比根结点大),其次必须知足任何节点的左右两个子树的高度最大差为1。)

  • B树  :每一个节点都存储key和data,全部节点组成这棵树,而且叶子节点指针为nul,叶子结点不包含任何关键字信息
  • B+树:全部的叶子结点中包含了所有关键字的信息,及指向含有这些关键字记录的指针,且叶子结点自己依关键字的大小自小而大的顺序连接,全部的非终端结点能够当作是索引部分。

20、为何说B+比B树更适合实际应用中操做系统的文件索引和数据库索引?

(1)B+的磁盘读写代价更低

  B+的内部结点并无指向关键字具体信息的指针。所以其内部结点相对B树更小。若是把全部同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的须要查找的关键字也就越多。相对来讲IO读写次数也就下降了。

(2)B+tree的查询效率更加稳定

  因为非终结点并非最终指向文件内容的结点,而只是叶子结点中关键字的索引。因此任何关键字的查找必须走一条从根结点到叶子结点的路。全部关键字查询的路径长度相同,致使每个数据的查询效率至关。

2一、汇集索引和非汇集索引区别?

  数据库中的B+索引能够分为汇集索引和辅助汇集索引。无论是汇集索引仍是非汇集的索引,其内部都是B+树的,即高度平衡的,叶节点存放着全部的数据,汇集索引与非汇集索引不一样的是,叶节点存放的是不是一整行的信息

  • 汇集索引(clustered index):

  汇集索引就是按照每张表的主键构造一颗B+树而且叶节点中存放着整张表的行记录数据,所以也让汇集索引的叶节点成为数据页。汇集索引的这个特性决定了索引组织表中数据也是索引的一部分。因为实际的数据页只能按照一颗B+树进行排序,所以每张表只能拥有一个汇集索引

  汇集索引表记录的排列顺序和索引的排列顺序一致,因此查询效率快,只要找到第一个索引值记录,其他就连续性的记录在物理也同样连续存放。汇集索引对应的缺点就是修改慢,由于为了保证表中记录的物理和索引顺序一致,在记录插入的时候,会对数据页从新排序。

  • 非汇集索引(nonclustered index)(也叫辅助索引):

  对于辅助索引(非汇集索引),叶级别不包含行的所有数据。汇集索引键来告诉InnoDB存储引擎,哪里能够找到与索引相对应的行数据。辅助索引的存在并不影响数据在汇集索引中的组织,所以每张表上能够有多个辅助索引经过辅助索引来寻找数据时,InnoDB存储引擎会遍历辅助索引并经过叶级别的指针得到指向主键索引的主键,而后再经过主键索引来找到一个完整的行记录

  非汇集索引指定了表中记录的逻辑顺序,可是记录的物理和索引不必定一致,两种索引都采用B+树结构,非汇集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针方式。非汇集索引层次多,不会形成数据重排。

根本区别:

汇集索引和非汇集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致。

2二、说一说drop、deletetruncate的区别?

  • drop直接删掉表。
  • truncate删除表中数据,再插入时自增加id又从1开始。
  • delete删除表中数据,能够加where字句。

(1)truncate和delete只删除数据,而drop则删除整个表(结构和数据)。

(2)delete语句执行删除的过程是每次从表中删除一行,而且同时将该行的删除操做做为事务记录在日志中保存以便进行进行回滚操做。truncate table则一次性地从表中删除全部的数据并不把单独的删除操做记录记入日志保存,删除行是不能恢复的。而且在删除的过程当中不会激活与表有关的删除触发器。执行速度快。

(3)执行速度:drop> truncate >delete

(4)delete语句是dml,这个操做会放到rollback segement,事务提交以后才生效。若是有相应的trigger(触发器),执行的时候将被触发

   truncate、dropddl,操做当即生效,原数据不放到rollback segment,不能回滚,操做不触发trigger

(5)当表被truncate后,这个表和索引所占用的空间会恢复到初始大小, delete操做不会减小表或索引所占用的空间。

(5)应用范围:truncate只能对table;delete能够是table和view

若是直接删除一个表drop,对数据量很大的表,这个过程会占用比较长的时间,若是先truncat后drop table:一、能够下降操做失败的风险;二、能够下降数据字典锁占用的时间,下降系统开销。

2三、drop、deletetruncate分别在什么场景之下使用?

  • 再也不须要一张表的时候,用drop
  • 想删除部分数据行时候,用delete,而且带上where子句
  • 保留表而删除全部数据的时候用truncate

2四、超键、候选键、主键、外键分别是什么?

 超键   :在关系中能惟一标识元组的属性集称为关系模式的超键。一个属性能够为做为一个超键,多个属性组合在一块儿也能够做为一个超键。超键包含候选键和主键。

候选键:是最小超键,即没有冗余元素的超键。

主键    :数据库表中对存储数据对象予以惟一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)。

外键    :在一个表中存在的另外一个表的主键称此表的外键。

2五、mysql为何建议用自增列做为主键?

  若是咱们定义了主键(PRIMARY KEY),那么InnoDB会选择主键做为汇集索引、若是没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的惟一索引做为主键索引、若是也没有这样的惟一索引,则InnoDB会选择内置6字节长的ROWID做为隐含的汇集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。

  1. 使用自增列(INT/BIGINT类型)作主键,这时候写入顺序是自增的,和B+数叶子节点分裂顺序一致;
  2. 该表不指定自增列作主键,同时也没有能够被选为主键的惟一索引(上面的条件),这时候InnoDB会选择内置的ROWID做为主键,写入顺序和ROWID增加顺序一致;
  3. 除此之外,若是一个InnoDB表又没有显示主键,又有能够被选择为主键的惟一索引,但该惟一索引可能不是递增关系时(例如字符串、UUID、多字段联合惟一索引的状况),该表的存取效率就会比较差。

2六、MySQL中的varchar和char的区别以及varchar(50)中的50表明的涵义?

  char是一种固定长度的类型,varchar是一种可变长度的类型。

varchar(50)中50的含义:
    最多存放50个字符,varchar(50)和(200)存储hello所占空间同样,但后者在排序时会消耗更多内存,由于order by col采用fixed_length计算col长度。ppp-

int(20)中20的含义:

   是指显示字符的长度
   但要加参数的,最大为255,好比它是记录行数的id,插入10笔资料,它就显示00000000001 ~~~00000000010,当字符的位数超过11,它也只显示11位,若是你没有加那个让它未满11位就前面加0的参数,它不会在前面加0.
  20表示最大显示宽度为20,但仍占4字节存储,存储范围不变;

mysql为何这么设计:
   对大多数应用没有意义,只是规定一些工具用来显示字符的个数;int(1)和int(20)存储和计算均同样。

2七、什么是视图?视图的使用场景有哪些?

   视图(View)是一个命名的虚表,它由一个查询来定义,能够看成表使用。

视图有什么用(应用场景)

一、当一个查询你须要频频的做为子查询使用时,视图能够简化代码,直接调用而不是每次都去重复写这个东西。
二、系统的数据库管理员,须要给他人提供一张表的某两列数据,而不但愿他能够看到其余任何数据,这时能够建一个只有这两列数据的视图,而后把视图公布给他。

建立视图sql语句:

CREATE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition

视图与表的区别

      一、视图是已经编译好的sql语句,而表不是。
      二、视图没有实际的物理记录,而表有。
      三、表是内容,视图是窗口。
      四、表只用物理空间而视图不占用物理空间,视图只是逻辑概念的存在,表能够及时对它进行修改,但视图只能由建立的语句来修改。
      五、视图是查看数据表的一种方法,能够查询数据表中某些字段构成的数据,只是一些SQL语句的集合。从安全的角度说,视图能够不给用户接触数据表,从而不知道表结构。
      六、表属于全局模式中的表,是实表;视图属于局部模式的表,是虚表。 
      七、视图的创建和删除只影响视图自己,不影响对应的基本表。
      八、不能对视图进行update或者insert into操做。

2八、数据库三大范式?

第一范式(1NF)
  (在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不知足第一范式(1NF)的数据库就不是关系数据库。)

  所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项第一范式就是无重复的列。强调的是列的原子性,即列不可以再分红其余几列。

第二范式(2NF)
  知足第二范式(2NF)必须先知足第一范式(1NF)。另外包含两部份内容,一是表必须有主键;二是没有包含在主键中的列必须彻底依赖于主键,而不能只依赖于主键的一部分。

第三范式(3NF)
  知足第三范式(3NF)必须先知足第二范式(2NF)第三范式就是属性不依赖于其它非主属性。非主键列必须直接依赖于主键,不能存在传递依赖

2九、sql优化

 1. explain sql 分析sql语句,这个语句能够打印出的各类item的意义:

  • select_type :表示查询中每一个select子句的类型
  • type :表示MySQL在表中找到所需行的方式,又称“访问类型”
  • possible_keys :指出MySQL能使用哪一个索引在表中找到行,查询涉及到的字段上若存在索引,则该索引将被列出,但不必定被查询使用。
  • key :显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。
  • key_len :表示索引中使用的字节数,可经过该列计算查询中使用的索引的长度
  • ref :表示上述表的链接匹配条件,即哪些列或常量被用于查找索引列上的值 
  • Extra :包含不适合在其余列中显示但十分重要的额外信息

2. 查询语句不一样元素(where、jion、limit、group by、having等等)执行前后顺序?

查询中用到的关键词主要包含6个,而且他们的顺序依次为 select--from--where--group by--having--order by--limit。

其中select和from是必须的,其余关键词是可选的。

(使用having字句对分组后的结果进行筛选,因此having只能用在group by以后;

 limit 起始记录位置:取记录的条数对记录进行选取,主要用来实现分页功能)

30、非关系型数据库和关系型数据库区别,优点比较?

非关系型数据库的优点:

  • 性能:NOSQL是基于键值对的,能够想象成表中的主键和值的对应关系,并且不须要通过SQL层的解析,因此性能很是高。
  • 可扩展性:一样也是由于基于键值对,数据之间没有耦合性,因此很是容易水平扩展。

关系型数据库的优点:

  • 复杂查询:能够用SQL语句方便的在一个表以及多个表之间作很是复杂的数据查询。
  • 事务支持:使得对于安全性能很高的数据访问要求得以实现。

其余:

1.对于这两类数据库,对方的优点就是本身的弱势,反之亦然。

2.NOSQL数据库慢慢开始具有SQL数据库的一些复杂查询功能,好比MongoDB。

3.对于事务的支持也能够用一些系统级的原子操做来实现例如乐观锁之类的方法来曲线救国,好比Redis set nx。

3一、什么是 内链接、外链接、交叉链接、笛卡尔积等?

  • 内链接: 只链接匹配的行
  • 左外链接: 包含左边表的所有行(无论右边的表中是否存在与它们匹配的行),以及右边表中所有匹配的行
  • 右外链接: 包含右边表的所有行(无论左边的表中是否存在与它们匹配的行),以及左边表中所有匹配的行

例如1:
SELECT a.,b. FROM luntan LEFT JOIN usertable as b ON a.username=b.username

例如2:
SELECT a.,b. FROM city as a FULL OUTER JOIN user as b ON a.username=b.username

  • 全外链接: 包含左、右两个表的所有行,无论另一边的表中是否存在与它们匹配的行。
  • 交叉链接: 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每一个行与另外一个数据源的每一个行都一一匹配

例如:
SELECT type,pub_name FROM titles CROSS JOIN publishers ORDER BY type

1.以A,B两张表为例
A left join B
选出A的全部记录,B表中没有的以null 代替
right join 同理

2.inner join
A,B的全部记录都选出,没有的记录以null代替

3.cross join (笛卡尔积)
A中的每一条记录和B中的每一条记录生成一条记录
例如A中有4条,B中有4条,cross join 就有16条记录

3二、SQL语言分类

  • 数据查询语言DQL :基本结构是由SELECT子句、FROM子句、WHERE子句组成的查询块。
  • 数据操纵语言DML :1)插入INSERT 2) 更新:UPDATE 3) 删除:DELETE
  • 数据定义语言DDL :用来建立数据库中的各类对象-----表、视图、索引、同义词、聚簇等如:CREATE TABLE/VIEW/INDEX/SYN/CLUSTER
          • DDL操做是隐性提交的!不能rollback
  • 数据控制语言DCL :用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。ROLLBACK/COMMIT
  • (1) 显式提交
    • 用COMMIT命令直接完成的提交为显式提交。其格式为:SQL>COMMIT;
  • (2) 隐式提交
    • 用SQL命令间接完成的提交为隐式提交。这些命令是:ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。
  • (3) 自动提交
    • 若把AUTOCOMMIT设置为ON,则在插入、修改、删除语句执行后,系统将自动进行提交。其格式为:SQL>SET AUTOCOMMIT ON;

3三、like %和-的区别

  % 通配符:表示任何字符出现任意次数 (能够是0次)。
  _ 通配符:表示只能匹配单个字符,不能多也不能少,就是一个字符。

使用通配符进行模糊查询须要用 like操做符,例:

  SELECT * FROM products WHERE products.prod_name like '%es%';

  SELECT * FROM products WHERE products.prod_name like '_es';

【注】若是在使用like操做符时,后面的没有使用通用匹配符效果是和 = 是一致的。

   SELECT * FROM products WHERE products.prod_name like '1000':只能匹配的结果为1000,而不能匹配像JetPack 1000这样的结果。

3四、count(*)、count(1)、count(column)的区别

  • count(*)  :对行的数目进行计数,包含NULL
  • count(column) :对特定的列的值具备的行进行计数,不包含NULL值

  • count(1)这个用法和count(*)的结果是同样的,包含null

性能问题:

  1. 任何状况下SELECT COUNT(*) FROM tablename是最优选择;
  2. 尽可能减小SELECT COUNT(*) FROM tablename WHERE COL = ‘value’ 这种查询;
  3. 杜绝SELECT COUNT(COL) FROM tablename WHERE COL2 = ‘value’ 的出现。
  • 若是表没有主键,那么count(1)比count(*)快。
  • 若是有主键,那么count(主键,联合主键)比count(*)快。
  • 若是表只有一个字段,count(*)最快。

  count(1)跟count(主键)同样,只扫描主键;count(*)跟count(非主键)同样,扫描整个表。明显前者更快一些。

3五、大家数据库是否支持emoji表情,若是不支持,如何操做?

若是是utf8字符集的话,须要升级至utf8_mb4方可支持。

3六、你是如何监控大家的数据库的?大家的慢日志都是怎么查询的?

监控的工具备不少,例如zabbix,lepus,我这里用的是lepus。

  • slow_query_log        :慢查询开启状态。
  • slow_query_log_file :慢查询日志存放的位置(这个目录须要MySQL的运行账号的可写权限,通常设置为MySQL的数据存放目录)。
  • long_query_time      :查询超过多少秒才记录。

 

 开启慢日志查询:set global slow_query_log='ON';

那么开启了慢查询日志后,什么样的SQL才会记录到慢查询日志里面呢? 

  这个是由参数long_query_time控制,默认状况下long_query_time的值为10秒,能够使用命令修改,也能够在my.cnf参数里面修改。运行时间大于long_query_time(非大于等于),才会记录到慢查询日志里。

 

3三、谈谈mongodb,mysql的区别和具体应用场景

MongoDB是神马?

  MongoDB是非关系型数据库,是一个基于分布式文件存储的数据库。(文档型数据库:能够存放xml、json、bson类型的数据。)同时MongoDB是由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。 是非关系数据库当中功能最丰富,最像关系数据库的。

  MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档相似于 JSON 对象。字段值能够包含其余文档,数组及文档数组。

  它能够存储比较复杂的数据类型。Mongo最大的特色是它支持的查询语言很是强大,其语法有点相似于面向对象的查询语言,几乎能够实现相似关系数据库单表查询的绝大部分功能,并且还支持对数据创建索引。

  mongodb与mysql不一样,mysql的每一次更新操做都会直接写入硬盘,可是mongo不会,做为内存型数据库,数据操做会先写入内存,而后再会持久化到硬盘中去 ,但MongoDB采用的预分配空间的方式来防止文件碎片,因此MongoDB的数据文件很大。

  MongoDB的特色是:

  (1)面向文档(2)高性能(3)高可用(4)易扩展(5)丰富的查询语言

  MongoDB 缺点:

    ① MongoDB 不支持事务操做(最主要的缺点)
    ② MongoDB 占用空间过大
    ③ MongoDB 没有如 MySQL 那样成熟的维护工具,这对于开发和IT运营都是个值得注意的地方

  存储方式:虚拟内存+持久化。

  持久化方式:MongoDB 的全部数据其实是存放在硬盘的,全部要操做的数据经过 mmap 的方式映射到内存某个区域内。而后,MongoDB 就在这块区域里面进行数据修改,避免了零碎的硬盘操做。

mongodb,mysql的区别?

  (1)MongoDB 非关系型数据库,MySql是关系型数据库

  (2)MongoDB存储方式:虚拟内存+持久化; MySql在不一样的引擎上有不一样 的存储方式。

  (3)MongoDB查询语句:是独特的Mongodb的查询方式; MySqlMySql查询语句是使用传统的sql语句,拥有较为成熟的体系,成熟度很高。

  (4)mysql的每一次更新操做都会直接写入硬盘,可是mongo的数据操做会先写入内存,而后再会持久化到硬盘中去 。(MongoDB数据是存储在硬盘上的,只不过须要常常读取的数据会被加载到内存中,将数据存储在物理内存中,从而达到高速读写。)

  (5)mysql缺点就是在海量数据处理的时候效率会显著变慢。在适量级的内存的Mongodb的性能是很是迅速的。

  (6)MongoDB 不支持事务操做,mysql的innodb和bdb存储引擎支持事务。(注:myisam不支持事务)

 

34.一条sql语句的执行过程?

先简单介绍一下一些组件的基本做用:

  • 链接器: 身份认证和权限相关(登陆 MySQL 的时候)。
  • 查询缓存: 执行查询语句的时候,会先查询缓存(MySQL 8.0 版本后移除,由于这个功能不太实用)。
  • 分析器: 没有命中缓存的话,SQL 语句就会通过分析器,分析器说白了就是要先看你的 SQL 语句要干吗,再检查你的 SQL 语句语法是否正确。
  • 优化器: 按照 MySQL 认为最优的方案去执行。
  • 执行器: 执行语句,而后从存储引擎返回数据。

 

一条查询语句的执行顺序:

1.客户端经过TCP链接发送链接请求到mysql链接器,链接器会对该请求进行权限验证及链接资源分配

2.创建链接后客户端发送一条语句,mysql收到该语句后,经过命令分发器判断其是不是一条select语句,若是是,在开启查询缓存的状况下,先在查询缓存中查找该SQL是否彻底匹配,若是彻底匹配,验证当前用户是否具有查询权限,若是权限验证经过,直接返回结果集给客户端,该查询也就完成了。若是不匹配继续向下执行。

3.若是在查询缓存中未匹配成功,则将语句交给分析器做语法分析,MySQL须要知道到底要查哪些东西,若是语法不对,就会返回语法错误中断查询。

4.分析器的工做完成后,将语句传递给预处理器,检查数据表和数据列是否存在,解析别名看是否存在歧义等

5.语句解析完成后,MySQL就知道要查什么了,以后会将语句传递给优化器进行优化(经过索引选择最快的查找方式),并生成执行计划。

6.以后交给执行器去具体执行该语句,在执行以前,会先检查该用户是否具备查询权限,若是有,继续执行该语句。执行器开始执行后,会逐渐将数据保存到结果集中,同时会逐步将数据缓存到查询缓存中,最终将结果集返回给客户端。(若是该SQL执行过程当中超过了慢查询阀值,该SQL会被记录到慢查询日志中) 

一条更新语句的执行顺序:

 。。。。。

  有一条记录须要更新的时候,InnoDB引擎就会先把记录写到 redo log(粉板)里,并更新到内存,这个时候更新就算完成了,同时,InnoDB引擎会在适合的时候,将这个操做记录更新到磁盘里面,而这个更新每每实在系统比较空闲的时候作。

 

MySQL中一条SQL语句的执行过程

一条SQL更新语句是如何执行的

 

 

参考史上最全的数据库面试题,不看绝对后悔

  【MySQL】20个经典面试题

  数据库常见面试题(附答案)

相关文章
相关标签/搜索