1 什么是MySQL
MySQL 是⼀种关系型数据库,在 Java 企业级开发中⾮常常⽤,因为 MySQL 是开源免费的,并 且⽅便扩展。阿⾥巴巴数据库系统也⼤量⽤到了
MySQL ,因此它的稳定性是有保障的。 MySQL 是开放源代码的,因此任何⼈都可以在 GPL(General Public License)
的许可下下载并根据个性 化的需要对其进⾏修改。 MySQL 的默认端⼝号是 3306 。
2 为什么要使用数据库

* 1. 因为MySQL数据库将数据保存在文件中,可以永久保存;
* 2. 使用SQL语句,查询方便效率高;
* 3. 使用MySQL数据库管理数据方便。
3 数据库三大范式

* 第一范式:每个列都不可以再拆分。
* 第二范式:在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分。
* 第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。
在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由。比如性能。事实上我们经常会为了性能而妥协数据库的设计。
4 mysql有关权限的表都有哪几个

* 1、user权限表:记录允许连接到服务器的用户帐号信息,里面的权限是全局级的。
* 2、db权限表:记录各个帐号在各个数据库上的操作权限。
* 3、table_priv权限表:记录数据表级的操作权限。
* 4、columns_priv权限表:记录数据列级的操作权限。
* 5、host权限表:配合db权限表对给定主机上数据库级操作权限作更细致的控制。这个权限表不受GRANT和REVOKE语句的影响。
5 MySQL的binlog有有几种录入格式
有三种格式: statement , row  和  mixed 。
* statement:每一条会修改数据的sql都会记录在binlog中。不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能。由于sql
的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制。
* row:不记录sql语句上下文相关信息,仅保存哪条记录被修改。记录单元为每一行的改动,基本是可以全部记下来,但是由于很多操作,会导致大量行的改动(比如
altertable),因此这种模式的文件保存的信息太多,日志量太大。
* mixed:一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row。
6 mysql有哪些数据类型

* 字符串类型:包括VARCHAR、CHAR、TEXT、BLOBVARCHAR用于存储可变长字符串,它比定长类型更节省空间。
* 整数类型:包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别表示1字节、2字节、3字节、4字节、8字节整数。
任何整数类型都可以加上UNSIGNED属性,表示数据是无符号的,即非负整数。
* 实数类型:包括FLOAT、DOUBLE、DECIMAL。DECIMAL可以用于存储比BIGINT还大的整型,能存储精确的小数。而FLOAT和DOUBLE
是有取值范围的,并支持使用标准的浮点进行近似计算。
* 枚举类型(ENUM):把不重复的数据存储为一个预定义的集合。
* 日期和时间类型:尽量使用timestamp,空间效率高于datetime,用整数保存时间戳通常不方便处理。
7 MySQL存储引擎

常用的存储引擎有以下:

* Innodb引擎:Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁和外键的约束。它的设计的目标就是处理大数据容量的数据库系统。
* MyIASM引擎(原本Mysql的默认引擎):不提供事务的支持,也不支持行级锁和外键。
* MEMORY引擎:所有的数据都在内存中,数据的处理速度快,但是安全性不高。 MyISAM 是 MySQL 的默认数据库引擎( 5.5
版之前)。虽然性能极佳,⽽且提供了⼤量的特性, 包括全⽂索引、压缩、空间函数等,但 MyISAM 不⽀持事务和⾏级锁,⽽且最⼤的缺陷就是崩溃
后⽆法安全恢复。不过, 5.5 版本之后, MySQL 引⼊了 InnoDB (事务性数据库引擎), MySQL 5.5 版本后默认的存储引擎为 InnoDB
。 MyISAM 与 InnoDB 区别 :
* 1. 存储结构:MyISAM 每张表被存放在三个文件:frm-表格定义、MYD(MYData)-数据文件、MYI(MYIndex)-索引文件;
⽽InnoDB所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。
* 2. 是否⽀持⾏级锁 : MyISAM 只有表级锁(table-level locking),⽽InnoDB ⽀持⾏级锁(row level
locking)、页级锁和表级锁,默认为⾏级锁。
* 3. 记录顺序:MyISAM 按记录插入顺序保存 ,InnoDB按主键大小有序插入。
* 4. 是否⽀持事务和崩溃后的安全恢复: MyISAM 强调的是性能,每次查询具有原⼦性,其执⾏ 速度⽐InnoDB类型更快,但是不提供事务⽀持。但是
InnoDB提供事务⽀持事务,外部键等⾼级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能⼒(crash recovery
capabilities)的事务安全(transaction-safe (ACID compliant))型表。
* 5. 是否⽀持外键: MyISAM不⽀持,⽽InnoDB⽀持。
* 6. 是否⽀持MVCC :仅 InnoDB ⽀持。应对⾼并发事务, MVCC⽐单纯的加锁更⾼效;MVCC只在 READ COMMITTED 和
REPEATABLE READ两个隔离级别下⼯作;MVCC可以使⽤乐观(optimistic)锁 和 悲观(pessimistic)锁来实现;各数据库中MVCC
实现并不统⼀。 MyISAM 索引与 InnoDB 索引的区别
* InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
* InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效。
* MyISAM索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据。
* InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效。
8 索引及其数据结构(Hash & B/B+树)
索引是一种特殊的文件 (InnoDB 数据表上的索引是表空间的一个组成部分 ),它们包含着对数据表里所有记录的引用指针。
索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新 数据库表中数据。索引的实现通常使用 B树及其变种B+ 树。
MySQL 索引使⽤的数据结构主要有 BTree 索引 和 哈希索引 。对于哈希索引来说,底层的数据结 构就是哈希表,因此在绝⼤多数需求为单条记录查询
的时候,可以选择哈希索引,查询性能最快;其余⼤部分场景,建议选择BTree 索引。 MySQL 的 BTree 索引使⽤的是 B 树中的 B+Tree
,但对于主要的两种存储引擎的实现⽅式是不同 的。
* MyISAM: B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候,⾸先按照B+Tree搜索算法搜索索引,如果指定的Key
存在,则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。这被称为“⾮聚簇索引”。
* InnoDB: 其数据⽂件本身就是索引⽂件。相比MyISAM,索引⽂件和数据⽂件是分离的,其表数据⽂件本身就是按B+Tree
组织的⼀个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据⽂件本身就是主索引。这被称为“
聚簇索引(或聚集索引)”。⽽其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值⽽不是地址,这也是和MyISAM不同的地⽅。
* 在根据主索引搜索时,直接找到key所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,再⾛⼀遍主索引。
因此,在设计表的时候,不建议使⽤过⻓的字段作为主键,也不建议使⽤⾮单调的字段作为主键,这样会造成主索引频繁分裂。
9 索引有哪几种类型

* 主键索引 : 数据列不允许重复,不允许为NULL,一个表只能有一个主键。
* 唯一索引 : 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。
* 普通索引 : 基本的索引类型,没有唯一性的限制,允许为NULL值。
* 全文索引 :是目前搜索引擎使用的一种关键技术。
10 索引的基本原理
索引的原理很简单,就是把无序的数据变成有序的查询
* 1. 把创建了索引的列的内容进行排序
* 2. 对排序结果生成倒排表
* 3. 在倒排表内容上拼上数据地址链
* 4. 在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据
11 索引设计的原则

* 1. 适合索引的列是出现在where子句中的列,或者连接子句中指定的列(较频繁作为查询条件的字段才去创建索引 )。
* 2. 基数较小的类,查询中很少涉及的列,重复值比较多的列,索引效果较差,没有必要在此列建立索引。
* 3. 使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间。
* 4. 
不要过度索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进行更新甚至重构,索引列越多,这个时间就会越长。所以只保持需要的索引有利于查询即可。
* 5 . 左前缀匹配原则,组合索引非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如
a=1andb=2andc>3andd=4如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d
的顺序可以任意调整。
* 6 . 更新频繁字段不适合创建索引。
* 7 . 若是不能有效区分数据的列不适合做索引列(如性别,男女未知,多也就三种,区分度实在太低)。
* 8 . 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
* 9 . 定义有外键的数据列一定要建立索引。
* 10 . 对于定义为 text、image 和 bit 的数据类型的列不要建立索引。
12 创建索引时需要注意什么

* 非空字段:应该指定列为NOTNULL,除非你想存储NULL。在mysql中,含有空值的列很难进行查
询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值;
* 取值离散大的字段:(变量各个取值之间的差异程度)的列放到联合索引的前面,可以通过count()
函数查看字段的差异值,返回值越大说明字段的唯一值越多字段的离散程度高;
* 索引字段越小越好:数据库的数据存储以页为单位一页存储的数据越多一次IO操作获取的数据越大效率越高。
13 事物的四⼤特性(ACID)
事务是逻辑上的⼀组操作,要么都执⾏,要么都不执⾏。

1. 原⼦性( Atomicity ): 事务是最⼩的执⾏单位,不允许分割。事务的原⼦性确保动作要么 全部完成,要么完全不起作⽤; 2. ⼀致性(
Consistency ): 执⾏事务前后,数据保持⼀致,多个事务对同⼀个数据读取的结 果是相同的; 3. 隔离性( Isolation ):
并发访问数据库时,⼀个⽤户的事务不被其他事务所⼲扰,各并发 事务之间数据库是独⽴的; 4. 持久性( Durability ):
⼀个事务被提交之后。它对数据库中数据的改变是持久的,即使数 据库发⽣故障也不应该对其有任何影响。
14 并发事务带来哪些问题 
在典型的应⽤程序中,多个事务并发运⾏,经常会操作相同的数据来完成各⾃的任务(多个⽤户 对同⼀数据进⾏操作)。并发虽然是必须的,但可能会导致以下的问题。
* 脏读(Dirty read):
当⼀个事务正在访问数据并且对数据进⾏了修改,⽽这种修改还没有提交到数据库中,这时另外⼀个事务也访问了这个数据,然后使⽤了这个数据。因为这个数据是还没有提交的数据,那么另外⼀个事务读到的这个数据是“
脏数据”,依据“脏数据”所做的操作可能是不正确的。
* 丢失修改(Lost to modify):
指在⼀个事务读取⼀个数据时,另外⼀个事务也访问了该数据,那么在第⼀个事务中修改了这个数据后,第⼆个事务也修改了这个数据。这样第⼀个事务内的修改结果就被丢失,因此称为丢失修改。
例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
* 不可重复读(Unrepeatableread):
指在⼀个事务内多次读同⼀数据。在这个事务还没有结束时,另⼀个事务也访问该数据。那么,在第⼀个事务中的两次读数据之间,由于第⼆个事务的修改导致第⼀个事务两次读取的数据可能不太⼀样。这就发⽣了在⼀个事务内两次读到的数据是不⼀样的情况,因此称为不可重复读。
* 幻读(Phantom read): 幻读与不可重复读类似。它发⽣在⼀个事务(T1)读取了⼏⾏数据,接着另⼀个并发事务(T2
)插⼊了⼀些数据时。在随后的查询中,第⼀个事务(T1)就会发现多了⼀些原本不存在的记录,就好像发⽣了幻觉⼀样,所以称为幻读。
不可重复读和幻读区别:
不可重复读的重点是修改⽐如多次读取⼀条记录发现其中某些列的值被修改,幻读的重点在于新 增或者删除⽐如多次读取⼀条记录发现记录增多或减少了。
15 事务隔离级别有哪些
SQL 标准定义了四个隔离级别:
* READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
* READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻⽌脏读,但 是幻读或不可重复读仍有可能发⽣。
* REPEATABLE-READ(可重复读): 对同⼀字段的多次读取结果都是⼀致的,除⾮数据是被 本身事务⾃⼰所修改,
可以阻⽌脏读和不可重复读,但幻读仍有可能发⽣。
* SERIALIZABLE(可串⾏化): 最⾼的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执⾏,这样事务之间就完全不可能产⽣⼲扰,也就是说,
该级别可以防⽌脏读、不可重复读以及幻读。 MySQL InnoDB 存储引擎的默认⽀持的隔离级别是 REPEATABLE-READ(可重读)。 Oracle 
默认采用的READ_COMMITTED(读已提交)。
16 分库分表之后 id 主键如何处理
因为要是分成多个表之后,每个表都是从 1 开始累加,这样是不对的,我们需要⼀个全局唯⼀的 id 来⽀持。 ⽣成全局 id 有下⾯这⼏种⽅式:
* UUID:不适合作为主键,因为太⻓了,并且⽆序不可读,查询效率低。比较适合⽤于⽣成唯⼀的名字的标示,⽐如⽂件的名字。
* 数据库⾃增 id:两台数据库分别设置不同步⻓,⽣成不重复ID的策略来实现⾼可⽤。这种⽅ 式⽣成的 id
有序,但是需要独⽴部署数据库实例,成本⾼,还会有性能瓶颈。
* 利⽤ redis ⽣成 id:性能比较好,灵活⽅便,不依赖于数据库。但是,引⼊了新的组件造成 系统更加复杂,可⽤性降低,编码更加复杂,增加了系统成本。
* Twitter的snowflake(雪花算法)算法 :雪花算法生成的主键主要由 4部分组成,1bit符号位、41bit时间戳位、10bit
工作进程位以及 12bit 序列号位。
* 美团的Leaf分布式ID⽣成系统 :Leaf 是美团开源的分布式ID⽣成器,能保证全局唯⼀性、
趋势递增、单调递增、信息安全,⾥⾯也提到了⼏种分布式⽅案的对⽐,但也需要依赖关系数据库、Zookeeper等中间件。
17 MySQL 锁机制
当数据库有并发事务的时候,可能会产生数据的不一致(丢失修改),这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制。
18 隔离级别与锁的关系

* 在 Read Uncommitted 级别下,读取数据不需要加共享锁,这样就不会跟被修改的数据上的排他锁冲突。
* 在 Read Committed 级别下,读操作需要加共享锁,但是在语句执行完以后释放共享锁。
* 在 Repeatable Read 级别下,读操作需要加共享锁,但是在事务提交之前并不释放共享锁,也就是必须等待事务执行完毕以后才释放共享锁。
* SERIALIZABLE 级别 是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。
19 按照粒度可以将锁分为

* 行级锁:行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减
少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和排他锁。 
* 特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度高。
* 表级锁:表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的
MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。
* 特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。
* 页级锁:页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级
冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。
* 特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。 
20 InnoDB存储引擎的锁的算法有三种

* Record lock:单个行记录上的锁
* Gap lock:间隙锁,锁定一个范围,不包括记录本身
* Next-key lock:record+gap 锁定一个范围,包含记录本身 相关知识点:
* 1. innodb对于行的查询使用next-key lock。
* 2. Next-locking keying为了解决Phantom Problem幻读问题。
* 3. 当查询的索引含有唯一属性时,将next-key lock降级为record key。
* 4. Gap锁设计的目的是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产生。
* 5. 有两种方式显式关闭gap锁: 将事务隔离级别设置为RC 或者 将参数innodb_locks_unsafe_for_binlog设置为1。
21 数据库的乐观锁和悲观锁
乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。
* 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。
* 实现方式:乐观锁一般会使用版本号机制或CAS算法实现。
* 适用场景:写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。
* 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。
* 实现方式:使用数据库中的锁机制。
* 适用场景:多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。
22 视图
为了提高复杂 SQL 语句的复用性和表操作的安全性, MySQL数据库管理系统提供了视图特性。
视图使开发者只关心感兴趣的某些特定数据和所负责的特定任务,只能看到视图中所定义的数据,而不是视图所引用表中的数据,从而提高了数据库中数据的安全性。 视图的特点:
* 视图的列可以来自不同的表,是表的抽象和在逻辑意义上建立的新关系。
* 视图是由基本表(实表)产生的表(虚表)。
* 视图的建立和删除不影响基本表。
* 对视图内容的更新(添加,删除和修改)直接影响基本表。
* 当视图来自多个基本表时,不允许添加和删除数据。视图的操作包括创建视图,查看视图,删除视图和修改视图。 视图的使用场景:
* 简化复杂的SQL操作。在编写查询后,可以方便的重用它而不必知道它的基本查询细节;使用表的组成部分而不是整个表。
* 保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限。
* 更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。 视图的优点:
* 查询简单化。视图能简化用户的操作。
* 数据安全性。视图使用户能以多种角度看待同一数据,能够对机密数据提供安全保护。
* 逻辑数据独立性。视图对重构数据库提供了一定程度的逻辑独立性。 视图的缺点:
* 性能。数据库必须把视图的查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所
定义,那么,即使是视图的一个简单查询,数据库也把它变成一个复杂的结合体,需要花费一定的时间。
* 修改限制。当用户试图修改视图的某些行时,数据库必须把它转化为对基本表的某些行的修改。事
实上,当从视图中插入或者删除时,情况也是这样。对于简单视图来说,这是很方便的,但是,对于比较复杂的视图,可能是不可修改的。这些视图有如下特征:
* 1. 有UNIQUE等集合操作符的视图。
* 2.有GROUP BY子句的视图。
* 3.有诸如AVG\SUM\MAX等聚合函数的视图。
* 4.使用DISTINCT关键字的视图。
* 5.连接表的视图(其中有些例外)。
23 触发器
触发器是用户定义在关系表上的一类由事件驱动的特殊的存储过程。触发器是指一段代码,当触发某个事件时,自动执行这些代码。 使用场景 :
* 可以通过数据库中的相关表实现级联更改。
* 实时监控某张表中的某个字段的更改而需要做出相应的处理。
* 例如可以生成某些业务的编号。
* 注意不要滥用,否则会造成数据库及应用程序的维护困难。 MySQL 中常见触发器:
* Before Insert
* After Insert
* Before Update
* After Update
* Before Delete
* After Delete
24 SQL语句主要分为哪几类

* 数据定义语言DDL(Data Ddefinition Language)CREATE,DROP,ALTER
主要为以上操作即对逻辑结构等有操作的,其中包括表结构,视图和索引。
* 数据查询语言DQL(Data Query Language)SELECT 这个较为好理解 即查询操作,以select关键字。各种简单查询,连接查询等
都属于DQL。
* 数据操纵语言DML(Data Manipulation Language)INSERT,UPDATE, DELETE 主要为以上操作
即对数据进行操作的,对应上面所说的查询操作 DQL与DML共同构建了多数初级程序员常用的增删改查操作。而查询是较为特殊的一种 被划分到DQL中。
* 数据控制功能DCL(Data Control Language)GRANT,REVOKE,COMMIT,ROLLBACK 主要为以上操作
即对数据库安全性完整性等有操作的,可以简单的理解为权限控制等。
25 超键、候选键、主键、外键

* 超键:在关系中能唯一标识元组的属性集称为关系模式的超键。
* 候选键:是小超键,即没有冗余元素的超键。
* 主键:数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。
* 外键:在一个表中存在的另一个表的主键称此表的外键。
26 SQL常见约束

* NOT NULL: 用于控制字段的内容一定不能为空(NULL)。
* UNIQUE: 控件字段内容不能重复,一个表允许有多个 Unique 约束。
* PRIMARY KEY: 也是用于控件字段内容不能重复,但它在一个表只允许出现一个。
* FOREIGN KEY: 用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。
* CHECK: 用于控制字段的值范围。
27 关联查询

* 交叉连接(CROSS JOIN):不加查询条件,会造成笛卡尔积。
* 内连接(INNER JOIN):分为等值连接、不等值连接、自连接。
* 外连接(LEFT JOIN/RIGHT JOIN):左外连接(以左表为主,先查询出左表,按照
ON后的关联条件匹配右表,没有匹配到的用NULL填充)、右外连接(以右表为主,先查询出右表,按照ON后的关联条件匹配左表,没有匹配到的用NULL填充)。
* 联合查询(UNION与UNION ALL):是把多个结果集集中在一起,UNION前的结果为基准,需要注意的是联合查询的列数要相等,相同的记录行会合并。
* 全连接(FULL JOIN):MySQL不支持全连接,可以使用LEFT JOIN + UNION + RIGHT JOIN联合使用。
28 子查询

* 条件:一条SQL语句的查询结果做为另一条查询语句的条件或查询结果
* 嵌套:多条SQL语句嵌套使用,内部的SQL查询语句称为子查询。 子查询的三种情况:
* 1. 子查询是单行单列的情况:结果集是一个值,父查询使用:=、 <、 > 等运算符。
* 2. 子查询是多行单列的情况:结果集类似于一个数组,父查询使用:in 运算符。
* 3. 子查询是多行多列的情况:结果集类似于一张虚拟表,不能用于where 条件,用于select子句中做为子表。
29 SQL的生命周期

* 1. 应用服务器与数据库服务器建立一个连接
* 2. 数据库进程拿到请求sql
* 3. 解析并生成执行计划,执行
* 4. 读取数据到内存并进行逻辑处理
* 5. 通过步骤一的连接,发送结果到客户端
* 6. 关掉连接,释放资源
30 大表数据查询,怎么优化

* 1. 优化shema(数据库对象的集合)、sql语句+索引。
* 2. 第二加缓存:memcached、redis。
* 3. 主从复制,读写分离。
* 4. 垂直拆分:根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统。
* 5. 水平切分:针对数据量大的表,这一步比较麻烦, 能考验技术水平,要选择一个合理的sharding key, 为了有好的查询效率,表结构也要改动,
做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表。
31 慢查询都怎么优化
慢查询的优化首先要搞明白慢的原因是什么。 是查询条件没有命中索引?是 load 了不需要的数据列?还是数据量太大?
* 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。
* 分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。
* 如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。
32 对于SQL语句优化方法

* 1 . 优化查询过程中的数据访问:重写SQL语句,让优化器可以以更优的方式执行查询。
* 2 . 优化长难的查询语句:将一个大的查询分为多个小的相同的查询。
* 3 . 优化特定类型的查询语句:可以使用explain查询近似值,用近似值替代count(*) 增加汇总表使用缓存。
* 4 . 优化关联查询:确定ON或者USING子句中是否有索引。确保GROUP BY和ORDER BY只有一个表中的列,这样MySQL才有可能使用索引。
* 5 . 优化子查询:用关联查询替代GROUP BY和DISTINCT这两种查询,可以使用索引来优化。
* 6 . 优化LIMIT分页:LIMIT偏移量大的时候,可以记录上次查询的大ID,下次直接俄使用。
* 7 . 优化UNION查询:UNION ALL的效率高于UNION。
* 8 . 优化WHERE子句 :where字句中最好不要 对字段进行 null 值判断、使用!=或<>操作符、中使用or
来连接条件、使用like操作符、使用参数、对字段进行表达式操作,否则都会导致引擎放弃使用索引而进行全表扫描。
33 MySQL的复制原理以及流程 

* 第一步:master在每个事务更新数据完成之前,将该操作记录串行地写入到 binlog文件中。
* 第二步:salve开启一个I/O Thread,该线程在master打开一个普通连接,主要工作是binlog dump process
。如果读取的进度已经跟上了master,就进入睡眠状态并等待master产生新的事件。I/O线程最终的目的是将这些事件写入到中继日志中。
* 第三步:SQL Thread会读取中继日志,并顺序执行该日志中的SQL事件,从而与主数据库中的数据保持一致。
34 读写分离有哪些解决方案 

* 方案一 :使用mysql-proxy代理
* 优点:直接实现读写分离和负载均衡,不用修改代码,master和slave用一样的帐号,mysql官方不建议实际生产中使用。
* 缺点:降低性能, 不支持事务。
* 方案二 :使用AbstractRoutingDataSource+aop+annotation在dao层决定数据源
* 优点:读写分离放在ORM层,通过注解或者分析语句是读写方法来选定主从库。
* 缺点:不支持事务。
* 方案三:使用AbstractRoutingDataSource+aop+annotation在service层决定数据源
* 优点:可以支持事务。
* 缺点:类内部方法通过this.xx()方式相互调用时,aop不会进行拦截,需进行特殊处理。
35 MySQL锁:悲观锁、乐观锁、排它锁、共享锁、表级锁、行级锁、页级锁、死锁

* 乐观锁 :用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的
“version”字段来实现。读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加1
。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比 对,如果数据库表当前版本号与第一次取出来的version
值相等,则予以更新,否则认为是过期数据。
* 悲观锁:在进行每次操作时都要通过获取锁才能进行对相同数据的操作,这点跟java synchronized很相似,共
享锁(读锁)和排它锁(写锁)是悲观锁的不同的实现。
* 共享锁(读锁):共享锁又叫做读锁,所有的事务只能对其进行读操作不能写操作,加上共享锁后在事务结束之前其他事
务只能再加共享锁,除此之外其他任何类型的锁都不能再加了。
* 排它锁(写锁):若某个事物对某一行加上了排他锁,只能这个事务对其进行读写,在此事务结束之前,其他事务不能对其进行加任何锁,其他进程可以读取,
不能进行写操作,需等待其释放。
* 表级锁:innodb 的行锁是在有索引的情况下,没有索引的表是锁定全表的 。
* 行级锁 :行锁又分共享锁和排他锁,由字面意思理解,就是给某一行加上锁,也就是一条记录加上锁。 注意:行级锁都是基于索引的,如果一条SQL
语句用不到索引是不会使用行级锁的,会使用表级锁。
* 页级锁:页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。
* 死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
36 死锁的产生、条件、如何避免死锁
产生死锁的原因主要是:
* 1 .  因为系统资源不足。
* 2 .  进程运行推进的顺序不合适。
* 3 .  资源分配不当等。

  产生死锁的四个必要条件:
* 1  . 互斥条件:一个资源每次只能被一个进程使用。
* 2 . 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
* 3 . 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
* 4 . 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。 如何避免线程死锁:
* 1. 破坏互斥条件 :这个条件我们没有办法破坏,因为我们⽤锁本来就是想让他们互斥的(临界资源需要互斥访问)。
* 2. 破坏请求与保持条件 :⼀次性申请所有的资源。
* 3. 破坏不剥夺条件 :占⽤部分资源的线程进⼀步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
* 4. 破坏循环等待条件 :靠按序申请资源来预防。按某⼀顺序申请资源,释放资源则反序释放。
37 Spring事务管理
Spring 并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给 Hibernate
或者JTA等持久化机制所提供的相关平台框架的事务来实现。 Spring
事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,
Spring 为各个平台如 JDBC 、 Hibernate 等都提供了对应的事务管理器,但是具体的实现就是各 个平台自己的事情。
38 SQL的整个解析、执行过程原理
整体架构:

SQL解析

39 为什么mysql提供了锁
防止更新丢失,更新丢失并不能单靠数据库事务控制器来解决,需要应用程序对要更新的数据加必要的锁 来解决。
* 第一类丢失更新:A事务撤销时,把已提交的B事务的数据覆盖掉。
* 第二类丢失更新:A事务提交时,把已提交的B事务的数据覆盖掉。 三级封锁协议:
* 1. 一级封锁协议:事务T中如果对数据R有写操作,必须在这个事务中对R的第一次读操作前对它加排他锁
,直到事务结束才释放。事务结束包括正常结束(COMMIT)和非正常结束(ROLLBACK)。
* 2. 二级封锁协议:一级封锁协议加上事务T在读取数据R之前必须先对其加共享锁,读完后方可释放共享锁。
* 3. 三级封锁协议 :一级封锁协议加上事务T在读取数据R之前必须先对其加共享锁,直到事务结束才释放。
 

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信