MySQL数据库

# MySQL数据库

[第1章 存储引擎](#no1) 

[第2章 索引](#no2) 

[第3章 存储过程与函数](#no3) 

[第4章 事务控制和锁定语句](#no4) 

[第5章 MySQL分区](#no5)  

[第6章 SQL优化](#no6) 

[第7章 锁](#no7) 

[第8章 MySQL体系结构](#no8) 

[第9章 备份还原](#no9)   

---

 
## 第1章 存储引擎  
#### 1.1 MySQL存储引擎概述  

插件式存储引擎是MySQL数据库最重要的特性之一,用户可以根据应用的需要选择如何存储和索引数据、是否使用事务等。MySQL默认支持多种存储引擎,以适用于不同领域的数据库应用需要,用户可以通过选择使用不同的存储引擎提高应用的效率,提供灵活的存储,用户甚至可以按照自己的需要定制和使用自己的存储引擎,以实现最大程度的可定制性。  

MySQL 5.0支持的存储引擎包括MyISAM、InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDB Cluster、ARCHIVE、CSV、BLACKHOLE、FEDERATED等,其中 InnoDB和BDB提供事务安全表,其他存储引擎都是非事务安全表。  

创建新表时如果不指定存储引擎,那么系统就会使用默认存储引擎,MySQL 5.5之前的默认存储引擎是MyISAM,5.5之后改为了InnoDB。如果要修改默认的存储引擎,可以在参数文件中设置default-table-type。  

查看当前的默认存储引擎,可以使用以下命令:  
```
show variables like 'table_type';
```
可以通过下面两种方法查询当前数据库支持的存储引擎,第一种方法为:  

```
SHOW ENGINES \G
```
第二种方法为:
```
SHOW VARIABLES LIKE 'have%';
```
#### 1.2 各种存储引擎的特性  
![image](https://note.youdao.com/yws/api/personal/file/WEBaee410b28a9ad150488870d52c24a911?method=download&shareKey=38e6d76cec2056103b523b6e87ac060a)

##### 1.2.1 MyISAM  

MyISAM是MySQL默认的存储引擎。MyISAM不支持事务、也不支持外键,其优势是访问的速度快,对事务完整性没有要求或者以 SELECT、INSERT 为主的应用基本上都可以使用这个引擎来创建表。  

每个MyISAM在磁盘上存储成3个文件,其文件名都和表名相同,但扩展名分别是:  

.frm(存储表定义);  
.MYD(MYData,存储数据);  
.MYI(MYIndex,存储索引)。  

数据文件和索引文件可以放置在不同的目录,平均分布IO,获得更快的速度。  

要指定索引文件和数据文件的路径,需要在创建表的时候通过 DATA DIRECTORY 和INDEX DIRECTORY语句指定,也就是说不同MyISAM表的索引文件和数据文件可以放置到不同的路径下。文件路径需要是绝对路径,并且具有访问权限。  

MyISAM的表还支持3种不同的存储格式,分别是:
静态(固定长度)表;
动态表;
压缩表。

##### 1.2.2 InnoDB  

nnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比MyISAM的存储引擎,InnoDB写的处理效率差一些,并且会占用更多的磁盘空间以保留数据和索引。  
InnoDB的表在使用过程中不同于使用其他存储引擎的表的特点。    

1.自动增长列  
InnoDB 表的自动增长列可以手工插入,但是插入的值如果是空或者 0,则实际插入的将是自动增长后的值。  

2.外键约束  
MySQL支持外键的存储引擎只有InnoDB,在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引。  

3.存储方式  
InnoDB存储表和索引有以下两种方式。  

##### 1.2.3 MEMORY   

MEMORY存储引擎使用存在于内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件,格式是.frm。MEMORY类型的表访问非常地快,因为它的数据是放在内存中的,并且默认使用HASH索引,但是一旦服务关闭,表中的数据就会丢失掉。  

##### 1.2.4 MERGE  

MERGE存储引擎是一组MyISAM表的组合,这些MyISAM表必须结构完全相同,MERGE表本身并没有数据,对MERGE类型的表可以进行查询、更新、删除操作,这些操作实际上是对内部的MyISAM表进行的。对于MERGE类型表的插入操作,是通过INSERT_METHOD子句定义插入的表,可以有3个不同的值,使用FIRST或LAST值使得插入操作被相应地作用在第一或最后一个表上,不定义这个子句或者定义为NO,表示不能对这个MERGE表执行插入操作。  

可以对MERGE表进行DROP操作,这个操作只是删除MERGE的定义,部的表没有任何的影响。  

MERGE表在磁盘上保留两个文件,文件名以表的名字开始,一个.frm文件存储表定义,另一个.MRG文件包含组合表的信息,包括MERGE表由哪些表组成、插入新的数据时的依据。可以通过修改.MRG文件来修改MERGE表,但是修改后要通过FLUSH TABLES刷新。  

##### 1.2.5 TokuDB  

第三方存储引擎。  

TokuDB是一个高性能、支持事务处理的MySQL和MariaDB的存储引擎,具有高扩展性、高压缩率、高效的写入性能,支持大多数在线DDL操作。

#### 1.3 如何选择合适的存储引擎  

下面是几种常用存储引擎的适用环境。  

MyISAM:  
默认的MySQL插件式存储引擎。如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎是非常适合的。MyISAM是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。  

InnoDB:  
用于事务处理应用程序,支持外键。如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询以外,还包括很多的更新、删除操作,那么InnoDB存储引擎应该是比较合适的选择。InnoDB存储引擎除了有效地降低由于删除和更新导致的锁定,还可以确保事务的完整提交(Commit)和回滚(Rollback),对于类似计费系统或者财务系统等对数据准确性要求比较高的系统,InnoDB都是合适的选择。  

MEMORY:  
将所有数据保存在 RAM 中,在需要快速定位记录和其他类似数据的环境下,可提供极快的访问。MEMORY 的缺陷是对表的大小有限制,太大的表无法缓存在内存中,其次是要确保表的数据可以恢复,数据库异常终止后表中的数据是可以恢复的。MEMORY表通常用于更新不太频繁的小表,用以快速得到访问结果。  

MERGE:  
用于将一系列等同的MyISAM表以逻辑方式组合在一起,并作为一个对象引用它们。MERGE表的优点在于可以突破对单个MyISAM表大小的限制,并且通过将不同的表分布在多个磁盘上,可以有效地改善MERGE表的访问效率。这对于诸如数据仓储等VLDB环境十分适合。  

 
## 第2章 索引    

MyISAM和InnoDB存储引擎的表默认创建的都是BTREE索引。  

MySQL 中还支持全文本(FULLTEXT)索引,该索引可以用于全文搜索。  

也可以为空间列类型创建索引,但是只有 MyISAM 存储引擎支持空间类型索引,且索引的字段必须是非空的。  

默认情况下,MEMORY存储引擎使用HASH索引,但也支持BTREE索引。  

```
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
[USING index_type]
ON tbl_name (index_col_name,. .)
index_col_name:
col_name [(length)] [ASC | DESC]
```
#### 2.1 设计索引的原则  

搜索的索引列,不一定是所要选择的列。换句话说,最适合索引的列是出现在WHERE子句中的列,或连接子句中指定的列,而不是出现在SELECT关键字后的选择列表中的列。  

使用唯一索引。考虑某列中值的分布。索引的列的基数越大,索引的效果越好。  

使用短索引。如果对字符串列进行索引,应该指定一个前缀长度,只要有可能就应该这样做。  

利用最左前缀。在创建一个n列的索引时,实际是创建了MySQL可利用的n个索引。多列索引可起几个索引的作用,因为可利用索引中最左边的列集来匹配行。这样的列集称为最左前缀。  

不要过度索引。  

对于InnoDB存储引擎的表,记录默认会按照一定的顺序保存,如果有明确定义的主键,则按照主键顺序保存。如果没有主键,但是有唯一索引,那么就是按照唯一索引的顺序保存。如果既没有主键又没有唯一索引,那么表中会自动生成一个内部列,按照这个列的顺序保存。按照主键或者内部列进行的访问是最快的,所以InnoDB表尽量自己指定主键,当表中同时有几个列都是唯一的,都可以作为主键的时候,要选择最常作为访问条件的列作为主键,提高查询的效率。另外,还需要注意,InnoDB 表的普通索引都会保存主键的键值,所以主键要尽可能选择较短的数据类型,可以有效地减少索引的磁盘占用,提高索引的缓存效果。  

#### 2.2 BTREE索引与HASH索引   

MEMORY存储引擎的表可以选择使用BTREE索引或者HASH索引,两种不同类型的索引各有其不同的适用范围。HASH索引有一些重要的特征需要在使用的时候特别注意,如下所示。  

只用于使用=或<=>操作符的等式比较。  

优化器不能使用HASH索引来加速ORDER BY操作。
MySQL 不能确定在两个值之间大约有多少行。如果将一个 MyISAM 表改为 HASH索引的MEMORY表,会影响一些查询的执行效率。  

只能使用整个关键字来搜索一行。  

而对于BTREE索引,当使用>、<、>=、<=、BETWEEN、!=或者<>,或者LIKE 'pattern' (其中'pattern'不以通配符开始)操作符时,都可以使用相关列上的索引。

 
## 第3章 存储过程与函数  

存储过程和函数是事先经过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。  

存储过程和函数的区别在于函数必须有返回值,而存储过程没有,存储过程的参数可以使用IN、OUT、INOUT类型,而函数的参数只能是IN类型的。如果有函数从其他类型的数据库迁移到MySQL,那么就可能因此需要将函数改造成存储过程。

#### 1. 创建、修改存储过程或者函数  


```
CREATE PROCEDURE sp_name ([proc_parameter[,. .]])
[characteristic . .] routine_body
CREATE FUNCTION sp_name ([func_parameter[,. .]])
RETURNS type
[characteristic . .] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'
routine_body:
Valid SQL procedure statement or statements
ALTER {PROCEDURE | FUNCTION} sp_name [characteristic . .]
characteristic:
{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'
```
调用过程的语法如下:
```
CALL sp_name([parameter[,. .]])
```

 
## 第4章 事务控制和锁定语句  

MySQL支持对MyISAM和MEMORY存储引擎的表进行表级锁定,对BDB存储引擎的表进行页级锁定,对InnoDB存储引擎的表进行行级锁定。默认情况下,表锁和行锁都是自动获得的,不需要额外的命令。但是在有的情况下,用户需要明确地进行锁表或者进行事务的控制,以便确保整个事务的完整性,这样就需要使用事务控制和锁定语句来完成。  

#### 4.1 LOCK TABLE和UNLOCK TABLE  

LOCK TABLES可以锁定用于当前线程的表。如果表被其他线程锁定,则当前线程会等待,直到可以获取所有锁定为止。  

UNLOCK TABLES 可以释放当前线程获得的任何锁定。当前线程执行另一个 LOCK TABLES时,或当与服务器的连接被关闭时,所有由当前线程锁定的表被隐含地解锁,具体语法如下:  
```
LOCK TABLES
tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] . .
UNLOCK TABLES
```  
#### 4.2 事务控制  

MySQL通过SET AUTOCOMMIT、START TRANSACTION、COMMIT和ROLLBACK等语句支持本地事务,具体语法如下。

```
START TRANSACTION | BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT = {0 | 1}
```
默认情况下,MySQL 是自动提交(Autocommit)的,如果需要通过明确的 Commit 和Rollback来提交和回滚事务,那么就需要通过明确的事务控制命令来开始事务,这是和Oracle的事务管理明显不同的地方。如果应用是从Oracle数据库迁移到MySQL数据库,则需要确保应用中是否对事务进行了明确的管理。  

START TRANSACTION或BEGIN语句可以开始一项新的事务。  

COMMIT和ROLLBACK用来提交或者回滚事务。  

CHAIN和RELEASE子句分别用来定义在事务提交或者回滚之后的操作,CHAIN会立即启动一个新事物,并且和刚才的事务具有相同的隔离级别,RELEASE 则会断开和客户端的连接。  

SET AUTOCOMMIT 可以修改当前连接的提交方式,如果设置了 SET AUTOC-OMMIT=0,则设置之后的所有事务都需要通过明确的命令进行提交或者回滚。

如果只是对某些语句需要进行事务控制,则使用START TRANSACTION语句开始一个事务比较方便,这样事务结束之后可以自动回到自动提交的方式,如果希望所有的事务都不是自动提交的,那么通过修改 AUTOCOMMIT 来控制事务比较方便,这样不用在每个事务开始的时候再执行START TRANSACTION语句。

#### 4.3 分布式事务的使用  
MySQL从5.0.3开始支持分布式事务,当前分布式事务只支持InnoDB存储引擎。一个分布式事务会涉及多个行动,这些行动本身是事务性的。所有行动都必须一起成功完成,或者一起被回滚。  

##### 4.3.1 分布式事务的原理  

在MySQL中,使用分布式事务的应用程序涉及一个或多个资源管理器和一个事务管理器。  

资源管理器(RM)用于提供通向事务资源的途径。数据库服务器是一种资源管理器。该管理器必须可以提交或回滚由RM管理的事务。例如,多台MySQL数据库作为多台资源管理器或者几台MySQL服务器和几台Oracle服务器作为资源管理器。  

事务管理器(TM)用于协调作为一个分布式事务一部分的事务。TM 与管理每个事务的RMs进行通信。在一个分布式事务中,各个单个事务均是分布式事务的“分支事务”。分布式事务和各分支通过一种命名方法进行标识。  

用于执行分布式事务的过程使用两阶段提交,发生时间在由分布式事务的各个分支需要进行的行动已经被执行之后。  

在第一阶段,所有的分支被预备好。即它们被TM告知要准备提交。通常,这意味着用于管理分支的每个RM会记录对于被稳定保存的分支的行动。分支指示是否它们可以这么做。这些结果被用于第二阶段。  
 
在第二阶段,TM 告知 RMs 是否要提交或回滚。如果在预备分支时,所有的分支指示它们将能够提交,则所有的分支被告知要提交。如果在预备时,有任何分支指示它将不能提交,则所有分支被告知回滚。  

##### 4.3.2 分布式事务的语法  

分布式事务(XA事务)的SQL语法主要包括:  

XA {START|BEGIN} xid [JOIN|RESUME]  

XA START xid用于启动一个带给定 xid值的XA事务。每个XA事务必须有一个唯一的xid值,因此该值当前不能被其他的XA事务使用。xid是一个XA事务标识符,用来唯一标识一个分布式事务。xid值由客户端提供,或由MySQL服务器生成。xid值包含1~3个部分:  

xid: gtrid [, bqual [, formatID ]]
gtrid 是一个分布式事务标识符,相同的分布式事务应该使用相同的 gtrid,这样可以明确知道XA事务属于哪个分布式事务。  

bqual 是一个分支限定符,默认值是空串。对于一个分布式事务中的每个分支事务,bqual值必须是唯一的。  

formatID是一个数字,用于标识由gtrid和bqual值使用的格式,默认值是1。  

下面其他XA语法中用到的xid值都必须和START操作使用的xid值相同,也就是表示对这个启动的XA事务进行操作。  

XA END xid [SUSPEND [FOR MIGRATE]]  

XA PREPARE xid
使事务进入PREPARE 状态,也就是两阶段提交的第一个提交阶段。  

XA COMMIT xid [ONE PHASE]
XA ROLLBACK xid
这两个命令用来提交或者回滚具体的分支事务。也就是两阶段提交的第二个提交阶段,分支事务被实际地提交或者回滚。  

XA RECOVER
XA RECOVER返回当前数据库中处于PREPARE状态的分支事务的详细信息。  

 
## 第5章 MySQL分区    

MySQL分区的优点主要包括以下4个方面。  

和单个磁盘或者文件系统分区相比,可以存储更多数据。  

优化查询。在 Where 子句中包含分区条件时,可以只扫描必要的一个或多个分区来提高查询效率;同时在涉及 SUM()和 COUNT()这类聚合函数的查询时,可以容易地在每个分区上并行处理,最终只需要汇总所有分区得到的结果。  

对于已经过期或者不需要保存的数据,可以通过删除与这些数据有关的分区来快速删除数据。  

跨多个磁盘来分散数据查询,以获得更大的查询吞吐量。  

#### 5.1 分区概述  

分区有利于管理非常大的表,它采用了“分而治之”的逻辑,分区引入了分区键(partition key)的概念,分区键用于根据某个区间值(或者范围值)、特定值列表或者HASH函数值执行数据的聚集,让数据根据规则分布在不同的分区中,让一个大对象变成一些小对象。  

可以通过使用SHOW VARIABLES命令来确定当前的MySQL是否支持分区。  

#### 5.2 分区类型  

RANGE分区:基于一个给定连续区间范围,把数据分配到不同的分区。  

```
按照RANGE分区的表是利用取值范围将数据分成分区,区间要连续并且不能互相重叠,使用VALUES LESS THAN操作符进行分区定义。
```


LIST分区:类似RANGE分区,区别在LIST分区是基于枚举出的值列表分区,RANGE是基于给定的连续区间范围分区。   

```
LIST分区是建立离散的值列表告诉数据库特定的值属于哪个分区,LIST分区在很多方面类似于RANGE分区,
区别在LIST分区是从属于一个枚举列表的值的集合,RANGE分区是从属于一个连续区间值的集合。

LIST分区通过使用PARTITION BY LIST(expr)子句来实现,expr是某列值或一个基于某列值返回一个整数值的表达式,
然后通过VALUES IN(value_list)的方式来定义分区,其中value_list是一个逗号分隔的整数列表。
```
Columns 分区:
lumns分区是在MySQL 5.5引入的分区类型,引入Columns分区解决了MySQL 5.5版本之前RANGE分区和LIST分区只支持整数分区,从而导致需要额外的函数计算得到整数或者通过额外的转换表来转换为整数再分区的问题。  

```
Columns分区可以细分为RANGE Columns分区和LIST Columns分区,RANGE Columns分区和LIST Columns分区都支持整数、日期时间、字符串三大数据类型。  

所有整数类型:tinyint、smallint、mediumint、int和bigint;其他数值类型都不支持。  

对比RANGE分区和LIST分区,Columns分区的亮点除了支持数据类型增加之外,另外一大亮点是 Columns 分区还支持多列分区。  
```

HASH分区:基于给定的分区个数,把数据分配到不同的分区。   

```
HASH分区主要用来分散热点读,确保数据在预先确定个数的分区中尽可能平均分布。  
对一个表执行HASH分区时,MySQL会对分区键应用一个散列函数,以此确定数据应当放在N个分区中的哪个分区中。

MySQL支持两种HASH分区,常规HASH分区和线性HASH分区(LINEAR HASH分区);
常规HASH使用的是取模算法,线性HASH分区使用的是一个线性的2的幂的运算法则。
```
KEY分区:类似于HASH分区。  

```
按照Key进行分区非常类似于按照HASH进行分区,只不过HASH分区允许使用用户自定义的表达式,
而Key分区不允许使用用户自定义的表达式,需要使用MySQL服务器提供的HASH函数;
同时HASH分区只支持整数分区,而Key分区支持使用除BLOB or Text类型外其他类型的列作为分区键。
```
#### 5.3 子分区  
子分区(subpartitioning)是分区表中对每个分区的再次分割,又被称为复合分区(composite partitioning)。

 
## 第6章 SQL优化  

#### 6.1 优化SQL语句的一般步骤  

##### 6.1.1 通过show status命令了解各种SQL的执行频率  

MySQL客户端连接成功后,通过 show [session|global]status命令可以提供服务器状态信息,也可以在操作系统上使用mysqladmin extended-status命令获得这些消息。show [session|global] status可以根据需要加上参数“session”或者“global”来显示session级(当前连接)的统计结果和global级(自数据库上次启动至今)的统计结果。如果不写,默认使用的参数是“session”。  

##### 6.1.2 定位执行效率较低的SQL语句  
可以通过以下两种方式定位执行效率较低的SQL语句。  
通过慢查询日志定位那些执行效率较低的SQL语句,用--log-slow-queries[= file_name]选项启动时,mysqld写一个包含所有执行时间超过long_query_time秒的SQL语句的日志文件。  

慢查询日志在查询结束以后才记录,所以在应用反映执行效率出现问题的时候查询慢查询日志并不能定位问题,可以使用 show processlist命令查看当前MySQL在进行的线程,包括线程的状态、是否锁表等,可以实时地查看 SQL 的执行情况,同时对一些锁表操作进行优化 。  

##### 6.1.3 通过EXPLAIN分析低效SQL的执行计划  

##### 6.1.4 通过show profile分析SQL  

##### 6.1.5 通过 trace分析优化器如何选择执行计划  
使用方式:首先打开trace,设置格式为JSON,设置 trace最大能够使用的内存大小,避免解析过程中因为默认内存过小而不能够完整显示。  

#### 6.2 索引存储分类   

索引是在MySQL的存储引擎层中实现的,而不是在服务器层实现的。所以每种存储引擎的索引都不一定完全相同,也不是所有的存储引擎都支持所有的索引类型。MySQL 目前提供了以下4种索引。  

B-Tree索引:最常见的索引类型,大部分引擎都支持B树索引。  

HASH索引:只有Memory引擎支持,使用场景简单。  

R-Tree索引(空间索引):空间索引是MyISAM的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少,不做特别介绍。  

Full-text(全文索引):全文索引也是 MyISAM 的一个特殊索引类型,主要用于全文索引,InnoDB从MySQL 5.6版本开始提供对全文索引的支持。  

MyISAM、InnoDB、Memory三个常用引擎支持的索引类型比较:  

![image](https://note.youdao.com/yws/api/personal/file/WEBeb2bcb3c3ca7fea74e4fd39aea56c607?method=download&shareKey=c508b3a639eb47abf1d00815183d0aee)  

#### 6.3 常用SQL的优化  

##### 6.3.1 大批量插入数据  

当用load命令导入数据的时候,适当的设置可以提高导入的速度。  

对于MyISAM存储引擎的表,可以通过以下方式快速地导入大量的数据。  

```
ALTER TABLE tbl_name DISABLE KEYS;
loading the data
ALTER TABLE tbl_name ENABLE KEYS;  

DISABLE KEYS和ENABLE KEYS用来打开或者关闭MyISAM表非唯一索引的更新。
在导入大量的数据到一个非空的 MyISAM 表时,通过设置这两个命令,可以提高导入的效率。对于导入大量数据到一个空的 MyISAM 表,
默认就是先导入数据然后才创建索引的,所以不用进行设置。
```  

可以有以下几种方式提高InnoDB表的导入效率:

(1)因为InnoDB类型的表是按照主键的顺序保存的,所以将导入的数据按照主键的顺序排列,可以有效地提高导入数据的效率。  

2)在导入数据前执行SET UNIQUE_CHECKS=0,关闭唯一性校验,在导入结束后执行SET UNIQUE_CHECKS=1,恢复唯一性校验,可以提高导入的效率。  

(3)如果应用使用自动提交的方式,建议在导入前执行SET AUTOCOMMIT=0,关闭自动提交,导入结束后再执行SET AUTOCOMMIT=1,打开自动提交,也可以提高导入的效率。  

##### 6.3.2 优化 INSERT语句  

如果同时从同一客户插入很多行,应尽量使用多个值表的INSERT语句,这种方式将大大缩减客户端与数据库之间的连接、关闭等消耗,使得效率比分开执行的单个INSERT语句快(在大部分情况下,使用多个值表的 INSERT 语句能比单个 INSERT 语句快上好几倍)。   

如果从不同客户插入很多行,可以通过使用 INSERT DELAYED语句得到更高的速度。DELAYED的含义是让INSERT语句马上执行,其实数据都被放在内存的队列中,并没有真正写入磁盘,这比每条语句分别插入要快得多;LOW_PRIORITY 刚好相反,在所有其他用户对表的读写完成后才进行插入。  

将索引文件和数据文件分在不同的磁盘上存放(利用建表中的选项)。  

如果进行批量插入,可以通过增加bulk_insert_buffer_size变量值的方法来提高速度,但是,这只能对MyISAM表使用。  

当从一个文本文件装载一个表时,使用 LOAD DATA INFILE。这通常比使用很多INSERT语句快20倍。  

##### 6.3.3 优化ORDER BY语句

1.MySQL中有两种排序方式  

第一种通过有序索引顺序扫描直接返回有序数据,这种方式在使用 explain 分析查询的时候显示为Using Index,不需要额外的排序,操作效率较高。  

第二种是通过对返回数据进行排序,也就是通常说的 Filesort 排序,所有不是通过索引直接返回排序结果的排序都叫Filesort排序。Filesort并不代表通过磁盘文件进行排序,而只是说明进行了一个排序操作,至于排序操作是否使用了磁盘文件或临时表等,则取决于MySQL服务器对排序参数的设置和需要排序数据的大小。  
2.Filesort的优化  

对于Filesort,MySQL有两种排序算法。  

两次扫描算法(Two Passes):首先根据条件取出排序字段和行指针信息,之后在排序区 sort buffer中排序。如果排序区 sort buffer不够,则在临时表Temporary Table中存储排序结果。完成排序后根据行指针回表读取记录。该算法是MySQL 4.1之前采用的算法,需要两次访问数据,第一次获取排序字段和行指针信息,第二次根据行指针获取记录,尤其是第二次读取操作可能导致大量随机I/O操作;优点是排序的时候内存开销较少。  

一次扫描算法(Single Pass):一次性取出满足条件的行的所有字段,然后在排序区sort buffer中排序后直接输出结果集。排序的时候内存开销比较大,但是排序效率比两次扫描算法要高。

##### 6.3.4 优化GROUP BY语句  

默认情况下,MySQL对所有GROUP BY col1,col2,…的字段进行排序。  

如果查询包括GROUP BY但用户想要避免排序结果的消耗,则可以指定ORDER BY NULL禁止排序。  

##### 6.3.5 优化嵌套查询  

连接(JOIN)之所以更有效率一些,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作。  

##### 6.3.6 MySQL如何优化OR条件  

对于含有OR的查询子句,如果要利用索引,则OR之间的每个条件列都必须用到索引;如果没有索引,则应该考虑增加索引。  

##### 6.3.7 优化分页查询  
1.第一种优化思路  

在索引上完成排序分页的操作,最后根据主键关联回原表查询所需要的其他列内容。  

2.第二种优化思路
把LIMIIT查询转换成某个位置的查询  


 
## 第7章 锁  

MySQL这3种锁的特性可大致归纳如下。  

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。  

行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。  

页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。  

#### 7.1 MyISAM表锁  

MyISAM存储引擎只支持表锁,这也是MySQL开始几个版本中唯一支持的锁类型。  

MySQL的表级锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。  
![image](https://note.youdao.com/yws/api/personal/file/WEB75ddc50ff071f870b872aeadc01d4f22?method=download&shareKey=cd3dc9c87becd223947a5b3403ef3b4d)  

##### 7.2 并发插入(Concurrent Inserts)  

MyISAM 存储引擎有一个系统变量 concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1或2。  

当concurrent_insert设置为0时,不允许并发插入。  

当concurrent_insert设置为1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置。  

当concurrent_insert设置为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。  

##### 7.3 InnoDB锁
InnoDB 与 MyISAM 的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁。  

InnoDB实现了以下两种类型的行锁。  

共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。  

排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。  

另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB 还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。  

意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。  

意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。  ![image](https://note.youdao.com/yws/api/personal/file/WEBab73cafbd9adc65c4e31a88d60f37806?method=download&shareKey=290a2c3c730d19f7c6f00acfdd207637)  

##### 7.4 InnoDB行锁实现方式

InnoDB行锁是通过给索引上的索引项加锁来实现的,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录加锁。InnoDB行锁分为3种情形。  

Record lock:对索引项加锁。  

Gap lock:对索引项之间的“间隙”、第一条记录前的“间隙”或最后一条记录后的“间隙”加锁。
Next-key lock:前两种的组合,对记录及其前面的间隙加锁。  

InnoDB这种行锁实现特点意味着:如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟表锁一样!  


  
## 第8章 MySQL体系结构  

![image](https://note.youdao.com/yws/api/personal/file/WEB3b17b5c4fbb85f635aa70a8ebd5caab0?method=download&shareKey=94069b81e6c4dbfc5e325290214fbe47)  

在默认情况下,MySQL有7组后台线程,分别是1个主线程,4组IO线程,1个锁线程,1个错误监控线程。   

  
## 第9章 备份还原  

#### 9.1 逻辑备份
MySQL 中的逻辑备份是将数据库中的数据备份为一个文本文件,备份的文件可以被查看和编辑。在MySQL中,可以使用mysqldump工具来完成逻辑备份。我们可以使用以下3种方法来调用mysqldump。  

备份指定的数据库或者此数据库中的某些表。  
shell> mysqldump [options] db_name [tables]  

备份指定的一个或多个数据库。  
shell> mysqldump [options] ---database DB1 [DB2 DB3...]  

备份所有数据库。
shell> mysqldump [options] --all—database   

##### 9.1.1 完全恢复  
mysqldump的恢复也很简单,将备份作为输入执行即可,具体语法如下:  

mysql –uroot –p dbname < bakfile    

注意,将备份恢复后数据并不完整,还需要将备份后执行的日志进行重做,语法如下:  

mysqlbinlog binlog-file | mysql -u root –p***  

##### 9.1.2 基于时间点恢复  

##### 9.1.3 基于位置恢复  

#### 9.1.4 物理备份和恢复  

##### 9.5.1 冷备份  
冷备份其实就是停掉数据库服务,cp 数据文件的方法。这种方法对 MyISAM 和 InnoDB存储引擎都适合,但是一般很少使用,因为很多应用是不允许长时间停机的。  

##### 9.5.2 热备份  
MyISAM 和InnoDB两种最常用的存储引擎的热备份方法。  

###### 1.MyISAM存储引擎  

方法1:使用mysqlhotcopy工具。  

方法2:手工锁表copy。  

###### 2.InnoDB存储引擎  

1. ibbackup是一个热备份工具,专门对InnoDB存储引擎进行物理热备份  

2. Xtrabackup热备工具

  

你可能感兴趣的:(数据库)