1.mySQL和Oracle的区别
对事务的提交,MySQL自动提交,Oralce手动提交;分页查询,Oracle需要用到伪列ROWNUM和嵌套查询;自动增长数据类型的处理;日期字段的处理,MYSQL日期字段分DATE和TIME两种,ORACLE日期字段只有DATE;Oracle是大型数据库,mySQL是中小型数据库;单引号的处理,Oracle只能用单引号包起字符串;MySQL的分区表还不太成熟稳定,Oracle的分区表和分区索引功能很成熟;事务的隔离级别, MySQL是read commited(可重复读)的隔离级别,而Oracle是repeatable read(读已提交)的隔离级别。
Oralce特有的函数:length、lengthb、INSTR(源字符串, 目标字符串, 起始位置)、substr( string, start_position, [ length ] )、trim(LTRIM/RTRIM)函数、lower/upper函数、nvl函数
2.数据库事务的隔离级别
读未提交(read uncommitted)--脏读、读已提交(read committed)--不可重复读、可重复读(Repeatable read)--幻读、可串行化(Serializable)。oracle默认的隔离级别为读已提交,mysql的默认隔离级别为可重复读。
脏读:读取未提交数据。指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据
不可重复读:前后多次读取,数据内容不一致。是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
幻读:前后多次读取,数据总量不一致。是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
3.mySQL引擎
Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别。该引擎还提供了行级锁和外键约束,MySQL运行时Innodb会在内存中建立缓冲池,用于缓冲数据和索引,5.5之后默认Innodb。myISAM没有提供对数据库事务的支持,也不支持行级锁和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。
1) InnoDB支持事务和外键,myISAM不支持;
2) InnoDB支持行锁,MyISAM不支持;
3) InnoDB是聚集索引,使用B+Tree作为索引结构,必须要有主键,MyISAM是非聚集索引,也是使用B+Tree作为索引结构;
4) InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描,而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快(注意不能加有任何WHERE条件);
5) Innodb不支持全文索引,而MyISAM支持全文索引,在涉及全文索引领域的查询效率上MyISAM速度更快高;
6) Innodb存储文件有frm、ibd,frm是表定义文件,ibd是数据文件;而Myisam是frm、MYD、MYI,frm是表定义文件,myd是数据文件,myi是索引文件
7) InnoDB不支持FULLTEXT类型的索引;
8) InnoDB适用insert和update的操作比较多的应用,myISAM查询速度很快,适合频繁查询及涉及安全性较高的应用;
9) 删除表时,InnoDB逐行删除,myISAM重建表;
4.char、varchar 、nchar和nvarchar的区别
char长度固定,存储ANSI字符,长度0~255,自动用空格填充到设定长度;varchar存储长数据,存储ANSI字符,存储效率没有char高,必须在括号里定义长度,可以有默认值。保存数据的时候,不进行空格自动填充,而且如果数据存在空格时,当值保存和检索时尾部的空格仍会保留,varchar类型的实际长度是它的值的实际长度+1,这一个字节用于保存实际使用了多大的长度。
varchar 长度可变,存储ANSI字符,根据数据长度自动变化。存储变长数据,但存储效率没有CHAR高;nvarchar长度可变,存储Unicode字符,根据数据长度自动变化
5.mySQl索引及优化
索引是关系型数据库中给数据库表中一列或者多列的值排序后的储存结构,SQL的主流索引结构有B+树以及Hash结构,聚集索引以及非聚集索引用的是B+树索引。创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件),实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。更新表时,MySQL不仅要保存数据,还要保存一下索引文件。 MySql索引类型有:唯一索引、主键(聚集)索引、非聚集索引、全文索引。 CREATE INDEX indexName ON table(username(length)) ALTER table tableName ADD INDEX indexName(columnName)
使用: 建立索引的目的就是帮助查询,如果查寻用不到则索引就没有必要建立;如果表是经常需要更新的也不适合做索引 。频繁更新会导致索引也会频繁更新,降低写的效率; 给一个字段创建了索引的话,而这个字段要进行like模糊查询的话,那么这个值左边不可以有%;如果数据表过大(5w以上)则有些字段(字符型长度超过(40))不适合作为索引,使用索引时会先过一遍索引,再过一遍数据。
索引失效:
1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
2.对于多列索引,不是使用的第一部分,则不会使用索引
3.like查询已 '%...'开头,以'xxx%'结尾会继续使用索引
4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
5.where语句中使用 <>和 != ,where语句中使用Not In ,where语句中对字段表达式操作
6.如果mysql估计使用全表扫描要比使用索引快,则不使用索引
查看索引的使用情况:
show status like ‘Handler_read%’;
索引分类
1.普通索引 index :加速查找
2.唯一索引 主键索引:primary key :加速查找+约束(不为空且唯一) 唯一索引:unique:加速查找+约束 (唯一)
3.联合索引 primary key(id,name):联合主键索引 unique(id,name):联合唯一索引 index(id,name):联合普通索引
4.全文索引 fulltext :用于搜索很长一篇文章的时候,效果最好。
前缀索引:使用字符串的前几个字符作为索引,选择足够长的前缀以保证较高的选择性,同时又不能太长,前缀索引进行ORDER BY和GROUP BY,也无法用来进行覆盖扫描。
全列选择性 SELECTCOUNT(DISTINCTcolumn_name)/COUNT(*) FROM table_name;
测试某一长度前缀的选择性 SELECT COUNT(DISTINCT LEFT(column_name, prefix_length)) / COUNT(*)FROMtable_name;
索引覆盖:如果一个索引覆盖(包含)了所有需要查询的字段的值,这个索引就是覆盖索引。因为索引中已经包含了要查询的字段的值,因此查询的时候直接返回索引中的字段值就可以了,不需要再到表中查询,避免了对主键索引的二次查询,也就提高了查询的效率。
回表:索引执行顺序,先搜索普通索引树,找到符合条件的叶子节点(主键),然后去聚簇索引拿到对应的行数据。
6.聚集索引和非聚集索引
聚集索引:数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。 数据库在创建主键同时,会自动建立一个唯一索引。如果这个表之前没有聚集索引,同时建立主键时候没有强制指定使用非聚集索引,则建立主键时候,同时建立一个唯一的聚集索引。
非聚合索引 :该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。
7.慢查询
MySQL会记录下查询超过指定时间的语句,我们将超过指定时间的SQL语句查询称为慢查询,都记在慢查询日志里。
查看慢查询配置 show variables like “%slow%” ;
查看慢查询 show status like 'slow_queries';
查询慢查询时间 show variables like 'long_query_time';
设置慢查询时间,当SQL语句执行时间超过此数值时,就会被记录到日志中 set long_query_time = 0.5;
8.悲观锁/乐观锁
乐观锁:总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量。
乐观锁每次在执行数据的修改操作时,都会带上一个版本号,一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行+1操作,否则就执行失败。因为每次操作的版本号都会随之增加,所以不会出现ABA问题,因为版本号只会增加不会减少。
悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
要使用悲观锁,我们必须关闭MySQL数据库的自动提交属性。因为MySQL默认使用autocommit模式,也就是说,当我们执行一个更新操作后,MySQL会立刻将结果进行提交。(sql语句:set autocommit=0)
在乐观锁与悲观锁的选择上面,主要看下两者的区别以及适用场景
乐观锁并未真正加锁,效率高。一旦锁的粒度掌握不好,更新失败的概率就会比较高,容易发生业务失败。
悲观锁依赖数据库锁,效率低。更新失败的概率比较低。
9.数据库分表 / 分库
垂直(纵向)切分:垂直切分常见有垂直分库和垂直分表两种,垂直分库就是根据业务耦合性,将关联度低的不同表存储在不同的数据库。做法与大系统拆分为多个小系统类似,按业务分类进行独立划分。与"微服务治理"的做法相似,每个微服务使用单独的一个数据库。垂直分表是基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不经常用或字段长度较大的字段拆分出去到扩展表中。在字段很多的情况下(例如一个大表有100多个字段),通过"大表拆小表",更便于开发与维护,也能避免跨页问题,MySQL底层是通过数据页存储的,一条记录占用空间过大会导致跨页,造成额外的性能开销。另外数据库以行为单位将数据加载到内存中,这样表中字段长度较短且访问频率较高,内存能加载更多的数据,命中率更高,减少了磁盘IO,从而提升了数据库性能。缺点:部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度;分布式事务处理复杂。
水平(横向)切分:水平切分分为库内分表和分库分表,是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。库内分表只解决了单一表数据量过大的问题,但没有将表分布到不同机器的库上,因此对于减轻MySQL数据库的压力来说,帮助不是很大,大家还是竞争同一个物理机的CPU、内存、网络IO,最好通过分库分表来解决。缺点:跨分片的事务一致性难以保证;部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度。
常用的支持分库分表中间件:sharding-jdbc(当当)、TSharding(蘑菇街)、Atlas(奇虎360)、Cobar(阿里巴巴)、MyCAT(基于Cobar)、Vitess(谷歌)
10.MySQL索引为什么用B+树
B+树的磁盘读写代价更低,因为B+树的所有非叶子节点只会存放索引信息,而真正的数据信息都只存放在叶子节点中,这样一来,每个非叶子节点存放的索引信息就更多,一次磁盘IO就可以读取更多的索引信息到内存中,可以减少磁盘IO的次数。
B+树的查询效率更加稳定,由于非叶子节点只存索引信息,而没有真正的数据信息,所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
B+树更加适合在区间查询的情况,由于B+树的数据都存储在叶子结点中,非叶子结点均为索引,只需要扫一遍叶子结点即可得到所有数据信息,但是B树因为其非叶子结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。
11.复合索引
两个或更多个列上的索引被称作复合索引。利用索引中的附加列,缩小搜索的范围,但使用一个具有两列的索引 不同于使用两个单独的索引。 实现:采用B+树实现,每个节点含有多个关键字,排序时按照多个关键字来排序。
12.主键和唯一索引的区别
主键是一种约束,唯一索引是一种索引,两者在本质上是不同的;主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键; 唯一性索引列允许空值,而主键列不允许为空值;一个表最多只能创建一个主键,但可以创建多个唯一索引;主键可以被其他表引用为外键,而唯一索引不能。
13. Varchar(2000)创建索引会怎样
使用InnoDB引擎创建组合索引(index)时,如果某个索引列的长度超过767 -> 给出warning,索引创建成功,超过767字节的列自动取前缀索引。 我们知道utf-8一般使用3个字节存储一个字,它是按照最大存储空间计算可以存储的字符数。767最大长度的限制对于utf-8编码的字段来说,最多能存放767 / 3 = 255.3个字。也就是说,如果创建的索引中包含一个varchar(256)会报warning,而把它改为varchar(255)就没有warning。
14.数据库事务
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作(对数据库的相关增删改查的操作),要么完全地执行,要么完全地不执行。 数据库的四大特性ACID,原子性、一致性、隔离性、持久性。每个特性都有其特定的职责。
原子性:一个事务中的所有操作,要不 操作全部成功,要不全部失败,不能存在中间态。
一致性:事务必须使得数据库从一个一致性状态转变到另一个一致性状态。比如银行转账,A账户转到B账户,不管转几次,A和B账户的总额不变。
隔离性:是指多个用户同时请求数据库,开启多个事务同时处理某个数据库,隔离性保证了各个事务之间均不受干扰,每个事务都感觉不到其他事务的存在。
持久性:对数据库的修改是持久性的,一旦修改,就算数据库系统出现故障,这种修改也不会丢失。
15.MySQL B+Tree索引和Hash索引的区别?
如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;
如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);哈希索引也不支持多列联合索引的最左匹配规则;
B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。
16.mysql都有什么锁,死锁判定原理和具体场景,死锁怎么解决
表级锁:myISAM 开销小,加锁快,不会出现死锁,锁定粒度大,并发量低,发生锁冲突概率大
行级锁:InnoDB 开销大,加锁慢,会出现死锁,锁定粒度小,并发量高,发生锁冲突概率小
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
死锁的解决办法
1.查出的线程杀死 kill SELECT trx_MySQL_thread_id FROM information_schema.INNODB_TRX;
2.设置锁的超时时间 Innodb 行锁的等待时间,单位秒。可在会话级别设置,RDS 实例该参数的默认值为 50(秒)。
生产环境不推荐使用过大的 innodb_lock_wait_timeout参数值
该参数支持在会话级别修改,方便应用在会话级别单独设置某些特殊操作的行锁等待超时时间,如下:
set innodb_lock_wait_timeout=1000; —设置当前会话 Innodb 行锁等待超时时间,单位秒。
3.指定获取锁的顺序
17.排它锁
select … for update 排他锁的申请前提:没有线程对该结果集中的任何行数据使用排他锁或共享锁,否则申请会阻塞。for update仅适用于InnoDB,且必须在事务块(BEGIN/COMMIT)中才能生效。在进行事务操作时,通过“for update”语句,MySQL会对查询结果集中每行数据都添加排他锁,其他线程对该记录的更新与删除操作都会阻塞。排他锁包含行锁、表锁。
18.非关系型数据库和关系型数据库
关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织
优点:1、易于维护:都是使用表结构,格式一致;2、使用方便:SQL语言通用,可用于复杂查询;3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。
缺点:1、读写性能比较差,尤其是海量数据的高效率读写;2、固定的表结构,灵活度稍欠;3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈
非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。
优点:1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;3、高扩展性;4、成本低:nosql数据库部署简单,基本都是开源软件。
缺点:1、不提供sql支持,学习和使用成本较高;2、无事务处理;3、数据结构相对复杂,复杂查询方面稍欠。
19.mySQL日志
1.错误日志(error log):记录mysql服务的启停时正确和错误的信息,还记录启动、停止、运行过程中的错误信息。
2.查询日志(general log):记录建立的客户端连接和执行的语句。
3.二进制日志(bin log):记录所有更改数据的语句,可用于数据复制。
4.慢查询日志(slow log):记录所有执行时间超过long_query_time的所有查询或不使用索引的查询。
5.中继日志(relay log):主从复制时使用的日志。
20.什么是内连接、外连接、交叉连接(笛卡尔积)?
内连接(inner join):取得两张表中满足存在连接匹配关系的记录。
外连接(outer join):取得两张表中满足存在连接匹配关系的记录,以及某张表(或两张表)中不满足匹配关系的记录。具体又分为:左外链接、右外连接、全外链接。
交叉连接(cross join):显示两张表所有记录一一对应,没有匹配关系进行筛选,也被称之为:笛卡尔积
21.索引的最左前缀原则
在Mysql建立多列索引(联合索引)有最左前缀的原则,即最左优先。
如果我们建立了一个2列的联合索引(col1,col2),实际上已经建立了两个联合索引(col1)、(col1,col2);如果有一个3列索引(col1,col2,col3),实际上已经建立了三个联合索引(col1)、(col1,col2)、(col1,col2,col3)。
22.数据库的三大范式
第一范式(确保每列保持原子性) 列不可再分
第二范式(确保表中的每列都和主键相关) 属性完全依赖于主键
第三范式(确保每列都和主键列直接相关,而不是间接相关) 属性不依赖于其它非主属性 属性直接依赖于主键
23.SQL优化
1、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
3、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
4、应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描
5、下面的查询也将导致全表扫描:select id from t where name like '%abc%' 若要提高效率,可以考虑全文检索
6、应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描
7、不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引