Mysql笔记总结

Mysql笔记

1.架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZnP33LEO-1599925202762)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\mysql结构.png)

1.概念

MySQL Server架构自顶向下大致可以分网络连接层、服务层、存储引擎层和系统文件层

  • 网络连接层

    客户端连接器(Client Connectors):提供与MySQL服务器建立的支持。

  • 服务层

    服务层是MySQL Server的核心,主要包含系统管理和控制工具、连接池、SQL接口、解析器、查询优化器和缓存六个部分。

    • 连接池(Connection Pool):负责存储和管理客户端与数据库的连接,一个线程负责管理一个连接。
    • 系统管理和控制工具(*Management Services & Utilities):例如备份恢复、安全管理、集群管理
    • SQL接口(SQL Interface)用于接受客户端发送的各种SQL命令,并且返回用户需要查询的结果。比如DML、DDL、存储过程、视图、触发器等。
    • 解析器(Parser):负责将请求的SQL解析生成一个"解析树"。然后根据一些MySQL规则进一步检查解析树是否合法。
    • 查询优化器(Optimizer):当“解析树”通过解析器语法检查后,将交由优化器将其转化成执行计划,然后与存储引擎交互。
  • 存储引擎层

    存储引擎负责MySQL中数据的存储与提取,与底层系统文件进行交互。

  • 系统文件层

    将数据库的数据和日志存储在文件系统之上,并完成与存储引擎的交互,是文件的物理存储层

    • 日志文件
    • 配置文件
    • 数据文件
    • pid 文件
    • socket 文件

2.执行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VHhfJvtC-1599925202764)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\mysql执行器.png)

通讯机制:

  • 全双工:能同时发送和接收数据,例如平时打电话。

  • 半双工:指的某一时刻,要么发送数据,要么接收数据,不能同时。例如早期对讲机

  • 单工:只能发送数据或只能接收数据。例如单行道

​ 查询缓存

show variables like '%query_cache%';
 show status like '%Qcache%';

3.存储引擎

存储引擎在MySQL的体系架构中位于第三层,负责MySQL中的数据的存储和提取,是与文件打交道的子系统,它是根据MySQL提供的文件访问层抽象接口定制的一种文件访问机制,这种机制就叫作存储引擎。

查询命令

show engines #查询当前数据库支持的引擎

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dR4xfYhm-1599925202767)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\引擎查询.png)

  • InnoDB:支持事务,具有提交,回滚和崩溃恢复能力,事务安全

  • MyISAM:不支持事务和外键,访问速度快

  • Memory:利用内存创建表,访问速度非常快,因为数据在内存,而且默认使用Hash索引,但是一旦关闭,数据就会丢失

1.InnoDB和MyISAM对比

InnoDBMyISAM是使用MySQL时最常用的两种引擎类型

  • 事务和外键

    InnoDB支持事务和外键,具有安全性和完整性,适合大量insert或update操作

    MyISAM不支持事务和外键,它提供高速存储和检索,适合大量的select查询操作

  • 锁机制

    InnoDB支持行级锁,锁定指定记录。基于索引来加锁实现

    MyISAM支持表级锁,锁定整张表

  • 索引结构

    InnoDB使用聚集索引(聚簇索引),索引和记录在一起存储,既缓存索引,也缓存记录。

    MyISAM使用非聚集索引(非聚簇索引),索引和记录分开

  • 并发处理能力

    MyISAM使用表锁,会导致写操作并发率低,读之间并不阻塞,读写阻塞。

    InnoDB读写阻塞可以与隔离级别有关,可以采用多版本并发控制(MVCC)来支持高并发

  • 存储文件

    InnoDB表对应两个文件,一个.frm表结构文件,一个.ibd数据文件。InnoDB表最大支持64TB;

    MyISAM表对应三个文件,一个.frm表结构文件,一个MYD表数据文件,一个.MYI索引文件。从MySQL5.0开始默认限制是256TB。

2.InnoDB和MyISAM的适用场景

  • MyISAM

    • 不需要事务支持(不支持)

    • 并发相对较低(锁定机制问题)

    • 数据修改相对较少,以读为主

    • 数据一致性要求不高

  • InnoDB

    • 需要事务支持(具有较好的事务特性)
    • 行级锁定对高并发有很好的适应能力
    • 数据更新较为频繁的场景
    • 数据一致性要求较高
    • 硬件设备内存较大,可以利用InnoDB较好的缓存能力来提高内存利用率,减少磁盘IO

3.InnoDB和MyISAM的总结

	是否需要事务?	有,InnoDB
	
	是否存在并发修改?	有,InnoDB
	
	是否追求快速查询,且数据修改少?是,MyISAM
	
	在绝大多数情况下,推荐使用InnoDB

4.InnoDB存储结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uU7hbmfy-1599925202769)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\InnoDb引擎图.png)

1.内存结构

内存结构主要包括Buffer Pool、Change Buffer、Adaptive Hash Index和Log Buffer四大组件

  • Buffer Pool缓存池
  • Change Buffer:写缓冲区,简称CB
  • Adaptive Hash Index:自适应哈希索引,用于优化对BP数据的查询。
  • Log Buffer:日志缓冲区
Buffer Pool

BP的底层采用链表数据结构管理Page。在InnoDB访问表记录和索引时会在Page页中缓存,以后使用可以减少磁盘IO操作,提升效率

Buffer Pool配置参数

show variables like '%innodb_page_size%'; //查看page页大小
show variables like '%innodb_old%'; //查看lru list中old列表参数
show variables like '%innodb_buffer%'; //查看buffer pool参数
#建议:将innodb_buffer_pool_size设置为总内存大小的60%-80%,innodb_buffer_pool_instances可以设置为多个,这样可以避免缓存争夺。
Change Buffer

ChangeBuffffer占用BufffferPool空间,默认占25%,最大允许占50%,可以根据读写业务量来进行调整。参数innodb_change_buffffer_max_size;

Adaptive Hash Index

自适应哈希索引,用于优化对BP数据的查询。InnoDB存储引擎会监控对表索引的查找,如果观察到建立哈希索引可以带来速度的提升,则建立哈希索引,所以称之为自适应。InnoDB存储引擎会自动根据访问的频率和模式来为某些页建立哈希索引

Log Buffer

日志缓冲区,用来保存要写入磁盘上log文件(Redo/Undo)的数据,日志缓冲区的内容定期刷新到磁盘log文件中。日志缓冲区满时会自动将其刷新到磁盘,当遇到BLOB或多行更新的大事务操作时,增加日志缓冲区可以节省磁盘I/O。

2.磁盘结构

InnoDB磁盘主要包含Tablespaces,InnoDB Data Dictionary,Doublewrite Buffffer、Redo Log和Undo Logs。

Tablespaces

用于存储表结构和数据。表空间又分为系统表空间、独立表空间、通用表空间、临时表空间、Undo表空间等多种类型;

  • 系统表空间 默认包含任何用户在系统表空间创建的表数据和索引数据。系统表空间是一个共享的表空间因为它是被多个表共享的。

  • 独立表空间 默认开启,独立表空间是一个单表表空间,该表创建于自己的数据文件中,而非创建于系统表空间中。

  • 通用表空间 通用表空间为通过create tablespace语法创建的共享表空间。通用表空间可以创建于mysql数据目录外的其他表空间,其可以容纳多张表,且其支持所有的行格式。

  • 撤销表空间 由一个或多个包含Undo日志文件组成。

  • 临时表空间 mysql服务器正常关闭或异常终止时,临时表空间将被移除,每次启动时会被重新创建

InnoDB Data Dictionary

InnoDB数据字典由内部系统表组成,这些表包含用于查找表、索引和表字段等对象的元数据。元数据物理上位于InnoDB系统表空间中。由于历史原因,数据字典元数据在一定程度上与InnoDB表元数据文件(.frm文件)中存储的信息重叠。

Doublewrite Buffffer

在BufffferPage的page页刷新到磁盘真正的位置前,会先将数据存在Doublewrite 缓冲区。

Redo Log

重做日志是一种基于磁盘的数据结构,用于在崩溃恢复期间更正不完整事务写入的数据。

Undo Logs

撤消日志是在事务开始之前保存的被修改数据的备份,用于例外情况时回滚事务。

5.InnoDB数据文件

1.InnoDB文件存储结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I8z7sgqY-1599925202771)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\文件存储结构.png)

InnoDB数据文件存储结构:分为一个ibd数据文件–>Segment(段)–>Extent(区)–>Page(页)–>Row(行)

  • Tablesapce 表空间,用于存储多个ibd数据文件,用于存储表的记录和索引。一个文件包含多个段

  • Segment 段,用于管理多个Extent

  • Extent 区,一个区固定包含64个连续的页,大小为1M。

  • Page 页,用于存储多个Row行记录,大小为16K。

  • Row行,包含了记录的字段值,事务ID(Trx id)、滚动指针(Roll pointer)、字段指针(Fieldpointers)等信息

SHOW TABLE STATUS  #查看命令

通过 information_schema 查看指定表的文件格式

select * from information_schema.innodb_sys_tables;

如果某些字段信息过长,无法存储在B树节点中,这时候会被单独分配空间,此时被称为溢出页,该字段被称为页外列。

REDUNDANT 行格式

使用REDUNDANT行格式,表会将变长列值的前768字节存储在B树节点的索引记录中,其余的存储在溢出页上。对于大于等于786字节的固定长度字段InnoDB会转换为变长字段,以便能够在页外存储。

COMPACT 行格式

与REDUNDANT行格式相比,COMPACT行格式减少了约20%的行存储空间,但代价是增加了某些操作的CPU使用量。如果系统负载是受缓存命中率和磁盘速度限制,那么COMPACT格式可能更快。如果系统负载受到CPU速度的限制,那么COMPACT格式可能会慢一些。

DYNAMIC 行格式

使用DYNAMIC行格式,InnoDB会将表中长可变长度的列值完全存储在页外,而索引记录只包含指向溢出页的20字节指针。大于或等于768字节的固定长度字段编码为可变长度字段。DYNAMIC行格式支持大索引前缀,最多可以为3072字节,可通过innodb_large_prefifix参数控制。

COMPRESSED 行格式

COMPRESSED行格式提供与DYNAMIC行格式相同的存储特性和功能,但增加了对表和索引数据压缩的支持

在创建表和索引时,文件格式都被用于每个InnoDB表数据文件(其名称与*.ibd匹配)。修改文件格式的方法是重新创建表及其索引,最简单方法是对要修改的每个表使用以下命令:

ALTER TABLE 表名 ROW_FORMAT=格式类型;

6.Undo Log

介绍

Undo:意为撤销或取消,以撤销操作为目的,返回指定某个状态的操作。

Undo Log:数据库事务开始之前,会将要修改的记录存放到 Undo 日志里,当事务回滚时或者数据库崩溃时,可以利用 Undo 日志,撤销未提交事务对数据库产生的影响。

Undo Log产生和销毁:Undo Log在事务开始前产生;事务在提交时,并不会立刻删除undolog,innodb会将该事务对应的undo log放入到删除列表中,后面会通过后台线程purge thread进行回收处理。Undo Log属于逻辑日志,记录一个变化过程。例如执行一个delete,undolog会记录一个insert;执行一个update,undolog会记录一个相反的update。

show variables like '%innodb_undo%';

Undo Log作用

  • 实现事务的原子性
  • 实现多版本并发控制(MVCC)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BSdA8gd5-1599925202773)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\Undo Log.png)

事务A手动开启事务,执行更新操作,首先会把更新命中的数据备份到 Undo Buffffer 中。

事务B手动开启事务,执行查询操作,会读取 Undo 日志数据返回,进行快照读

7.Redo Log和Binlog

Redo Log介绍

Redo:顾名思义就是重做。以恢复操作为目的,在数据库发生意外时重现操作

Redo Log:指事务中修改的任何数据,将最新的数据备份存储的位置(Redo Log),被称为重做日志。

Redo Log 的生成和释放:随着事务操作的执行,就会生成Redo Log,在事务提交时会将产生

Redo Log写入Log Buffer,并不是随着事务的提交就立刻写入磁盘文件。等事务操作的脏页写入到磁盘之后,Redo Log 的使命也就完成了,Redo Log占用的空间就可以重用(被覆盖写入)。

### [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dmrQdmjR-1599925202775)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\Redo Log.png)

show variables like '%innodb_log%';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eLcM6FmO-1599925202775)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\redo LogSql.png)

Binlog日志

Redo Log 是属于InnoDB引擎所特有的日志,而MySQL Server也有自己的日志,即 Binarylog(二进制日志),简称Binlog。

Binlog是记录所有数据库表结构变更以及表数据修改的二进制日志不会记录SELECT和SHOW这类操作

Binlog两个最重要的使用场景
  • 主从复制:在主库中开启Binlog功能,这样主库就可以把Binlog传递给从库,从库拿到Binlog后实现数据恢复达到主从数据一致性。
  • 数据恢复:通过mysqlbinlog工具来恢复数据。
Binlog文件操作

Binlog状态查看

show variables like 'log_bin';

开启Binlog功能

mysql> set global log_bin=mysqllogbin; 

需要修改my.cnf或my.ini配置文件,在[mysqld]下面增加log_bin=mysql_bin_log,重启

MySQL服务。

#log-bin=ON 
#log-bin-basename=mysqlbinlog 
binlog-format=ROW 
log-bin=mysqlbinlog

使用show binlog events命令


show binary logs; //等价于show master logs; 
show master status; 
show binlog events; 
show binlog events in 'mysqlbinlog.000001';

使用mysqlbinlog 命令

mysqlbinlog “文件名”

mysqlbinlog “文件名” > “test.sql”

使用 binlog 恢复数据

//按指定时间恢复 
mysqlbinlog --start-datetime="2020-04-25 18:00:00" --stop- datetime="2020-04-26 00:00:00" mysqlbinlog.000002 | mysql -uroot -p1234 
//按事件位置号恢复 
mysqlbinlog --start-position=154 --stop-position=957 mysqlbinlog.000002 | mysql -uroot -p1234

mysqldump:定期全部备份数据库数据。mysqlbinlog可以做增量备份和恢复操作。

删除Binlog文件

purge binary logs to 'mysqlbinlog.000001'; //删除指定文件 

purge binary logs before '2020-04-28 00:00:00'; //删除指定时间之前的文件 

reset master; //清除所有文件

通过设置expire_logs_days参数来启动自动清理功能。默认值为0表示没启用。设置为1表示超出1天binlog文件会自动删除掉。

Redo Log和Binlog区别

  • Redo Log是属于InnoDB引擎功能,Binlog是属于MySQL Server自带功能,并且是以二进制文件记录。

  • Redo Log属于物理日志,记录该数据页更新状态内容,Binlog是逻辑日志,记录更新过程。

  • Redo Log日志是循环写,日志空间大小是固定,Binlog是追加写入,写完一个写下一个,不会覆盖使用。

  • Redo Log作为服务器异常宕机后事务数据自动恢复使用,Binlog可以作为主从复制和数据恢复使用。Binlog没有自动crash-safe能力。

2.索引

1.索引类型

索引可以提升查询速度,会影响where查询,以及order by排序。MySQL索引类型如下:

  • 从索引存储结构划分:B Tree索引、Hash索引、FULLTEXT全文索引、R Tree索引

  • 从应用层次划分:普通索引、唯一索引、主键索引、复合索引

  • 从索引键值类型划分:主键索引、辅助索引(二级索引)

  • 从数据存储和索引键值逻辑关系划分:聚集索引(聚簇索引)、非聚集索引(非聚簇索引)

普通索引

基于普通字段建立的索引,没有任何限制。

  • CREATE INDEX <索引的名字> ON tablename (字段名);

  • ALTER TABLE tablename ADD INDEX [索引的名字] (字段名);

  • CREATE TABLE tablename ( […], INDEX [索引的名字] (字段名) );

唯一索引

索引字段的值必须唯一,但允许有空值 。在创建或修改表时追加唯一约束,就会自动创建对应的唯一索引。

  • CREATE UNIQUE INDEX <索引的名字> ON tablename (字段名);

  • ALTER TABLE tablename ADD UNIQUE INDEX [索引的名字] (字段名);

  • CREATE TABLE tablename ( […], UNIQUE [索引的名字] (字段名) ;

主键索引

特殊的唯一索引,不允许有空值。在创建或修改表时追加主键约束即可,每个表只能有一个主键

  • CREATE TABLE tablename ( […], PRIMARY KEY (字段名) );

  • ALTER TABLE tablename ADD PRIMARY KEY (字段名);

复合索引

单一索引是指索引列为一列的情况,即新建索引的语句只实施在一列上;用户可以在多个列上建立索引,这种索引叫做组复合索引(组合索引)。复合索引可以代替多个单一索引,相比多个单一索引复合索引所需的开销更小。

索引同时有两个概念叫做窄索引和宽索引,窄索引是指索引列为1-2列的索引,宽索引也就是索引列超过2列的索引,设计索引的一个重要原则就是能用窄索引不用宽索引,因为窄索引往往比组合索引更有效

  • CREATE INDEX <索引的名字> ON tablename (字段名1,字段名2…);
  • ALTER TABLE tablename ADD INDEX [索引的名字] (字段名1,字段名2…);
  • CREATE TABLE tablename ( […], INDEX [索引的名字] (字段名1,字段名2…) );
复合索引使用注意事项:
  • 何时使用复合索引,要根据where条件建索引,注意不要过多使用索引,过多使用会对更新操作效率有很大影响。

  • 如果表已经建立了(col1,col2),就没有必要再单独建立(col1);如果现在有(col1)索引,如果查询需要col1和col2条件,可以建立(col1,col2)复合索引,对于查询有一定提高。

全文索引

查询操作在数据量比较少时,可以使用like模糊查询,但是对于大量的文本数据检索,效率很低。如果使用全文索引,查询速度会比like快很多倍

创建全文索引的方法如下:

  • CREATE FULLTEXT INDEX <索引的名字> ON tablename (字段名);

  • ALTER TABLE tablename ADD FULLTEXT [索引的名字] (字段名);

  • CREATE TABLE tablename ( […], FULLTEXT KEY [索引的名字] (字段名) ;

select * from user where match(name) against('aaa');
全文索引使用注意事项
  • 全文索引必须在字符串、文本字段上建立。

  • 全文索引字段值必须在最小字符和最大字符之间的才会有效。(innodb:3-84;myisam:4-84)

  • 全文索引字段值要进行切词处理,按syntax字符进行切割,例如b+aaa,切分成b和aaa

  • 全文索引匹配查询,默认使用的是等值匹配,例如a匹配a,不会匹配ab,ac。如果想匹配可以在布尔模式下搜索a*

2.索引原理

MySQL官方对索引定义:是存储引擎用于快速查找记录的一种数据结构。需要额外开辟空间和数据维护工作。

  • 索引是物理数据页存储,在数据文件中(InnoDB,ibd文件),利用数据页(page)存储。

  • 索引可以加快检索速度,但是同时也会降低增删改操作速度,索引维护需要代价。

二分查找法

二分查找法也叫作折半查找法,它是在有序数组中查找指定数据的搜索算法。它的优点是等值查询、范围查询性能优秀,缺点是更新数据、新增数据、删除数据维护成本高

Hash结构

Hash底层实现是由Hash表来实现的,是根据键值 <key,value> 存储数据的结构。非常适合根据key查找value值,也就是单个key查询,或者说等值查询。

InnoDB自适应哈希索引:在使用Hash索引访问时,一次性查找就能定位数据,等值查询效率要优于B+Tree。

自适应哈希索引的建立使得InnoDB存储引擎能自动根据索引页访问的频率和模式自动地为某些热点页建立哈希索引来加速访问

show engine innodb status \G; 
show variables like '%innodb_adaptive%';

B+Tree结构

MySQL数据库索引采用的是B+Tree结构,在B-Tree结构上做了优化改造。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFXZki3V-1599925202776)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\B-Tree.png)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kHoaqv45-1599925202778)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\B+Tree.png)

聚簇索引和辅助索引

聚簇索引和非聚簇索引:B+Tree的叶子节点存放主键索引值和行记录就属于聚簇索引;如果索引值和行记录分开存放就属于非聚簇索引。

主键索引和辅助索引:B+Tree的叶子节点存放的是主键字段值就属于主键索引;如果存放的是非主键值就属于辅助索引(二级索引)。

在InnoDB引擎中,主键索引采用的就是聚簇索引结构存储

  • 聚簇索引(聚集索引)

聚簇索引是一种数据存储方式,InnoDB的聚簇索引就是按照主键顺序构建 B+Tree结构。B+Tree的叶子节点就是行记录,行记录和主键值紧凑地存储在一起。 这也意味着 InnoDB 的主键索引就是数据表本身,它按主键顺序存放了整张表的数据,占用的空间就是整个表数据量的大小。通常说的主键索引就是聚集索引

  • 辅助索引

InnoDB辅助索引,也叫作二级索引,是根据索引列构建 B+Tree结构。但在 B+Tree 的叶子节点中只存了索引列和主键的信息。二级索引占用的空间会比聚簇索引小很多, 通常创建辅助索引就是为了提升查询效率。一个表InnoDB只能创建一个聚簇索引,但可以创建多个辅助索引。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IiZRHApa-1599925202779)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\聚簇索引.png)

  • 非聚簇索引

与InnoDB表存储不同,MyISAM数据表的索引文件和数据文件是分开的,被称为非聚簇索引结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d0syLCZZ-1599925202780)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\非聚簇索引.png)

3.索引分析与优化

MySQL 提供了一个 EXPLAIN 命令,它可以对 SELECT 语句进行分析,并输出 SELECT 执行的详细信息,供开发人员有针对性的优化。

EXPLAIN SELECT * from user WHERE id < 3;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nltNXtE5-1599925202781)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\Sql分析.png)

  • select_type

表示查询的类型。常用的值如下:

  • SIMPLE : 表示查询语句不包含子查询或union

  • PRIMARY:表示此查询是最外层的查询

  • UNION:表示此查询是UNION的第二个或后续的查询

  • EXPLAIN SELECT * from user WHERE id < 3;DEPENDENT UNION:UNION中的第二个或后续的查询语句,使用了外面查询结果

  • UNION RESULT:UNION的结果

  • SUBQUERY:SELECT子查询语句

  • DEPENDENT SUBQUERY:SELECT子查询语句依赖外层查询的结果。

最常见的查询类型是SIMPLE,表示我们的查询没有子查询也没用到UNION查询。

  • type

表示存储引擎查询数据时采用的方式。比较重要的一个属性,通过它可以判断出查询是全表扫描还是基于索引的部分扫描。常用属性值如下,

从上至下效率依次增强。

ALL:表示全表扫描,性能最差。

index:表示基于索引的全表扫描,先扫描索引再扫描全表数据。

range:表示使用索引范围查询。使用>、>=、<、<=、in等等。

ref:表示使用非唯一索引进行单值查询。

eq_ref:一般情况下出现在多表join查询,表示前面表的每一个记录,都只能匹配后面表的一行结果。

const:表示使用主键或唯一索引做等值查询,常量查询。

NULL:表示不用访问表,速度最快。

  • possible_keys

表示查询时能够使用到的索引。注意并不一定会真正使用,显示的是索引名称

  • key

表示查询时真正使用到的索引,显示的是索引名称

  • rows

MySQL查询优化器会根据统计信息,估算SQL要查询到结果需要扫描多少行记录。原则上rows是越少效率越高,可以直观的了解到SQL效率高低。

  • Extra

Extra表示很多额外的信息,各种操作会在Extra提示相关信息,常见几种如下:

Using where

表示查询需要通过索引回表查询数据。

Using index

表示查询需要通过索引,索引就可以满足所需数据。

Using filesort

表示查询出来的结果需要额外排序,数据量小在内存,大的话在磁盘,因此有Using fifilesort建议优化。

Using temprorary

查询使用到了临时表,一般出现于去重、分组等操作。

4.回表查询

通过索引查询主键值,然后再去聚簇索引查询记录信息

5.覆盖索引

只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快,这就叫做索引覆盖

实现索引覆盖最常见的方法就是:将被查询的字段,建立到组合索引。

6.最左前缀原则

复合索引使用时遵循最左前缀原则,最左前缀顾名思义,就是最左优先,即查询中使用到最左边的列,那么查询就会使用到索引,如果从索引的第二列开始查找,索引将失效。

7.面试题

1.LIKE查询

面试题:MySQL在使用like模糊查询时,索引能不能起作用?

回答:MySQL在使用Like模糊查询时,索引是可以被使用的,只有把%字符写在后面才会使用到索引。

select * from user where name like ‘%o%’; //不起作用

select * from user where name like ‘o%’; //起作用

select * from user where name like ‘%o’; //不起作用

2.NULL查询

面试题:如果MySQL表的某一列含有NULL值,那么包含该列的索引是否有效?

对MySQL来说,NULL是一个特殊的值,从概念上讲,NULL意味着“一个未知值”,它的处理方式与其他值有些不同。比如:不能使用=,<,>这样的运算符,对NULL做算术运算的结果都是NULL,count时不会包括NULL行等,NULL比空字符串需要更多的存储空间等。

虽然MySQL可以在含有NULL的列上使用索引,但NULL和其他数据还是有区别的,不建议列上允许为NULL。最好设置NOT NULL,并给一个默认值,比如0和 ‘’ 空字符串等,如果是datetime类型,也可以设置系统当前时间或某个固定的特殊值,例如’1970-01-01 00:00:00’。

8.索引与排序

MySQL查询支持filesort和index两种方式的排序。

filesort是先把结果查出,然后在缓存或磁盘进行排序操作,效率较低

index是指利用索引自动实现排序,不需另做排序操作,效率会比较高

如果我们Explain分析SQL,结果中Extra属性显示Using filesort,表示使用了filesort排序方式,需要优化。

如果Extra属性显示Using index时,表示覆盖索引,也表示所有操作在索引上完成,也可以使用index排序方式,建议大家尽可能采用覆盖索引

Sql会使用index方式的排序

  • ORDER BY 子句索引列组合满足索引最左前列

    explain select id from user order by id; //对应(id)、(id,name)索引有效
    
  • WHERE子句+ORDER BY子句索引列组合满足索引最左前列

    explain select id from user where age=18 order by name; //对应 (age,name)索引
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ff7WJN1H-1599925202782)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\sql排序调优.png)

Sql会使用fifilesort方式的排序

  • 对索引列同时使用了ASC和DESC
explain select id from user order by age asc,name desc; //对应 (age,name)索引
  • WHERE子句和ORDER BY子句满足最左前缀,但where子句使用了范围查询(例如>、<、in等)
explain select id from user where age>10 order by name; //对应 (age,name)索引
  • ORDER BY或者WHERE+ORDER BY索引列没有满足索引最左前列
explain select id from user order by name; //对应(age,name)索引
  • 使用了不同的索引,MySQL每次只采用一个索引,ORDER BY涉及了两个索引
explain select id from user order by name,age; //对应(name)、(age)两个索引
  • WHERE子句与ORDER BY子句,使用了不同的索引
explain select id from user where name='tom' order by age; //对应 (name)、(age)索引
  • WHERE子句或者ORDER BY子句中索引列使用了表达式,包括函数表达式
explain select id from user order by abs(age); //对应(age)索引

9.查询优化

慢查询定位

查看 MySQL 数据库是否开启了慢查询日志和慢查询日志文件的存储位置的命令如下:

SHOW VARIABLES LIKE 'slow_query_log%'

通过如下命令开启慢查询日志:

SET global slow_query_log = ON;
SET global slow_query_log_file = 'OAK-slow.log'; 
SET global log_queries_not_using_indexes = ON; 
SET long_query_time = 10;
  • long_query_time:指定慢查询的阀值,单位秒。如果SQL执行时间超过阀值,就属于慢查询记录到日志文件中。

  • log_queries_not_using_indexes:表示会记录没有使用索引的查询SQL。前提是slow_query_log的值为ON,否则不会奏效。

查看慢查询日志

  • 文本方式查看

  • 使用mysqldumpslow查看

慢查询优化

  • 索引和慢查询

    • 如何判断是否为慢查询?

    MySQL判断一条语句是否为慢查询语句,主要依据SQL语句的执行时间,它把当前语句的执行时间跟 long_query_time 参数做比较

    • 如何判断是否应用了索引?

    通过 explain命令分析查看,检查结果中的 key 值,是否为NULL。

    • 应用了索引是否一定快?

    select * from user where id>0; 从主键索引的最左边的叶节点开始向右扫描整个索引树,进行了全表扫描,此时索引就失去了意义。

    select * from user where id = 2 ; 使用了索引的快速搜索功能,并且有效地减少了扫描行数。

  • 提高索引过滤性

    案例:

    表:student 
    字段:id,name,sex,age 
    造数据:insert into student (name,sex,age) select name,sex,age from student; SQL
    案例:select * from student where age=18 and name like '张%';(全表扫 描)
    

    优化一:

    alter table student add index(name); //追加name索引
    

    优化二:

    alter table student add index(age,name); //追加age,name索引
    

    优化三:

    index condition pushdown 优化的效果还是很不错的。再进一步优化,我们可以把名 字的第一个字和年龄做一个联合索引,这里可以使用 MySQL 5.7 引入的虚拟列来实现。
    
    //为user表添加first_name虚拟列,以及联合索引(first_name,age) 
    alter table student add first_name varchar(2) generated always as (left(name, 1)), add index(first_name, age); 
    explain select * from student where first_name='张' and age=18;
    
  • 慢查询原因总结

    • 全表扫描:explain分析type属性all
    • 全索引扫描:explain分析type属性index
    • 索引过滤性不好:靠索引字段选型、数据量和状态、表设计
    • 频繁的回表查询开销:尽量少用select *,使用覆盖索引

分页查询优化

  • 一般性分页
SELECT * FROM 表名 LIMIT [offset,] rows

第一个参数指定第一个返回记录行的偏移量,注意从0开始;

第二个参数指定返回记录行的最大数目;

如果只给定一个参数,它表示返回最大的记录行数目;

思考1:如果偏移量固定,返回记录量对执行时间有什么影响?

select * from user limit 10000,1; 
select * from user limit 10000,10;
select * from user limit 10000,100; 
select * from user limit 10000,1000; 
select * from user limit 10000,10000;

结果:在查询记录时,返回记录量低于100条,查询时间基本没有变化,差距不大。随着查询记录量越大,所花费的时间也会越来越多。

思考2:如果查询偏移量变化,返回记录数固定对执行时间有什么影响?

select * from user limit 1,100;
select * from user limit 10,100;
select * from user limit 100,100; 
select * from user limit 1000,100; 
select * from user limit 10000,100;

结果:在查询记录时,如果查询记录量相同,偏移量超过100后就开始随着偏移量增大,查询时间急剧的增加。(这种分页查询机制,每次都会从数据库第一条记录开始扫描,越往后查询越慢,而且查询的数据越多,也会拖慢总查询速度。)

分页优化方案

第一步:利用覆盖索引优化

select * from user limit 10000,100; 
select id from user limit 10000,100;

第二步:利用子查询优化

select * from user limit 10000,100;
select * from user where id>= (select id from user limit 10000,1) limit 100;

原因:使用了id做主键比较(id>=),并且子查询使用了覆盖索引进行优化。

3.MySQL事务和锁

ACID 特性

一个逻辑工作单元要成为事务,必须满足这 4 个特性,即所谓的 ACID:

原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)

原子性

原子性:事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。

持久性

持久性:指的是一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,后续的操作或故障不应该对其有任何影响,不会丢失。

隔离性

隔离性:指的是一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对其他的并发事务是隔离的

一致性

事务开始之前和事务结束之后,数据库的完整性限制未被破坏。一致性包括两方面的内容,分别是约束一致性和数据一致性。

一致性也可以理解为数据的完整性。数据的完整性是通过原子性、隔离性、持久性来保证的,而这3个特性又是通过 Redo/Undo 来保证的。

事务控制的演进

并发事务

事务并发处理可能会带来一些问题,比如:更新丢失、脏读、不可重复读、幻读等。

  • 更新丢失

    当两个或多个事务更新同一行记录,会产生更新丢失现象。可以分为回滚覆盖和提交覆盖。

    回滚覆盖:一个事务回滚操作,把其他事务已提交的数据给覆盖了。

    提交覆盖:一个事务提交操作,把其他事务已提交的数据给覆盖了。

  • 脏读

    一个事务读取到了另一个事务修改但未提交的数据。

  • 不可重复读

    一个事务中多次读取同一行记录不一致,后面读取的跟前面读取的不一致。

  • 幻读

    一个事务中多次按相同条件查询,结果不一致。后续查询的结果和面前查询结果不同,多了或少了几行记录。

排队

完全顺序执行所有事务的数据库操作,不需要加锁,简单的说就是全局排队。序列化执行所有的事务单元,数据库某个时刻只处理一个事务操作,特点是强一致性,处理性能低。

排他锁

引入锁之后就可以支持并发处理事务,如果事务之间涉及到相同的数据项时,会使用排他锁,或叫互斥锁,先进入的事务独占数据项以后,其他事务被阻塞,等待前面的事务释放锁。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iwZYePUx-1599925202783)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\排他锁.png)

读写锁

读和写操作:读读、写写、读写、写读。

读写锁就是进一步细化锁的颗粒度,区分读操作和写操作,让读和读之间不加锁,这样下面的两个事务就可以同时被执行了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VtKSLZnV-1599925202784)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\读写锁.png)

MVCC

多版本控制MVCC,也就是Copy on Write的思想。MVCC除了支持读和读并行,还支持读和写、写和读的并行,但为了保证一致性,写和写是无法并行的。

概念

MVCC(Multi Version Concurrency Control)被称为多版本控制,是指在数据库中为了实现高并发的数据访问,对数据进行多版本处理,并通过事务的可见性来保证事务能看到自己应该看到的数据版本。

MVCC实现原理

MVCC最大的好处是读不加锁,读写不冲突。在读多写少的系统应用中,读写不冲突是非常重要的,极大的提升系统的并发性能,这也是为什么现阶段几乎所有的关系型数据库都支持 MVCC 的原因,不过目前MVCC只在 Read Commited 和 Repeatable Read 两种隔离级别下工作

MVCC只在 Read Commited 和 Repeatable Read 两种隔离级别下工作。

在 MVCC 并发控制中,读操作可以分为两类: 快照读(Snapshot Read)与当前读 (Current Read)

  • 快照读:读取的是记录的快照版本(有可能是历史版本),不用加锁。(select)

  • 当前读:读取的是记录的最新版本,并且当前读返回的记录,都会加锁,保证其他事务不会再并发修改这条记录。(select… for update 或lock in share mode,insert/delete/update)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uzXrUHKp-1599925202785)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\mvvc.png)

事务隔离级别

隔离级别类型

  • 读未提交

Read Uncommitted 读未提交:解决了回滚覆盖类型的更新丢失,但可能发生脏读现象,也就是可能读取到其他会话中未提交事务修改的数据。

  • 已提交读

Read Committed 读已提交:只能读取到其他会话中已经提交的数据,解决了脏读。但可能发生不可重复读现象,也就是可能在一个事务中两次查询结果不一致。

  • 可重复度

Repeatable Read 可重复读:解决了不可重复读,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上会出现幻读,简单的说幻读指的的当用户读取某一范围的数据行时,另一个事务又在该范围插入了新行,当用户在读取该范围的数据时会发现有新的幻影行。

  • 可串行化

Serializable 串行化:所有的增删改查串行执行。它通过强制事务排序,解决相互冲突,从而解决幻度的问题。这个级别可能导致大量的超时现象的和锁竞争,效率低下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mXeta1HT-1599925202786)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\隔离级别.png)

事务隔离级别和锁的关系

  • 事务隔离级别是SQL92定制的标准,相当于事务并发控制的整体解决方案,本质上是对锁和MVCC使用的封装,隐藏了底层细节。

  • 锁是数据库实现并发控制的基础,事务隔离性是采用锁来实现,对相应操作加不同的锁,就可以防止其他事务同时对数据进行读写操作。

  • 对用户来讲,首先选择使用隔离级别,当选用的隔离级别不能解决并发问题或需求时,才有必要在开发中手动的设置锁。

MySQL默认隔离级别:可重复读

Oracle、SQLServer默认隔离级别:读已提交

一般使用时,建议采用默认隔离级别,然后存在的一些并发问题,可以通过悲观锁、乐观锁等实现处理

MySQL隔离级别控制

查看MySQL当前数据库的事务隔离级别命令

show variables like 'tx_isolation';
select @@tx_isolation;

设置隔离级别

set tx_isolation='READ-UNCOMMITTED'; 
set tx_isolation='READ-COMMITTED'; 
set tx_isolation='REPEATABLE-READ'; 
set tx_isolation='SERIALIZABLE';

锁机制和实战

锁分类

  • 操作的粒度可分为表级锁、行级锁和页级锁。

    • 表级锁:每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、BDB 等存储引擎中。
    • 行级锁:每次操作锁住一行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB 存储引擎中。
    • 页级锁:每次锁定相邻的一组记录,锁定粒度界于表锁和行锁之间,开销和加锁时间界于表锁和行锁之间,并发度一般。应用在BDB 存储引擎中。
  • 操作的类型可分为读锁和写锁。

    • 读锁(S锁):共享锁,针对同一份数据,多个读操作可以同时进行而不会互相影响。

    • 写锁(X锁):排他锁,当前写操作没有完成前,它会阻断其他写锁和读锁。

    IS锁、IX锁:意向读锁、意向写锁,属于表级锁,S和X主要针对行级锁。在对表记录添加S或X锁之前,会先对表添加IS或IX锁。

    S锁:事务A对记录添加了S锁,可以对记录进行读操作,不能做修改,其他事务可以对该记录追加。

    S锁,但是不能追加X锁,需要追加X锁,需要等记录的S锁全部释放。

    X锁:事务A对记录添加了X锁,可以对记录进行读和修改操作,其他事务不能对记录做读和修改操作

  • 操作的性能可分为乐观锁和悲观锁。

    • 乐观锁:一般的实现方式是对记录数据版本进行比对,在数据更新提交的时候才会进行冲突检测,如果发现冲突了,则提示错误信息。
    • 悲观锁:在对一条数据修改的时候,为了避免同时被其他人修改,在修改数据之前先锁定,再修改的控制方式。共享锁和排他锁是悲观锁的不同实现,但都属于悲观锁范畴。

行锁原理

在InnoDB引擎中,我们可以使用行锁和表锁,其中行锁又分为共享锁和排他锁InnoDB行锁是通过对索引数据页上的记录加锁实现的

主要实现算法有 3 种:Record Lock、Gap Lock 和 Next-key Lock。

  • RecordLock锁:锁定单个行记录的锁。(记录锁,RC、RR隔离级别都支持)
  • GapLock锁:间隙锁,锁定索引记录间隙,确保索引记录的间隙不变。(范围锁,RR隔离级别支持)
  • Next-key Lock 锁:记录锁和间隙锁组合,同时锁住数据,并且锁住数据前后范围。(记录锁+范围锁,RR隔离级别支持)

在RR隔离级别,InnoDB对于记录加锁行为都是先采用Next-Key Lock,但是当SQL操作含有唯一索引时,Innodb会对Next-Key Lock进行优化,降级为RecordLock,仅锁住索引本身而非范围。

  • select … from 语句:InnoDB引擎采用MVCC机制实现非阻塞读,所以对于普通的select语句,InnoDB不加锁

  • select … from lock in share mode语句:追加了共享锁,InnoDB会使用Next-Key Lock锁进行处理,如果扫描发现唯一索引,可以降级为RecordLock锁。

  • select … from for update语句:追加了排他锁,InnoDB会使用Next-Key Lock锁进行处理,如果扫描发现唯一索引,可以降级为RecordLock锁。

  • update … where 语句:InnoDB会使用Next-Key Lock锁进行处理,如果扫描发现唯一索引,可以降级为RecordLock锁。

  • delete … where 语句:InnoDB会使用Next-Key Lock锁进行处理,如果扫描发现唯一索引,可以降级为RecordLock锁。

  • insert语句:InnoDB会在将要插入的那一行设置一个排他的RecordLock锁

悲观锁

悲观锁(Pessimistic Locking),是指在数据处理过程,将数据处于锁定状态,一般使用数据库的锁机制实现。从广义上来讲,前面提到的行锁、表锁、读锁、写锁、共享锁、排他锁等,这些都属于悲观锁范畴。

  • 表级锁

表级锁每次操作都锁住整张表,并发度最低。

常用命令如下:手动增加表锁

lock table 表名称 read|write,表名称2 read|write;

查看表上加过的锁

show open tables;

删除表锁

unlock tables;

表级读锁会阻塞写操作,但是不会阻塞读操作。而写锁则会把读和写操作都阻塞。

  • 共享锁

共享锁又称为读锁,简称S锁。共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。使用共享锁的方法是在select … lock in share mode,只适用查询语句

总结:事务使用了共享锁(读锁),只能读取,不能修改,修改操作被阻塞。

  • 排他锁(行级锁-写锁)

排他锁又称为写锁,简称X锁。排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能对该行记录做其他操作,也不能获取该行的锁。

使用排他锁的方法是在SQL末尾加上for updateinnodb引擎默认会在update,delete语句加上for update。行级锁的实现其实是依靠其对应的索引,所以如果操作没用到索引的查询,那么会锁住全表记录。

总结:事务使用了排他锁(写锁),当前事务可以读取和修改,其他事务不能修改,也不能获取记录锁(select… for update)。如果查询没有使用到索引,将会锁住整个表记录

乐观锁

在数据库操作时,想法很乐观,认为这次的操作不会导致冲突,因此在数据库操作时并不做任何的特殊处理,即不加锁,而是在进行事务提交时再去判断是否有冲突了。

悲观锁和乐观锁都可以解决事务写写并发,在应用中可以根据并发处理能力选择区分,比如对并发率要求高的选择乐观锁;对于并发率要求低的可以选择悲观锁。

乐观锁实现原理

  • 使用版本字段(version)

先给数据表增加一个版本(version) 字段,每操作一次,将那条记录的版本号加 1。version是用来查看被读的记录有无变化,作用是防止记录在业务处理期间被其他事务修改。

  • 使用时间戳(Timestamp)

与使用version版本字段相似,同样需要给在数据表增加一个字段,字段类型使用timestamp时间戳。也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则提交更新,否则就是版本冲突,取消操作

乐观锁案例

第一步:查询商品信息

select (quantity,version) from products where id=1;

第二部:根据商品信息生成订单

insert into orders ... insert into items ...

第三部:修改商品库存

update products set quantity=quantity-1,version=version+1 where id=1 and version=#{version};

死锁与解决方案

  • 表锁死锁

用户A访问表A(锁住了表A),然后又访问表B;另一个用户B访问表B(锁住了表B),然后企图访问表A.

解决方案:

这种死锁比较常见,是由于程序的BUG产生的,除了调整的程序的逻辑没有其它的办法。仔细分析程序的逻辑,对于数据库的多表操作时,尽量按照相同的顺序进行处理,尽量避免同时锁定两个资源,如操作A和B两张表时,总是按先A后B的顺序处理, 必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源。

  • 行级锁死锁

如果在事务中执行了一条没有索引条件的查询,引发全表扫描,把行级锁上升为全表记录锁定(等价于表级锁),多个这样的事务执行后,就很容易产生死锁和阻塞,最终应用系统会越来越慢,发生阻塞或死锁。

解决方案:

解决一:

SQL语句中不要使用太复杂的关联多表的查询;使用explain“执行计划"对SQL语句进行分析,对于有全表扫描和全表锁定的SQL语句,建立相应的索引进行优化

解决二:

  • 在同一个事务中,尽可能做到一次锁定所需要的所有资源

  • 按照id对资源排序,然后按顺序进行处理

==================================

  • 共享锁转换为排他锁

事务A 查询一条纪录,然后更新该条纪录;此时事务B 也更新该条纪录,这时事务B 的排他锁由于事务A 有共享锁,必须等A 释放共享锁后才可以获取,只能排队等待。事务A 再执行更新操作时,此处发生死锁,因为事务A 需要排他锁来做更新操作。但是,无法授予该锁请求,因为事务B 已经有一个排他锁请求,并且正在等待事务A 释放其共享锁。

事务A: 
select * from dept where deptno=1 lock in share mode; //共享锁,1
update dept set dname='java' where deptno=1;//排他锁,3
事务B: 
update dept set dname='Java' where deptno=1;//由于1有共享锁,没法获取排他锁,需等待,2

解决方案:

  • 对于按钮等控件,点击立刻失效,不让用户重复点击,避免引发同时对同一条记录多次操作;

  • 使用乐观锁进行控制。乐观锁机制避免了长事务中的数据库加锁开销,大大提升了大并发量下的系统性能。需要注意的是,由于乐观锁机制是在我们的系统中实现,来自外部系统的用户更新操作不受我们系统的控制,因此可能会造成脏数据被更新到数据库中;

死锁排查:

  • 查看死锁日志

通过show engine innodb status\G命令查看近期死锁日志信息。

使用方法:1、查看近期死锁日志信息;2、使用explain查看下SQL执行计划

  • 查看锁状态变量

通过**show status like’innodb_row_lock%‘**命令检查状态变量,分析系统中的行锁的争夺情况

Innodb_row_lock_current_waits:当前正在等待锁的数量

Innodb_row_lock_time:从系统启动到现在锁定总时间长度

Innodb_row_lock_time_avg: 每次等待锁的平均时间

Innodb_row_lock_time_max:从系统启动到现在等待最长的一次锁的时间

Innodb_row_lock_waits:系统启动后到现在总共等待的次数

如果等待次数高,而且每次等待时间长,需要分析系统中为什么会有如此多的等待,然后着手定制优化。

mysql集群架构

概念

实现高可用的方案有以下几种架构模式:

  • 主从模式

简单灵活,能满足多种需求。比较主流的用法,但是写操作高可用需要自行处理。

  • 双主模式

互为主从,有双主双写、双主单写两种方式,建议使用双主单写

centos虚拟机安装mysql

cd /usr/local/src
tar -xvf mysql-5.7.28-1.el7.x86_64.rpm-bundle.tar

## centos自带 mariadb,查询并删除
rpm -qa|grep mariadb
rpm -e mariadb-libs-5.5.41-2.el7_0.x86_64 --nodeps

## i表示安装,v表示显示安装过程,h表示显示进度
## 安装common包
rpm -ivh mysql-community-common-5.7.28-1.el7.x86_64.rpm
## 安装lib包
rpm -ivh mysql-community-libs-5.7.28-1.el7.x86_64.rpm
## 安装libs-compat包
rpm -ivh mysql-community-libs-compat-5.7.28-1.el7.x86_64.rpm
## 安装client包
rpm -ivh mysql-community-client-5.7.28-1.el7.x86_64.rpm
## 安装server包
rpm -ivh mysql-community-server-5.7.28-1.el7.x86_64.rpm
## 安装devel包
rpm -ivh mysql-community-devel-5.7.28-1.el7.x86_64.rpm
## 初始化mysql
mysqld --initialize --user=mysql
## 查询密码
cat /var/log/mysqld.log
## 获取临时密码
ZTl%tXzk#57
## 开机自启
systemctl start mysqld.service
## 查询状态是否启动
systemctl status mysqld.service
##登录mysql
mysql -uroot -p

## 进入mysql 设置 密码
set password=password('root');
## mysql授权外部链接
GRANT REPLICATION SLAVE ON *.*  TO  'root'@'%'  identified by 'root';
GRANT all privileges ON *.*  TO  'root'@'%'  identified by 'root';
##刷新
flush privileges;
## 退出 关闭防火墙
exit#mysql内执行
systemctl stop iptables;
systemctl stop firewalld;
## 禁用防火墙
systemctl disable firewalld.service

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UGsspwua-1599925202788)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\安装mysql.png)

mysql主从复制

MySQL主从模式是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQL 默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,从节点可以复制主数据库中的所有数据库,或者特定的数据库,或者特定的表。

mysql主从复制用途:

  • 实时灾备,用于故障切换(高可用)

  • 读写分离,提供查询服务(读扩展)

  • 数据备份,避免影响业务(高可用)

主从复制整体分为以下三个步骤

  • 主库将数据库的变更操作记录到Binlog日志文件中

  • 从库读取主库中的Binlog日志文件信息写入到从库的Relay Log中继日志中

  • 从库读取中继日志信息在从库中进行Replay,更新从库数据信息

搭建流程

主服务器master

从服务器 slave

主服务器
  • 从库服务器能连通主库

  • 主库开启binlog日志(设置log-bin参数)

  • 主从server-id不同

  1. 配置etc下的my.cnf(my.ini)文件
#开启binlog日期
log_bin=mysql-bin 
server-id=1
## 同步日志
sync-binlog=1 
## 忽略一些库
binlog-ignore-db=performance_schema
binlog-ignore-db=informance_schema
binlog-ignore-db=sys
## 同步一些表
binlog-do-db=xxx(表名)
  1. 修改后重启mysql
systemctl restart mysqld
  1. 授权

进入mysql的命令行

GRANT REPLICATION SLAVE ON *.*  TO  'root'@'%'  identified by 'root';
GRANT all privileges ON *.*  TO  'root'@'%'  identified by 'root';
//刷新
flush privileges;
  1. 查询主库状态
show master status

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bct6bTNd-1599925202789)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\msterStatus.png)

从服务器
  1. 配置etc下的my.cnf(my.ini)文件
## 同步日志
sync-binlog=1 
## 中继日志
relay_log=mysql-relay-bin
##只读属性
read_only=1
  1. 修改后重启mysql
systemctl restart mysqld
  1. 清楚库状态
show master status ## 从库中如果有值,说明之前做过
stop slave; ##先停步slave服务线程,这个是很重要的,
  1. 同步复制进入mysql的命令行
change master to master_host='192.168.182.128',master_port=3306,master_user='root',master_password='root',master_log_file='nysql_bin.000002',master_log_pos=154;
  1. 查询从库状态
show master status \G; ## 从库中如果有值,说明之前做过
start slave;

问题

mysql主从复制存在的问题:

  • 主库宕机后,数据可能丢失

  • 从库只有一个SQL Thread,主库写压力大,复制很可能延时

解决方法:

  • 半同步复制—解决数据丢失的问题

  • 并行复制----解决从库复制延迟的问题

半同步复制

semi-sync意思是MASTER只需要接收到其中一台SLAVE的返回信息,就会commit;否则需等待直至切换成异步再提交

主库安装semi

进入mysql 安装配置semi

##是否支持动态加载
select @@have_dynamic_loading;
##开启插件
show plugins;
##安装semi
install plugin rpl_semi_sync_master soname 'semisync_master.so';
##查看
show variables like '%semi%';
//============下面部分无视
##开启semi
set global rpl_semi_sync_master_enabled=1;
##1000毫秒
set global rpl_semi_sync_master_timeout=1000;

从库安装semi

进入mysql 安装配置semi

##安装semi
install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
##查看
show variables like '%semi%';
##开启semi
set global rpl_semi_sync_master_enabled=1;
## 重启
stop slave;
start slave;
全同步复制

为了兼容MySQL 5.6基于库的并行复制,5.7引入了新的变量slave-parallel-type,其可以配置的值有:

DATABASE(默认值,基于库的并行复制方式)、LOGICAL_CLOCK(基于组提交的并行复制方式)。

show variables like '%binlog_group%';
## 先关闭
stop slave;
## 提交的时间
set global binlog_group_commit_sync_delay=1000;
## 提交的组数量
set global binlog_group_commit_sync_no_delay_count=100;


show variables like '%slave%';
## 并行组提交方式
set global slave_parallel_type=LOGICAL_CLOCK;
## 线程数
set global slave_parallel_workers=8;

show variables like '%relay_log%';
## 转发的日志回复  
set global relay_log_recovery=1;
## 存储方式
set relay_log_info_repository='table';

直接写配置文件与set global的区别

set global后重启服务,配置属性消失

写到my.ini文件中,不会消失

配置etc下的my.ini文件

relay_log_recovery=1
slave_parallel_type=LOGICAL_CLOCK
slave_parallel_workers=8
relay_log_info_repository=table;
master_info_repository=table;

#重启
systemctl restart mysqld
# 查询
show variables like '%relay_log%';
并行复制配置与调优
  • binlog_transaction_dependency_history_size 用于控制集合变量的大小
  • binlog_transaction_depandency_tracking 控制binlog文件中事务之间的依赖关系
  • transaction_write_set_extraction 用于控制事务的检测算法
  • master_info_repository 性能提升
  • slave_parallel_workers SQL线程
  • slave_preserve_commit_order 实现更小粒度的并行复制

slave-parallel-type=LOGICAL_CLOCK 
slave-parallel-workers=16 
slave_pending_jobs_size_max = 2147483648 
slave_preserve_commit_order=1 
master_info_repository=TABLE 
relay_log_info_repository=TABLE 
relay_log_recovery=ON

读写分离

mysql-proxy

解压 mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz文件

创建配置文件

vim /etc/mysql-proxy.cnf
user=root

admin-username=root

admin-password=root

#代理的主机IP名
proxy-address=192.168.95.134:4040
#指定主库的ip
proxy-backend-address=192.168.95.130:3306
#指定读库(从库)的ip
proxy-read-only-backend-addresses=192.168.95.132:3306,192.168.95.133:3306
#采用lua脚本管理
proxy-lua-script=/share/doc/mysql-proxy/rw-spiltting.lua
#log路径
log-file=/var/log/mysql-proxy.log
log-level=debug
#进程的运行模式
daemon=true
#是否重启
keepalive=true

修改权限

chmod 660 /etc/mysql-proxy.cnf

修改rw-spilttind.lua脚本

#连接池
#最小链接 4改成1
min_idle_connections = 1
min_idle_connections = 8

启动mysql-proxy

./mysql-proxy --defaults-file=/etc/mysql-proxy.cnf

双主复制

配置master1

进入master1的etc/my.cnf

#开启binlog日期
log_bin=mysql-bin 
server-id=1
## 同步日志
sync-binlog=1 
## 忽略一些库
binlog-ignore-db=performance_schema
binlog-ignore-db=informance_schema
binlog-ignore-db=sys
## 同步一些表
binlog-do-db=xxx(表名)
## relay_log功能
relay_log=mysql-relay-bin
##从服务日志更新
log_slave_updates=1
##1.3.5.7.9
##指定自动递增
auto_increment_offset=1
##增量
auto_increment_increment=2

重启mysql

systemctl restart mysqld

进入mysql,查询,指定授权(授权过,直接取消)

show master status
## 授权
GRANT REPLICATION SLAVE ON *.*  TO  'root'@'%'  identified by 'root';
GRANT all privileges ON *.*  TO  'root'@'%'  identified by 'root';
##刷新
flush privileges;

配置master2

进入master2的etc/my.cnf

#开启binlog日期
log_bin=mysql-bin 
server-id=3
## 同步日志
sync-binlog=1 
## 忽略一些库
binlog-ignore-db=performance_schema
binlog-ignore-db=informance_schema
binlog-ignore-db=sys

## relay_log功能
relay_log=mysql-relay-bin
##从服务日志更新
log_slave_updates=1
##2,4,6,8,10
##指定自动递增
auto_increment_offset=2
##增量
auto_increment_increment=2

重启mysql

systemctl restart mysqld

授权

## 授权
GRANT REPLICATION SLAVE ON *.*  TO  'root'@'%'  identified by 'root';
GRANT all privileges ON *.*  TO  'root'@'%'  identified by 'root';
## 刷新
flush privileges;

查询状态

show master status

指定复制操作

master1指定master2(fileID,Position)

change master to master_host='59.151.15.36',master_port='3306',master_user='root',master_password='root',master_log_file=' mysql-bin.000016 ',master_log_pos=107;

## 启动slave
start slave;
## 查询状态
show slave status\G

master2指定master1(fileID,Position)

change master to master_host='59.151.15.36',master_port='3306',master_user='root',master_password='root',master_log_file=' mysql-bin.000016 ',master_log_pos=107;

## 启动slave
start slave;
## 查询状态
show slave status\G

MMM架构

MMM(Master-Master Replication Manager for MySQL)是一套用来管理和监控双主复制,支持双主故障切换 的第三方软件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i1dYKjRO-1599925202790)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\mmm.png)

MMM 包含writer和reader两类角色,分别对应写节点和读节点。

  • 当 writer节点出现故障,程序会自动移除该节点上的VIP

  • 写操作切换到 Master2,并将Master2设置为writer将所有Slave节点会指向Master2

MHA架构

MHA(Master High Availability)是一套比较成熟的 MySQL 高可用方案,也是一款优秀的故障切换和主从提升的高可用软件。

MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)

  • MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。负责检测master是否宕机、控制故障转移、检查MySQL复制状况等。

  • MHA Node运行在每台MySQL服务器上,不管是Master角色,还是Slave角色,都称为Node,是被监控管理的对象节点负责保存和复制master的二进制日志、识别差异的中继日志事件并将其差异的事件应用于其他的slave、清除中继日志

MHA故障处理机制:

  • 把宕机master的binlog保存下来

  • 根据binlog位置点找到最新的slave

  • 用最新slave的relay log修复其它slave

  • 将保存下来的binlog在最新的slave上恢复

  • 将最新的slave提升为master

  • 将其它slave重新指向新提升的master,并开启主从复制

MHA优点:

  • 自动故障转移快

  • 主库崩溃不存在数据一致性问题

  • 性能优秀,支持半同步复制和异步复制

  • 一个Manager监控节点可以监控多个集群

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ort5wtfD-1599925202792)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\mha.png)

主备切换策略

主备切换是指将备库变为主库,主库变为备库,有可靠性优先可用性优先两种策略。

主备延迟问题

主备延迟是由主从数据同步延迟导致的,与数据同步有关的时间点主要包括以下三个:

  • 主库 A 执行完成一个事务,写入 binlog,我们把这个时刻记为 T1;

  • 之后将binlog传给备库 B,我们把备库 B 接收完 binlog 的时刻记为 T2;

  • 备库 B 执行完成这个binlog复制,我们把这个时刻记为 T3。

分库分表

使用分库分表时,主要有垂直拆分和水平拆分两种拆分模式,都属于物理空间的拆分。

垂直拆分:由于表数量多导致的单个库大。将表拆分到多个库中。

水平拆分:由于表记录多导致的单个库大。将表记录拆分到多个表中。

垂直拆分

垂直拆分是将表按库进行分离,或者修改表结构按照访问的差异将某些列拆分出去。

  • 垂直分库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-94T8gQo1-1599925202792)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\垂直拆分.png)

  • 垂直分表

一个表中字段过多,还有有些字段经常使用,有些字段不经常使用,或者还有text等字段信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s9YySdU9-1599925202795)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\垂直分表.png)

垂直拆分优点

  • 拆分后业务清晰,拆分规则明确;

  • 易于数据的维护和扩展;

  • 可以使得行数据变小,一个数据块 (Block) 就能存放更多的数据,在查询时就会减少 I/O 次数;

  • 可以达到最大化利用 Cache 的目的,具体在垂直拆分的时候可以将不常变的字段放一起,将经常改变的放一起;

  • 便于实现冷热分离的数据表设计模式。

垂直拆分缺点

  • 主键出现冗余,需要管理冗余列;

  • 会引起表连接 JOIN 操作,可以通过在业务服务器上进行 join 来减少数据库压力,提高了系统的复杂度;

  • 依然存在单表数据量过大的问题;

  • 事务处理复杂。

水平拆分

水平拆分又称为横向拆分。 相对于垂直拆分,它不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个库或表中,每个表仅包含数据的一部分。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v2d2XdHf-1599925202796)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\水平拆分.png)

下图所示

区分

水平拆分:解决表中记录过多问题。

垂直拆分:解决表过多或者是表字段过多问题

水平拆分重点考虑拆分规则:例如范围、时间或Hash算法等。

水平拆分优点

  • 拆分规则设计好,join 操作基本可以数据库做;

  • 不存在单库大数据,高并发的性能瓶颈;

  • 切分的表的结构相同,应用层改造较少,只需要增加路由规则即可;

  • 提高了系统的稳定性和负载能力。

水平拆分缺点

  • 拆分规则难以抽象;

  • 跨库Join性能较差;

  • 分片事务的一致性难以解决;

  • 数据扩容的难度和维护量极大。

  • 日常工作中,我们通常会同时使用两种拆分方式,垂直拆分更偏向于产品/业务/功能拆分的过程,在技术上我们更关注水平拆分的方案。

主键策略

  • UUID

UUID是通用唯一识别码(Universally Unique Identififier)的缩写。

UUID在生成时使用到了以太网卡地址、纳秒级时间、芯片ID码和随机数等信息,目的是让分布式系统中的所有元素都能有唯一的识别信息

使用UUID做主键,可以在本地生成,没有网络消耗,所以生成性能高。但是UUID比较长,没有规律性,耗费存储空间

  • SNOWFLAKE(雪花ID)

SnowFlake是Twitter开源的分布式ID生成算法,结果是一个long型的ID,long型是8个字节,64-bit。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号,最后还有一个符号位,永远是0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AFXPsBps-1599925202797)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\雪花ID.png)

分片策略

将一个数据库打碎成多个的过程就叫做分片,分片是属于横向扩展方案。

数据库扩展方案:

  • 横向扩展:一个库变多个库,加机器数量

  • 纵向扩展:一个库还是一个库,优化机器性能,加高配CPU或内存

  • 基于范围分片

根据特定字段的范围进行拆分,比如用户ID、订单时间、产品价格等。例如:

{[1 - 100] => Cluster A, [101 - 199] => Cluster B}

优点:新的数据可以落在新的存储节点上,如果集群扩容,数据无需迁移。

缺点:数据热点分布不均,数据冷热不均匀,导致节点负荷不均。

  • 哈希取模分片

假设有n台设备,编号为0 ~ n-1,通过Hash(Key) % n就可以确定数据所在的设备编号。该模式也称为离散分片

  • 一致性哈希分片

一致性Hash是将数据按照特征值映射到一个首尾相接的Hash环上,同时也将节点(按照IP地址或者机器名Hash)映射到这个环上。对于数据,从数据在环上的位置开始,顺时针找到的第一个节点即为数据的存储节点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HWvw8o80-1599925202798)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\一致性哈希.png)

扩容方案

当系统用户进入了高速增长期时,即便是对数据进行分库分表,但数据库的容量,还有表的数据量也总会达到天花板。当现有数据库达到承受极限时,就需要增加新服务器节点数量进行横向扩容。

  • 停机扩容

优点:简单

缺点:

​ 停止服务,缺乏高可用

​ 程序员压力山大,需要在指定时间完成

​ 如果有问题没有及时测试出来启动了服务,运行后发现问题,数据会丢失一部分,难以回滚。

适用场景:

​ 小型网站

​ 大部分游戏

​ 对高可用要求不高的服务

  • 平滑扩容

平滑扩容就是将数据库数量扩容成原来的2倍,比如:由2个数据库扩容到4个数据库

平滑扩容方案能够实现n库扩2n库的平滑扩容,增加数据库服务能力,降低单库一半的数据量。其核心

原理是:成倍扩容,避免数据迁移。

优点:

​ 扩容期间,服务正常进行,保证高可用

​ 相对停机扩容,时间长,项目组压力没那么大,出错率低

​ 扩容期间遇到问题,随时解决,不怕影响线上服务

​ 可以将每个数据库数据量减少一半

缺点:

​ 程序复杂、配置双主同步、双主双写、检测数据同步等

​ 后期数据库扩容,比如成千上万,代价比较高

适用场景:

​ 大型网站

​ 对高可用要求高的服务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-14aoaZJs-1599925202802)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\平滑扩容.png)

问题

1.虚拟机centos7执行ip addr命令看不到ip地址?

方案一:

#切换到root用户
su root
#编辑修改文件
vi /etc/sysconfig/network-scripts/ifcfg-eno16777736
ONBOOT=no #修改成ONBOOT=yes
#强制保存
:wq!
#重启网络服务
service netword restart

方案二:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCZ0U7Wa-1599925202804)(D:\拉钩笔记\lagouNode\4Stage\Mysql(上)]\pic\虚拟机.png)

https://blog.csdn.net/weixin_43343006/article/details/100094624?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

https://blog.csdn.net/liunian0714/article/details/78560473

2.上传文件:permission is not allowed?

#切换到root用户
su root
#给目录赋权限
chmod 777 src

3.克隆虚拟机黑屏无法启动

  1. 在克隆完虚拟机以后,启动之前,再虚拟机属性->适配器-.从新生成maca地址

  2. 在首选项中,把虚拟机打印 打开

(主要解决方式)https://blog.csdn.net/wpw2000/article/details/108121096

https://blog.csdn.net/Jarbein/article/details/91851350

https://blog.csdn.net/fengy_jav/article/details/104458930

4.虚拟机克隆修改网关IP

cd /etc/sysconfig/network-scripts/
##生成UUid
uuidgen

单词

Parser 解析

Optimizer 查询优化器

Engines 引擎

Pluggable Storage Engines 存储引擎层

partition 分割,隔断

dependent 依赖

identical 相同的

Pessimistic 悲观的

relay 转发

dynamic 动态的

parallel 并行,平行

recovery 恢复,回复

trace 追踪,发现

问题:虚拟机centos7执行ip addr命令看不到ip地址

fg-eno16777736
ONBOOT=no #修改成ONBOOT=yes
#强制保存
:wq!
#重启网络服务
service netword restart

方案二:

[外链图片转存中...(img-PCZ0U7Wa-1599925202804)]\pic\虚拟机.png)


> https://blog.csdn.net/weixin_43343006/article/details/100094624?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

> https://blog.csdn.net/liunian0714/article/details/78560473

## 2.上传文件:permission is not allowed?

```shell
#切换到root用户
su root
#给目录赋权限
chmod 777 src

3.克隆虚拟机黑屏无法启动

  1. 在克隆完虚拟机以后,启动之前,再虚拟机属性->适配器-.从新生成maca地址

  2. 在首选项中,把虚拟机打印 打开

(主要解决方式)https://blog.csdn.net/wpw2000/article/details/108121096

https://blog.csdn.net/Jarbein/article/details/91851350

https://blog.csdn.net/fengy_jav/article/details/104458930

4.虚拟机克隆修改网关IP

cd /etc/sysconfig/network-scripts/
##生成UUid
uuidgen

https://blog.csdn.net/qq_35461394/article/details/92788603?utm_medium=distribute.pc_relevant.none-task-blog-title-6&spm=1001.2101.3001.4242

https://blog.csdn.net/weixin_30426065/article/details/102344340?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

https://blog.csdn.net/qq_39192827/article/details/85952823

待测试

https://blog.csdn.net/woSHIxiaobai2/article/details/104222073?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

https://www.cnblogs.com/Guugle/p/12982803.html

单词

Parser 解析

Optimizer 查询优化器

Engines 引擎

Pluggable Storage Engines 存储引擎层

partition 分割,隔断

dependent 依赖

identical 相同的

Pessimistic 悲观的

relay 转发

dynamic 动态的

parallel 并行,平行

recovery 恢复,回复

trace 追踪,发现

问题:虚拟机centos7执行ip addr命令看不到ip地址

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值