基础

非关系型数据库和关系型数据库的区别?

关系型 非关系型
优点 易于维护:都是使用表结构,格式一致;
使用方便:SQL语言通用,可用于复杂查询;
复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。
格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;
高扩展性;
成本低:nosql数据库部署简单,基本都是开源软件。
缺点 读写性能比较差,尤其是海量数据的高效率读写;
固定的表结构,灵活度稍欠;
高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈
不提供sql支持,学习和使用成本较高;
无事务处理;
数据结构相对复杂,复杂查询方面稍欠。

存储引擎

mysql 两种常用存储引擎,MyISAM InnoDB ,默认为InnoDB

MyISAM

不支持事务,但是每次查询都是原子的
支持表级锁,即每次操作是对整个表加锁
存储表的总行数,即查询的时候非常快
一个MyISAM表三个文件:索引文件,表结构文件,数据文件
采用非聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致。但是辅索引不用保证唯一性。

InnoDb

支持ACID的事务,支持事务的四种隔离级别
支持行级锁及外键约束:因此可以支持写并发
不存出总行数
一个InnoDB引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多个文件里),也有可能为多个(设置为独立表空间,表大小受操作系统文件大小限制。一般为2G),受操作系统文件大小的限制。
主键索引采用聚集索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值。因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时,为维持B+树结构,文件的大调整。

事 务 的 四 大 特 性 了 解 么 ?

原⼦性

事务是最⼩的执⾏单位,不允许分割。事务的原⼦性确保动作要么全部完成,要么完全不起作⽤

⼀致性

事务是最⼩的执⾏单位,不允许分割。事务的原⼦性确保动作要么全部完成,要么完全不起作⽤

隔离性

事务是最⼩的执⾏单位,不允许分割。事务的原⼦性确保动作要么全部完成,要么完全不起作⽤

隔离性

事务是最⼩的执⾏单位,不允许分割。事务的原⼦性确保动作要么全部完成,要么完全不起作⽤

MySQL 事 务 隔 离 级 别 ? 默 认 是 什 么 级 别 ?

SQL 标准定义了四个隔离级别:
READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据, 可以阻⽌脏读,但是幻读或不可重复读仍有可能发⽣。
REPEATABLE-READ(可重复读): 对同⼀字段的多次读取结果都是⼀致的,除⾮数据是被本身事务⾃⼰所修改, 可以阻⽌脏读和不可重复读,但幻读仍有可能发⽣。
SERIALIZABLE(可串⾏化): 最⾼的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执⾏,这样事务之间就完全不可能产⽣⼲扰,也就是说, 该级别可以防⽌脏读、不可
重复读以及幻读。

MySQL InnoDB 存储引擎的默认⽀持的隔离级别是 REPEATABLE-READ(可重读) 。

乐观锁与悲观锁的区别

乐观锁

定义

指的是在操作数据的时候非常乐观,认为别人不会修改数据。因此乐观锁不会上锁。只有在执行更新的时候才会去判断在此期间别人是否修改了数据,如果别人修改了数据则放弃操作,否则执行操作。
乐观锁适用于写比较少的情况下

实现

乐观锁的实现方式主要有两种,一种是CAS(Compare and Swap,比较并交换)机制,一种是版本号机制
CAS机制
CAS操作包括了三个操作数,分别是需要读取的内存位置(V)、进行比较的预期值(A)和拟写入的新值(B),操作逻辑是,如果内存位置V的值等于预期值A,则将该位置更新为新值B,否则不进行操作。另外,许多CAS操作都是自旋的,意思就是,如果操作不成功,就会一直重试,直到操作成功为止。
版本号机制
版本号机制的基本思路,是在数据中增加一个version字段用来表示该数据的版本号,每当数据被修改版本号就会加1。当某个线程查询数据的时候,会将该数据的版本号一起读取出来,之后在该线程需要更新该数据的时候,就将之前读取的版本号与当前版本号进行比较,如果一致,则执行操作,如果不一致,则放弃操作。

悲观锁

定义

指的是在操作数据的时候比较悲观,悲观地认为别人一定会同时修改数据,因此悲观锁在操作数据时是直接把数据上锁,直到操作完成之后才会释放锁,在上锁期间其他人不能操作数据。

实现

悲观锁的实现方式也就是加锁,加锁既可以在代码层面(比如Java中的synchronized关键字),也可以在数据库层面(比如MySQL中的排他锁)。

CHAR 和VARCHAR 的区别?

1、CHAR 和 VARCHAR 类型在存储和检索方面有所不同
2、CHAR 列长度固定为创建表时声明的长度, 长度值范围是 1 到 255 当 CHAR 值被存储时, 它们被用空格填充到特定长度, 检索 CHAR 值时需删除尾随空格

索引

定义

索引是帮助MySQL高效获取数据的排好序数据结构

索引数据结构

  • 二叉树
  • 红黑树
  • Hash表
  • B-Tree

    为什么索引能提高查询速度 ?

    索引是帮助MySQL高效获取数据的数据结构,通过不断的缩小想要获得数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事

聚集索引和非聚集索引的区别?非聚集索引一定回表查询吗?

MySQL 索引类型有:唯一索引,主键(聚集)索引非聚集索引,全文索引。

  • 聚集索引:就是以主键创建的索引。
  • 非聚集索引:就是以非主键创建的索引(也叫做二级索引)。

区别

  • 聚集索引在叶子节点存储的是表中的数据。
  • 非聚集索引在叶子节点存储的是主键和索引列。

索引这么多优点,为什么不对表中的每一个列创建一个索引呢?(使用索引一定能提高查询性能吗? )

1、索引是有大量数据的时候才建立的,没有大量数据反而会浪费时间,因为索引是使用二叉树建立.
2、当一个系统查询比较频繁,而新建,修改等操作比较少时,可以创建索引,这样查询的速度会比以前快很多,同时也带来弊端,就是新建或修改等操作时,比没有索引或没有建立覆盖索引时的要慢。
3、索引并不是越多越好,太多索引会占用很多的索引表空间,甚至比存储一条记录更多。
对于需要频繁新增记录的表,最好不要创建索引,没有索引的表,执行insert、append都很快,有了索引以后,会多一个维护索引的操作,一些大表可能导致insert 速度非常慢。

索引底层的数据结构了解么?Hash索引和B+树索引优劣分析

索引的各种存储结构:二叉树,红黑树, Hash, B-Tree, B+Tree(MySQL索引的真正存储结构)

Hash索引

优点:对数据进行Hash(散列)运算,主流的Hash算法有MD5、SHA256等等,然后将哈希结果作为文件指针可以从索引文件中获得数据的文件指针,再到数据文件中获取到数据,按照这样的设计,我们在查找where Col2 = 22的记录时只需要对22做哈希运算得到该索引所对应那行数据的文件指针,从而在MySQL的数据文件中定位到目标记录,查询效率非常高。
缺点:无法解决范围查询(Range)的场景,比如 select count(id) from sus_user where id >10;因此Hash这种索引结构只能针对字段名=目标值的场景使用。不适合模糊查询(like)的场景。

B+Tree(MySQL索引的真正存储结构)

  • 非叶子节点中不存储data,只存储索引,可以放更多的索引
  • 叶子节点包含所有索引字段
  • 叶子节点包含数据(key和data域)和指针
  • 叶子节点用指针连接,提高区间访问的性能


B +树做索引比红黑树(B树)好在哪里?

  • B+树非叶子节点只存储key值,而B-树存储key值和data值,这样B+树每次读取时可以读取到更多的key值
  • mysql进行区间访问时,由于B+树叶子节点之间用指针相连,只需要遍历所有的叶子节点即可;而B-树则需要中序遍历那样遍历
  • B+树非叶子节点只存储key值,而B-树存储key值和data值,导致B+树的层级更少,查询效率更高
  • B+树所有关键词地址都存在叶子节点上,所以每次查询次数都相同,比B-树稳定

    为什么高度为3的B+树存储千万级数据?

    解释这个问题的前提,mysql使用InnoDB引擎,mysql默认页文件大小为16k
    假设我们一行数据大小为1k,那么一页存储16条数据,也就是说一个叶子节点能存储16条数据
    再来看看非叶子节点,假设主键ID为bigint类型,那么长度为8B,指针大小在InnoDB引擎中的大小为6B,一共14B,那么一页中可以存放16k/14B=1170个(主键+指针)
    也就是说高度为2的B+树可以存储的数据为:117016=18720条;高度为3的B+树可以存储的数据为:1170117016=21902400(千万条数据)
    *这也是为什么mysql可以支撑千万级别数据的原因

    最左前缀匹配原则了解么?

    最左匹配原则:最左优先,以最左边的为起点任何连续的索引都能匹配上,如不连续,则匹配不上。

    什么是覆盖索引

    就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。当发起一个被索引覆盖的查询(也叫作索引覆盖查询)时,在EXPLAIN的Extra列可以看到“Using index”的信息。

    什么情况下设置了索引但无法使用

  1. 没有符合最左前缀原则
    2. 字段进⾏了隐式数据类型转化
    3. ⾛索引没有全表扫描效率⾼

    进阶

    一条 SQL 语句在 MySQL 中如何执行的?

    MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用,redolog 只有 InnoDB 有。

•SQL 等执行过程分为两类,一类对于查询等过程如下:权限校验—-》查询缓存—-》分析器—-》优化器—-》权限校验—-》执行器—-》引擎
•对于更新等语句执行流程如下:分析器——》权限校验——》执行器—-》引擎—-redo log prepare—-》binlog—-》redo log commit

explain命令了解么?

慢查询命令

EXPALIN只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划。

执行计划包含的信息

  1. +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
  2. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  3. +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+

select_type
示查询中每个select子句的类型(简单OR复杂), 有PRIMARY,UNION
type
表示MySQL在表中找到所需行的方式,又称“访问类型”,ALL, index, range, ref, eq_ref, const, system, NULL
Extra
Using index(覆盖索引),Using where 等

简单说一下 S QL 调优思路。

简单说一下 S QL 调优思路。
1、SQL 语句及索引的优化
2、数据库表结构的优化
3、系统配置的优化
4、硬件的优化

优化数据库的方法

1、选取最适用的字段属性,尽可能减少定义字段宽度,尽量把字段设置 NOTNULL, 例如’ 省份’、’ 性别’ 最好适用 ENUM
2、使用连接(JOIN)来代替子查询
3、适用联合(UNION)来代替手动创建的临时表
4、事务处理
5、锁定表、优化事务处理
6、适用外键, 优化锁定表
7、建立索引
8、优化查询语句

简单说一下大表优化的思路

当MySQL单表记录数过⼤时,数据库的CRUD性能会明显下降,⼀些常⻅的优化措施如下:

限定数据的范围

务必禁⽌不带任何限制数据范围条件的查询语句。⽐如:我们当⽤户在查询订单历史的时候,我们可以控制在⼀个⽉的范围内;

读/写分离

经典的数据库拆分⽅案,主库负责写,从库负责读;

垂直分区

根据数据库⾥⾯数据表的相关性进⾏拆分。 简单来说垂直拆分是指数据表列的拆分,把⼀张列⽐较多的表拆分为多张表。

⽔平分区

就是将一张表的数据,分几张表分别存储

数据库分⽚的两种常⻅⽅案

  • 客户端代理: 分⽚逻辑在应⽤端,封装在jar包中,通过修改或者封装JDBC层来实现。 当当⽹的 Sharding-JDBC 、阿⾥的TDDL是两种⽐较常⽤的实现。
  • 中间件代理: 在应⽤和数据中间加了⼀个代理层。分⽚逻辑统⼀维护在中间件服务中。 我们现在谈的 Mycat 、 360的Atlas、⽹易的DDB等等都是这种架构的实现。

MySQL锁有哪些,如何理解

其中 InnoDB 支持表级锁和行级锁,MyISAM 只支持表级锁。
按锁粒度分类:
1. ⾏锁:锁某⾏数据,锁粒度最⼩,并发度⾼
2. 表锁:锁整张表,锁粒度最⼤,并发度低
3. 间隙锁:锁的是⼀个区间

Innodb是如何实现事务的

Innodb通过Buffer Pool,LogBuffer,Redo Log,Undo Log来实现事务,以⼀个update语句为例:
1. Innodb在收到⼀个update语句后,会先根据条件找到数据所在的⻚,并将该⻚缓存在Buffer Pool中
2. 执⾏update语句,修改Buffer Pool中的数据,也就是内存中的数据
3. 针对update语句⽣成⼀个RedoLog对象,并存⼊LogBuffer中
4. 针对update语句⽣成undolog⽇志,⽤于事务回滚
5. 如果事务提交,那么则把RedoLog对象进⾏持久化,后续还有其他机制将Buffer Pool中所修改的数据⻚持久化到磁盘中
6. 如果事务回滚,则利⽤undolog⽇志进⾏回滚

MVCC机制

定义

MVCC代表多版本并发控制
MVCC最大的优势:读不加锁,读写不冲突。读写不冲突是非常重要的,极大的增加了系统的并发性能。MVCC机制也是乐观锁的一种体现。

实现原理

MVCC的实现原理主要依赖于记录中的三个隐藏字段,undolog , read view 来实现的。

隐藏字段

每行记录除了我们自定义的子段外,还有数据库隐式定义的DB_TRX_ID , DB_ROLL_PTR , DB_ROW_ID等字段
DB_TRX_ID
6字节,最近修改事务ID,记录创建这条记录或者最后一次修改该记录的事务ID
DB_ROLL_PTR
7字节,回滚指针,指向这条记录的上一个版本,用于配合undo log
DB_ROW_ID
6字节,隐藏的主键,如果数据表没有主键,那么innodb会自动生成一个6字节的roe_id
记录如图所示:
image.png

undo log

undo log为回滚日志,表示在进行insert , update , delete 操作的饿时候产生的方便回滚的日志。
实质为一个记录版本的链表,存数据变化的记录内容。
image.png

read view

Read View是事务进行快照读操作的时候生产的读视图,在该事务执行快照的那一刻,会生成一个数据系统当前的快照,记录并维护系统归档前活跃事务的ID,事务的id值也是自增的。
三个全局属性:
trx_list:一个数值列表,用来维护read view生成时刻系统正活跃的事务ID
up_limit_id:记录trx_list列表中事务ID,最小的ID
low_limit_id:Read View生成时刻系统尚未分配的下一个事务ID

MySQL锁有哪些?如何理解

按锁粒度分类:
1、行锁: 锁某行数据,锁粒度最小,并发度高
2、表锁: 锁整张表,锁粒度大,并发度低
3、间隙锁:锁的是一个区间

还可以分为:
共享锁:也就是读锁,一个事务给某行数据加了读锁,其他事务也可以读,但是不能写
排他锁:也就是写锁,一个事务给某行数据加了写锁,其他事务不能读,也不能写

还可以分为:
1、乐观锁:并不会真正的锁某行记录,而是通过一个版本号来实现的
2、悲观锁:上面锁的行锁,表锁都是悲观锁