1.什么是存储过程?有哪些优缺点?
存储过程Procedure是一组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称并给出参数来执行。
存储过程中可以包含逻辑控制语句和数据操纵语句,它可以接受参数、输出参数、返回单个或多个结果集以及返回值。
由于存储过程在创建时即在数据库服务器上进行了编译并存储在数据库中,所以存储过程运行要比单个的SQL语句块要快。同时由于在调用时只需用提供存储过程名和必要的参数信息,所以在一定程度上也可以减少网络流量、简单网络负担。
2.介绍一下mysql的索引(优缺点?存储结构等,索引类型?)
MyISAM使用的B+树,树的叶子节点存放执行指向数据的地址;
InnoDB也是使用的B+树,但是叶子节点存放的是数据,数据文件本身就是索引文件;
InnoDB是聚类索引,辅助索引data域存储相应记录主键的值而不是地址;聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。
索引有唯一索引,主键索引,全文索引,普通索引。
3.事务介绍
主要四个事务隔离级别
4.数据库的乐观锁和悲观锁是什么?
悲观锁,往往依靠数据库提供的锁机制 (也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据) ,需要关闭数据库的自动提交功能,autocommit=0;通过select。。。 for update拿到锁。
乐观锁,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本,有版本号或者时间戳方式,需要通过代码来实现(类似CAS的功能)
处理如下,加上版本号的处理
1.查询出商品信息 select (status,status,version) from t_goods where id=#{id} 2.根据商品信息生成订单 3.修改商品status为2 update t_goods set status=2,version=version+1 where id=#{id} and version=#{version};
5.使用索引查询一定能提高查询的性能吗?为什么
不一定,在以下情况中不一定会有性能的提升
- 当查询结果返回的数据集较大时,使用索引并不会提升性能;
- 对于值比较少的字段,比如性别,使用索引性能也不会有多少提升;
6.简单说一说drop、delete与truncate的区别
相同点:drop、delete(不带where子句)、truncate都会删除表中的数据
不同点:
- 1.truncate与delete只删除表的数据,不删除表的结构;而drop会删除表的结构被依赖的约束、索引、触发器,但是存储过程/函数会保留,但是会变为invalid状态(所以delete table后,再插入时的自增ID不是从1开始,而是从之前最大的值+1开始);
- 2.delete是DML,删除的数据会存储在系统的回滚段中,需要的时候,数据可以回滚恢复;而truncate、delete是DDL,删除的数据的操作立即生效,且原数据不放回segment rollback中,无法回滚恢复。所以慎用。
- delete不会自动提交事务,操作会触发trigger,而truncate、drop自动提交事务,且不触发trigger。
- 速度来说,一般是drop>truncate>delete
-
因为delete语句不影响表所占用的extent,高水位(high watermark)保持原位置不动;而drop语句将表所占用的空间全部释放,truncate语句缺省情况下将空间释放到minextents个extent,除非使用reuse storage;否则truncate会将高水位复位,因为默认情况下truncate table = truncate table drop storage;
PS:使用select语句查询数据时,数据库会扫描高水位线以下的数据块,因为高水位线没有变化,所以扫描的时间不会减少,所以才会出现使用delete删除数据以后,查询的速度还是和delete以前一样。
7.drop、delete与truncate分别在什么场景之下使用?
6中已经把特点介绍的比较清楚了:
想删除部分数据行用delete,注意带上where子句,回滚段要足够大;
想删除表,当然用drop;
想保留表而将所有数据删除,如果和事务无关,用truncate即可;
如果和事务有关,或者想触发trigger,还是用delete;
如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据。
8.mysql里面的行锁和表锁介绍?
- 表锁:开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低
- 行锁:开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高
MyISAM引擎使用的表锁,InnoDB有行锁和表锁。表锁只有在条件为有索引的情况下才会使用,行锁实际是针对索引的。
具体锁的简绍见Mysql锁机制
9.超键、候选键、主键、外键分别是什么?
粘贴过来的
超键:在关系模式中,能唯一标识元组的属性集称为超键。
候选键 :如果一个属性集能唯一标识元组,且有不包含多余属性,那么这个属性集称为候选键(候选键是没有多余属性的超键)
主键:关系模式中用户正在使用的候选键称主键(primary key)。一般,如不加说明,键是指主键。
外键:在关系模式R中,如果某属性集是其他模式的候选键,那么该属性集对模式R来说就是外键
10.什么是视图?以及视图的使用场景有哪些?
视图就是将你需要的几张表中的数据整合到一张表上面。方便操作,特别是查询操作,减少复杂的SQL语句,增强可读性;
使用场景:
权限控制的时候,不希望用户访问表中某些含敏感信息的列,比如salary...
关键信息来源于多个复杂关联表,可以创建视图提取我们需要的信息,简化操作。
11.说三个范式。
1.第一范式(确保每列保持原子性)
第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
2.第二范式(确保表中的每列都和主键相关)
第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
3.第三范式(确保每列都和主键列直接相关,而不是间接相关)
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
12.mysql查询优化有哪些手段?
1.数据库设计方面;包括索引的添加,字段类型,是否允许非空等等。
2.数据库查询方面;优化查询条件,尽量使用到索引,避免全表扫描
3.连接方面,数据库连接池的,使用orm的框架等
13.例举mysql可能出现死锁的场景
MyISAM基于的是表锁,所以不会出现死锁的情况。InnoDB大部分情况下使用的行锁,比如两个存在客户端执行事务:
session1 session2
获取表1的排它锁 获取表2的排它锁
获取表2的排它锁(进入等待) 获取表1的排它锁(这时就会进入死锁)
这样就进入了相互等待的过程,所以会造成死锁
14.mysql死锁怎么解决的?
发生死锁后,InnoDB一般都会自动检测到,并使一个事务释放锁并回退事务,另一个事务获取锁,继续执行。在设计外部锁,外部表锁的情况下,InnoDB并不能完全检测到死锁,这时候通过设置锁等待的超时时间来解决。innodb_lock_wait_timeout
15.InnoDB什么时候会用到行锁,什么情况下会用到表锁?
- 第一种情况是:事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间锁等待和锁冲突,这种情况下可以考虑使用表锁来提高该事务的执行速度。
- 第二种情况是:事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚。这种情况也可以考虑一次性锁定事务涉及的表,从而避免死锁、减少数据库因事务回滚带来的开销。
16.索引字段为什么越小越好?
从索引的数据结构来讲,因为索引使用的B+树,而B+树的高度决定了查询的时间,每高度增加1,即一次磁盘分页读取。因为磁盘的分页大小是固定的,所以需要尽可能的让每一页存更多的数据,所以如果索引字段比较大的话,每一页存的数量就会少了,这样就会增加B+树的高度。
还有在InnoDB中,辅助索引都引用主索引的值,这样如果主索引值太大的话,所有辅助索引都会变大。
17.为什么建议使用一个也业务ID不相干的字段来作为主键?
1.如果使用身份证号或学号,首先主键索引值会比较大,而辅助索引都会引用主键索引的值,辅助索引也会变大;
2.如果使用学号或身份证号,每次插入时,会根据主键将其插入到合适的节点和位置,如果达到装载因子,会开辟一个新的页(内存页或磁盘页),
如果使用自增主键,每次都是顺序插入,达到装载因子时,开辟一个新的页,这样就会形成一个非常紧凑的索引结构,由于每次插入也不需要移动已有数据,因此效率很高。如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。