某文件占10个磁盘块处理读取或写入请求的时间百分比进程与性能里不一样,

机械盘不是系统盘,所以肯定不是自动更新导致的卡100%占用。虽然硬盘一直在100%占用,但是数据传输速率表可以看到硬盘其实没有传输多少数据(间隔很久才有一次),但是访问延迟超过1秒(正常应该低于200ms)。综上,判断为机械硬盘出现坏道,或者SATA接口发生CRC错误。现在固态硬盘已经很便宜了,如果可以的话,先把机械盘拔掉正常使用即可。

如果访问固态里的文件正常,只有机械里的卡,那就是机械硬盘有坏道了,只能更换


· TA获得超过1.9万个赞

任务管理器进程选项里面看看是哪项进程读写硬盘导致100%的

WIN10系统?没救,除非换固态硬盘
占用磁盘的是windows自动更新,就算是手动关闭了也会自动打开

除非你换固态硬盘,否则这个问题无解

三星的固态盘是很不错的。
不过,三星的固态盘自带的程序有时候会有兼容性问题。如果你装了它有问题,那就卸载了。
还有就是系统最好慢安装微软的原版系统,尽量不要用ghost或迁移旧系统。

下载百度知道APP,抢鲜体验

使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。

I/O 的概念,从字义来理解就是输入输出。操作系统从上层到底层,各个层次之间均存在 I/O。比如,CPU 有 I/O,内存有 I/O, VMM 有 I/O, 底层磁盘上也有 I/O,这是广义上的 I/O。通常来讲,一个上层的 I/O 可能会产生针对磁盘的多个 I/O,也就是说,上层的 I/O 是稀疏的,下层的 I/O 是密集的。我们通常所说的IO都是指磁盘等设备IO。

I/O设备一般包括机械部件和电子部件两个部分:电子部件-设备控制器(适配器)和机械部件-设备本身。控制器是插在电路板上的一块芯片或一组芯片,这块电路板物理地控制设备。它从操作系统接收命令,例如,从设备读数据,并且完成数据的处理。

I/O设备的另一个部分是实际设备的自身。设备本身有个相对简单的接口,这是因为接口既不能做很多工作,又已经被标准化了。例如,标准化后任何一个SATA磁盘控制器就可以适配任一种SATA磁盘。

现在SATA是很多计算机的标准硬盘接口。由于实际的设备接口隐藏在控制器中,所以,操作系统看到的是对控制器的接口,这个接口可能和设备接口有很大的差别。

每类设备控制器都是不同的,所以,需要不同的软件进行控制。专门与控制器对话,发出命令并接收响应的软件,称为设备驱动程序(device driver)。每个控制器厂家必须为所支持的操作系统提供相应的设备驱动程序。例如,一台扫描仪会配有用于OSX、Windows 7、Windows 8以及Linux的设备驱动程序。

为了能够使用设备驱动程序,必须把设备驱动程序装人操作系统中,这样它可在核心态运行。

字符设备指能够像字节流串行顺序依次进行访问的设备,对它的读写是以字节为单位。字符设备的上层没有磁盘文件系统,所以字符设备的file_operations成员函数就直接由字符设备驱动提供(一般字符设备都会实现相应的fops集),因此file_operations 也就成为了字符设备驱动的核心。

  • 一个字节一个字节读写的设备

  • 读取数据需要按照先后数据(顺序读取)

  • 每个字符设备在/dev目录下对应一个设备文件,linux用户程序通过设备文件(或称设备节点)来使用驱动程序操作字符设备。

  • 常见的字符设备有鼠标、键盘、串口、控制台等

块设备以数据块的形式存放数据,如NAND Flash以页为单位存储数据,并采用mount方式挂载块设备。

块设备必须能够随机存取(random access),字符设备则没有这个要求。

块设备除了给内核提供和字符设备一样的接口外,还提供了专门面向块设备的接口,块设备的接口必须支持挂装文件系统,通过此接口,块设备能够容纳文件系统,因此应用程序一般通过文件系统来访问块设备上的内容,而不是直接和设备打交道。

对于块设备而言,上层ext2,jiffs2,fat等文件系统会 实现针对VFS的file_opertations成员函数,所以设备驱动层将看不到file_opeations的存在。磁盘文件系统和设备驱动会将对磁盘上文件的访问转换成对磁盘上柱面和扇区的访问。

  • 数据以固定长度进行传输,比如512K

  • 从设备的任意位置(可跳)读取,但实际上,块设备会读一定长度的内容,而只返回用户要求访问的内容,所以随机访问实际上还是读了全部内容。

  • 块设备包括硬盘、磁盘、U盘和SD卡等

  • 每个块设备在/dev目录下对应一个设备文件,linux用户程序可以通过设备文件(或称设备节点)来使用驱动程序操作块设备。

  • 块设备可以容纳文件系统,所以一般都通过文件系统来访问,而不是/dev设备节点。

虽然在Linux系统存在一句话叫一切皆文件,无论是各种文本文件还是具体的硬件设备(硬件由设备文件来实现相应)。但是网络设备在Linux内核中却是唯一不体现一切皆设备思想的驱动架构,因为网络设备使用套接字来实现网数据的接受和发送。

网络设备驱动不同于字符设备和块设备,不在/dev下以文件节点代表,而是通过单独的网络接口来代表。

  • 网络接口没有像字符设备和块设备一样的设备号和/dev设备节点,只有接口名,如eth0,eth1

上图概括了一次磁盘 write 操作的过程,假设文件已经被从磁盘中读入了 page cache 中

  1. 一个用户进程通过 write() 系统调用发起写请求

  2. 文件系统层将每一个 block buffer 存放为一个 bio 结构体,并向块设备层提交一个写请求

  3. 块设备层从上层接受到请求,执行 IO 调度操作,并将请求放入IO 请求队列中

  4. 设备驱动(如 SCSI 或其他设备驱动)完成写操作

  5. 磁盘设备固件执行对应的硬件操作,如磁盘的旋转,寻道等,数据被写入到磁盘扇区中

block layer 处理 bio 请求,并将这些请求链接成一个队列,称作 IO 请求队列,这个连接的操作就称作 IO 调度(也叫 IO elevator 即电梯算法).

IO 调度器的总体目标是减少磁盘的寻道时间(因此调度器都是针对机械硬盘进行优化的),IO 调度器通过两种方式来减少磁盘寻道:合并和排序。

合并即当两个或多个 IO 请求的是相邻的磁盘扇区,那么就将这些请求合并为一个请求。通过合并请求,多个 IO 请求只需要向磁盘发送一个请求指令,减少了磁盘的开销。

排序就是将不能合并的 IO 请求,根据请求磁盘扇区的顺序,在请求队列中进行排序,使得磁头可以按照磁盘的旋转顺序的完成 IO 操作,可以减小磁盘的寻道次数。

调度器的算法和电梯运行的策略相似,因此 IO 调度器也被称作 IO 电梯( IO Elevator )。由于对请求进行了重排,一部分的请求可能会被延迟,以提升整体的性能。

读文件函数调用流程(Linux2.6)

以经过页缓存读取一个ext2文件系统上的普通文件的流程为例,看一看IO子系统的各个层级都实现了什么功能。IO系统架构分层如下:

首先是应用程序发起系统调用,进入虚拟文件系统层。

  • dentry : 联系了文件名和文件的 i 节点
  • inode : 文件 i 节点,保存文件标识、权限和内容等信息
  • file : 保存文件的相关信息和各种操作文件的函数指针集合

每秒的输入输出量(或读写次数),也就是在一秒内,磁盘进行多少次 I/O 读写。是衡量磁盘性能的主要指标之一。

指单位时间内可以成功传输的数据数量。即磁盘写入加上读出的数据的大小。吞吐量等于IOPS乘以每次IO大小。

使用率,是指磁盘处理I/O的时间百分比,也就是一个时间段内磁盘用于处理IO的时间占这段时间的比例。过高的使用率(比如超过80% ) , 通常意味着磁盘I/O存在性能瓶颈。

饱和度,是指磁盘处理I/O的繁忙程度,也就是能否接受新的IO请求。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为100%时,磁盘无法接受新的I/O请求。

响应时间,是指I/O请求从发出到收到响应的间隔时间。

性能监测工具提供的指标

磁盘I/O使用率、IOPS、 吞吐量、响应时间、I/O平均大小以及等待队列长度
进程I/O大小以及I/O延迟
磁盘I/O使用率、IOPS 、吞吐量以及响应时间
磁盘I/O使用率、IOPS以及吞吐量
按I/O大小对进程排序
目录项、索引节点以及文件系统的缓存
目录项、索引节点以及文件系统的缓存
页缓存和可回收Slab缓存
磁盘的IOPS、吞吐量以及延迟!
进程IOPS、IO大小以及IO延迟
跟踪进程的块设备I/O大小
跟踪进程块I/O并按I/O大小排序
跟踪进程的I/O系统调用
跟踪内核中的I/O事件
磁盘空间和索引节点使用量和剩余量
文件系统的挂载路径以及挂载参数
目录占用的磁盘空间大小
显示和设置文件系统参数

iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视。它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况。这些指标实际上来自 /proc/diskstats。

每秒发送给磁盘的读请求数
每秒发送给磁盘的写请求数
每秒从磁盘读取的数据量
每秒向磁盘写入的数据量
%rrqm表示合并读请求的百分比
%wrqm表示合并写请求的百分比
读请求处理完成等待时间 包括队列中的等待时间和设备实际处理的时间,单位为毫秒
写请求处理完成等待时间 包括队列中的等待时间和设备实际处理的时间,单位为毫秒
处理I/O请求所需的平均时间(不包括等待时间) 单位为毫秒。注意这是推断的数据,并不保证完全准确
磁盘处理I/O的时间百分比 即使用率,由于可能存在并行I/O,100%并不一定表明磁盘I/O饱和

关于%util,举个简单的例子,某硬盘处理单个I/O需要0.1秒,有能力同时处理10个I/O请求,那么当10个I/O请求依次顺序提交的时候,需要1秒才能全部完成,在1秒的采样周期里%util达到100%;而如果10个I/O请求一次性提交的话,0.1秒就全部完成,在1秒的采样周期里%util只有10%。可见,即使%util高达100%,硬盘也仍然有可能还有余力处理更多的I/O请求,即没有达到饱和状态。

iostat只提供磁盘整体的I/O性能数据,缺点在于 ,并不能知道具体是哪些进程在进行磁盘读写。要观察进程的I/O情况,你还可以使用pidstat和iotop这两个工具。

从pidstat的输出你能看到,它可以实时查看每个进程的I/O情况,包括下面这些内容。

每秒发出的写请求数据大小( kB_wr/s ),单位是KB。 块I/O延迟(iodelay) ,包括等待同步块I/O和换入块I/O结束的时间,单位是时钟周期。

除了可以用pidstat实时查看,iotop可以按照I/O 大小对进程排序,然后找到I/O较大的那些进程。

上图为按照磁盘写速度进行排序的情况。

从这个输出,你可以看到,前两行分别表示,进程的磁盘读写大小总数和磁盘真实的读写大小总数。因为缓存、缓冲区、I/O 合并等因素的影响,它们可能并不相等。

剩下的部分,则是从各个角度来分别表示进程的1/O情况,包括线程ID、I/O优先级、每秒读磁盘的大小、每秒写磁盘的大小、换入和等待I/O的时钟百分比等。

任何一个系统都有两个指标和性能紧密联系:响应时间和吞吐量。两个很关键的指标则是系统的IO延迟(响应时间)与IO吞吐量。

1个完整的I/O传输,可能会经过以下路径:
进程->虚拟文件系统->具体文件系统(页缓存)->通用块层(加入请求队列)->IO调度层->块设备驱动层->块设备层(操作磁盘)->磁盘

在上述I/O传输途径中消耗的时间就是IO延迟。我们习惯性的把IO的延迟分为以下几部分:

  1. 系统OS等软件配置产生的延迟:异步IO的情况下整个系统的延迟就会比同步IO下好很多。

  2. 硬件延迟:存储的延迟则是自身主控器+硬盘的延迟。存储主控上的缓存都比较大,加上存储厂家对命中率算法持续改进,以往单个硬盘因寻址、旋转产生的IO延迟时间都可以在一定比例上规避。

可以对io延迟做这样的划分:IO延迟时间=常量延迟+变量延迟

常量就是操作系统和数据库参数配置完毕后,那些硬件上的固定延迟加上一定存储命中率下软硬件共同作用产生的延迟时间,变量延迟就是io压力变大时,特别是海量随机小IO请求,导致的延迟变大。

biotop是跟踪块设备I/O事件,并按照总的传输字节大小进行排序的工具,biotop总结了哪些事件执行了磁盘I / O,并打印出在一定时间间隔内,事件发送的进程id,平均等待时间,磁盘设备号等信息。


默认情况下,屏幕每1秒刷新一次,并显示前20个磁盘 消费者,按总KB排序。 打印的第一行是标题,其中包含时间,然后包含/proc/loadavg的内容。 其他bcc工具可用于获取更多详细的内容,例如biolatency 和 biosnoop。

该工具跟踪块设备IO(磁盘IO)的延迟分布情况:

第一列表示延迟的时间范围,单位是微秒;第二列表示有多少事件属于该延迟时间段;第三列表示直方图。

我们通常在块设备层( block device layer)研究存储I/O延迟问题,如上面的biolatency和biotop工具,但是对文件系统进行检测可以提供更多相关的指标来了解应用程序如何受到影响。ext4dist工具针对ext4文件系统,跟踪读取(reads),写入(writes),打开(opens)和同步(fsync),并将其延迟汇总为直方图。


此输出显示读取延迟的双峰分布,其中分别为延迟小于7微秒的较快事件和256至1023微秒之间的较慢事件。 计数列显示有多少事件属于该延迟范围。 较快的事件可能是内存中文件系统高速缓存命中的原因,较慢的事件是从存储设备(磁盘)中读取的。

//获取当前进程pid //即如果当前进程pid不是用户指定的进程pid,函数返回,不进行监测。 //用户没有指定pid,或者用户指定的pid等于当前进程pid,执行下面的函数获取当前的时间,以纳秒为单位。 //将当前进程pid地址作为key,以及当前时间ts地址作为value,更新保存到hash map。
// 按照操作名称,统计操作执行的延迟,pt_regs保存寄存器信息和bpf上下文,op为操作名称,例如read,write
 //定义变量存储开始追踪的时间
 //获取当前系统时间,并且计算出与开始时间的时间增量,保存到delta。
 //删除hash map中当前进程的开始监测时间。
 //时间单位转换,FACTOR占位符表示进制,将纳秒转换为微妙或者毫秒
 //操作名称保存到结构体变量

该函数为在读写函数执行完成,返回的时候,加入的kprobe,结合函数开始执行时记录下的时间与当前的时间,计算出时间差,即本次读写所用的时间。

ext4slower显示ext4的读取,写入,打开和同步操作,其速度低于阈值的所有事件。 该工具与上一个工具不同之处在于,该工具提供了一个延迟时间阈值参数,可以监测到所有延迟低于某个阈值的事件,并打印输出。当然这仅能跟踪常见文件系统操作, 其他文件系统操作(例如,inode操作,getattr()) 不会跟踪。


以上是所有延迟时间大于10毫秒的事件。

此“延迟时间”是从虚拟文件系统(VFS)向文件系统的接口发起操作时算起的,直到完成。 这涵盖了所有内容: 块设备I/O(磁盘I/O),文件系统CPU周期,文件系统锁,请求队列等待时间等。这是对延迟时间的更好衡量。因为应用程序从文件系统读取,而不是通过块设备层接口读取。

回复“000”获取大量电子书

大家好,我是老田,之前写过 JVM、并发编程连环炮。然后有很多小伙伴私下找我就我继续把MySQL的连环炮整理出来,但是由于本人比较懒,又加上最近有点忙,所以拖到了今天才发出来。

有志者,事竟成;破釜沉舟,百二秦关终归楚;苦心人,天不负;卧薪尝胆,三千越甲可吞吴。

本文总结了MySQL的核心知识点,然后结合20个连环炮,可以帮助大家学习MySQL、快速复习MySQL有所帮助。

MySQL的20个连环炮,如下:

1、数据库的三范式是什么?

3、熟悉MySQL的整体架构吗?

5、熟悉哪些日志文件?

7、MySQL优化手段有哪些?

9、事务的四大特性是什么?

10、说说Mysql的四种隔离级别

11、MySQL默认隔离级别是哪个?

12、知道MySQL中哪些锁?

13、并发读写容易带来什么问题?

15、是如何解决幻读的?

17、MySQL索引数据结构有哪几种?

18、有哪些类型的索引呢?

19、Hash和BTree作为MySQL索引,说说你对此有什么想法?

20、索引优化有哪些方式?

21、哪些场景建议创建索引?

22、哪些场景不建议使用索引?

23、用过explain吗?怎么用的?

24、熟悉MySQL锁优化吗?

25、熟悉哪些MySQL调优策略?

需要思维导图的,加微信tj,免费获取

数据库中的所有字段(列)都是单一属性,不可再分的。 这个单一属性由基本的数据类型所构成,如整型、浮点型、字符串等。第一范式是为了保证列的原子性。

数据库中的表不存在非关键字段对任一关键字字段的部分函数依赖  部分函数依赖是指存在着组合关键字中的某一关键字决定非关键字的情况。第二范式在满足了第一范式的基础上,消除非主键列对联合主键的部分依赖

所有非主键属性都只和候选键有相关性,也就是说非主键属性之间应该是独立无关的。第三范式是在满足了第二范式的基础上,消除列与列之间的传递依赖。

CREATE:创建数据库及其对象(如表,索引,视图,存储过程,函数和触发器)  ALTER:改变现有数据库的结构  DROP:从数据库中删除对象  TRUNCATE:从表中删除所有记录,包括为记录分配的所有空间都将被删除  COMMENT:添加注释  RENAME:重命名对象

DCL是数据控制语言(Data Control Language)的简称,  它包含诸如GRANT之类的命令,并且主要涉及数据库系统的权限,权限和其他控件。

GRANT :允许用户访问数据库的权限  REVOKE:撤消用户使用GRANT命令赋予的访问权限


连接层:负责处理客户端的连接以及权限的认证。

服务层:定义有许多不同的模块,包括权限判断,SQL接口,SQL解析,SQL分析优化, 缓存查询的处理以及部分内置函数执行等。MySQL的查询语句在服务层内进行解析、优化、缓存以及内置函数的实现和存储。

引擎层:负责MySQL中数据的存储和提取。MySQL中的服务器层不管理事务,事务是由存储引擎实现的。其中使用最为广泛的存储引擎为InnoDB,其它的引擎都不支持事务。

存储层:负责将数据存储于设备的文件系统中。

Mysql5.5 版本之前默认的存储引擎就是 MyISAM 存储引擎,MySQL 中比较多的系统表使用 MyISAM 存储引擎,系统临时表也会用到 MyISAM 存储引擎,但是在 Mysql5.5 之后默认的存储引擎就是 InnoDB 存储引擎了。原因主要是 MyISAM 是表级锁定,限制了数据库读/写的性能;另外一个原因 MyISAM 不支持事务,基于以上两点,InnoDB

读多写少操作,比如配置表

MySQL的默认事务型引擎、它被用来处理大量短期事务。 除非有非常特别的原因需要使用其他的存储引擎,否则建议优先考虑Inno DB引擎。

提供了大量的特性,包含全文索引,压缩,空间行数等,  但不支持事务和行级锁,有个缺陷就是崩溃后无法恢复

Memory存储引擎使用存在内存中的内容来创建表。每个 Memory表实际只对应一个磁盘文件,格式是 .frm。Memory类型的表访问速度很快,因为其数据是存放在内存中。默认使用 HASH 索引。

Merge存储引擎是一组 MyISAM 表的组合,Merge表本身没有数据,对 Merge类型的表进行查询、更新、删除的操作,  实际上是对内部的 MyISAM 表进行的。Merge表在磁盘上保留两个文件,一个是.frm文件存储表定义、  一个是 .MRG文件存储 Merge表的组成等。

MyISAM:如果应用程序通常以检索为主,只有少量的插入、更新和删除操作,并且对事物的完整性、  并发程度不是很高的话,通常建议选择 MyISAM 存储引擎。

InnoDB:如果使用到外键、需要并发程度较高,数据一致性要求较高,那么通常选择 InnoDB 引擎,  一般互联网大厂对并发和数据完整性要求较高,所以一般都使用 InnoDB 存储引擎。

MEMORY:MEMORY 存储引擎将所有数据保存在内存中,在需要快速定位下能够提供及其迅速的访问。MEMORY 通常用于更新不太频繁的小表,用于快速访问取得结果。

MERGE:MERGE 的内部是使用 MyISAM 表,MERGE 表的优点在于可以突破对单个 MyISAM 表大小的限制,  并且通过将不同的表分布在多个磁盘上, 可以有效地改善 MERGE 表的访问效率。

MySQL中有八种日志文件,分别是:

  • 二进制日志(binlog)

他们分别都有各自的作用,而且默认情况下,服务器的日志文件都位于数据目录(datadir)中。

确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。

事务开始之后就产生redo log,redo log的落盘并不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo log文件中。

关于文件的大小和数量,由以下两个参数配置:

保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读 。undo日志是逻辑格式的日志,在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于redo log的。

关于MySQL5.7之后的独立undo 表空间配置参数如下:

二进制日志(binlog)

用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。用于数据库的基于时间点的还原。

内容是以逻辑格式的日志,可以简单认为就是执行过的事务中的sql语句。

但又不完全是sql语句这么简单,而是包括了执行的sql语句(增删改)反向的信息,也就意味着delete对应着delete本身和其反向的insert;update对应着update执行前后的版本的信息;insert对应着delete和insert本身的信息。

因此可以基于binlog做到类似于oracle的闪回功能,其实都是依赖于binlog中的日志记录。

配置文件的路径为log_bin_basename,binlog日志文件按照指定大小,当日志文件达到指定的最大的大小之后,进行滚动更新,生成新的日志文件。

MySQL 错误日志(error log)记录了 mysqld 启动和停止的相关信息,同时还记录了服务器在启动、停止以及运行期间发生的诊断消息,例如错误、警告和通知等。例如,当 mysqld 发现某个表需要执行自动检查或修复时,它会向错误日志中写入一条消息。

见后面的SQL优化部分。

2、关闭C1E和C States等选项,目的也是为了提升CPU效率;

1、使用SSD或者PCIe SSD设备,至少获得数百倍甚至万倍的IOPS提升;

2、购置阵列卡同时配备CACHE及BBU模块,可明显提升IOPS(主要是指机械盘,SSD或PCIe SSD除外。 同时需要定期检查CACHE及BBU模块的健康状况,确保意外时不至于丢失数据);

3、有阵列卡时,设置阵列写策略为WB,甚至FORCE WB(若有双电保护,或对数据安全性要求不是特别高的话),  严禁使用WT策略。并且闭阵列预读策略,基本上是鸡肋,用处不大;

5、使用机械盘的话,尽可能选择高转速的,例如选用15KRPM,而不是7.2KRPM的盘,不差几个钱的;

1、使用deadline/noop这两种I/O调度器,千万别用cfq(它不适合跑DB类服务);

2、使用xfs文件系统,千万别用ext3;ext4勉强可用,但业务量很大的话,则一定要用xfs;

1、将vm.swappiness设置为5-10左右即可,甚至设置为0(RHEL 7以上则慎重设置为0,除非你允许OOM kill发生),以降低使用SWAP的机会;

4、至于网传的read_ahead_kb、nr_requests这两个参数,我经过测试后,发现对读写混合为主的OLTP环境影响并不大(应该是对读敏感的场景更有效果),不过没准是我测试方法有问题,可自行斟酌是否调整;

1、选择Percona或MariaDB版本的话,强烈建议启用thread pool特性,可使得在高并发的情况下,性能不会发生大幅下降。此外,还有extra_port功能,非常实用, 关键时刻能救命的。还有另外一个重要特色是 QUERY_RESPONSE_TIME 功能,也能使我们对整体的SQL响应时间分布有直观感受;

4、根据实际需要设置innodb_flush_log_at_trx_commit、sync_binlog的值。如果要求数据不能丢失,那么两个都设为1。如果允许丢失一点数据,则可分别设为2和10。而如果完全不用care数据是否丢失的话(例如在slave上,反正大不了重做一次),则可都设为0。这三种设置值导致数据库的性能受到影响程度分别是:高、中、低;

5、设置innodb_file_per_table = 1,使用独立表空间,我实在是想不出来用共享表空间有什么好处了;

8、设置long_query_time = 1,而在5.5版本以上,已经可以设置为小于1了,建议设置为0.05(50毫秒),记录那些执行较慢的SQL,用于后续的分析排查;

1、所有的InnoDB表都设计一个无业务用途的自增列做主键,对于绝大多数场景都是如此,真正纯只读用InnoDB表的并不多,真如此的话还不如用TokuDB来得划算;

2、字段长度满足需求前提下,尽可能选择长度小的。此外,字段属性尽量都加上NOT NULL约束,可一定程度提高性能;

3、尽可能不使用TEXT/BLOB类型,确实需要的话,建议拆分到子表中,不要和主表放在一起,避免SELECT * 的时候读性能太差。

4、读取数据时,只选取所需要的列,不要每次都SELECT *,避免产生严重的随机读问题,尤其是读到一些TEXT/BLOB列;

5、对一个VARCHAR(N)列创建索引时,通常取其50%(甚至更小)左右长度创建前缀索引就足以满足80%以上的查询需求了,没必要创建整列的全长度索引;

6、通常情况下,子查询的性能比较差,建议改造成JOIN写法;

7、多表联接查询时,关联字段类型尽量一致,并且都要有索引;

8、多表连接查询时,把结果集小的表(注意,这里是指过滤后的结果集,不一定是全表数据量小的)作为驱动表;

9、多表联接并且有排序时,排序字段必须是驱动表里的,否则排序列无法用到索引;

10、多用复合索引,少用多个独立索引,尤其是一些基数(Cardinality)太小(比如说,该列的唯一值总数少于255)的列就不要创建独立索引了;

11、类似分页功能的SQL,建议先用主键关联,然后返回结果集,效率会高很多;

1、通常地,单表物理大小不超过10GB,单表行数不超过1亿条,行平均长度不超过8KB,如果机器性能足够,这些数据量MySQL是完全能处理的过来的,不用担心性能问题,这么建议主要是考虑ONLINE DDL的代价较高;

2、不用太担心mysqld进程占用太多内存,只要不发生OOM kill和用到大量的SWAP都还好;

3、在以往,单机上跑多实例的目的是能最大化利用计算资源,如果单实例已经能耗尽大部分计算资源的话,就没必要再跑多实例了;

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完整地执行,要么完全地不执行。

经典的银行转账例子: A从银行转账1w块钱给B,此时数据库会涉及2个最基本的操作:

那么这2个操作是一个整体,要么一起成功,要么一起失败,不会存在只有部分成功。例如A银行卡余额减少1w,但是B银行卡余额没有增加1w,这就会出大问题了。

原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败

事务按照预期生效,数据的状态是预期的状态。

事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,  不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,  接下来即使数据库发生故障也不应该对其有任何影响。

将事务执行结果写入数据库

回滚所有已执行的语句,返回修改之前的数据

  • Grap lock :间隙锁锁定一个范围,但不包括记录本身。
  • Next-key lock:锁定一个范围,包括锁记录本身。

通过写锁,可以做到读读并行,但不能做到读写、写写并行。

  • 自动死锁检测,优先回滚小事务
  • 尽量提交事务,小事务不容易产生死锁
  • 事务中涉及多个表,或者涉及多行记录时,每个事务的操作顺序都要保持一致,降低死锁概率,最好用存储过程
  • 通过索引等方式优化 sql 效率,降低死锁概率(目的是减少扫描 / 锁范围,降低概率)

某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就有几列数据是未查询出来的,如果此时插入和另外一个事务插入的数据,就会报错。

Mysql的四种隔离级别

SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影”

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

在MySQL中,实现了这四种隔离级别,分别有可能产生问题如下所示:

MVCC是为了实现事务的隔离性,通过版本号,避免同一数据在不同事务间的竞争,你 可以把它当成基于多版本号的一种乐观锁。当然,这种乐观锁只在事务级别未提交锁和已提交锁时 才会生效。MVCC最大的好处,相信也是耳熟能详:读不加锁,读写不冲突。在读多写少的OLTP 应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能。

则会对所有读取的行都加锁。

Mysql默认隔离级别是RR(可重复读),是通过“行锁+MVCC”来实现的,正常读时不加锁,写时加锁,MVCC的实现依赖于:三个隐藏字段Read ViewUndo log 来实现。

1、DB_TRX_ID:6个字节,记录每一行最近修改他的事务ID

3、DB_ROW_ID:行标识(隐藏单调自增 ID),大小为 6 字节,如果表没有主键,InnoDB 会自动生成一个隐藏主键,因此会出现这个列。

读快照,可以读取数据的所有版本信息,包括旧版本的信息。其实就是读取MVCC中的read_view,同时结合MVCC进行相对应的控制;

读当前,读取当前数据的最新版本。而且读取到这个数据之后会对这个数据加锁,防止别的事务更改。(分析:在进行写操作的时候就需要进行“当前读”,读取数据记录的最新版本)

RC和RR隔离级别下的快照读和当前读:

  • RC隔离级别下,快照读和当前读结果一样,都是读取已提交的最新;

  • RR隔离级别下,当前读结果是其他事务已经提交的最新结果,快照读是读当前事务之前读到的结果。RR下创建快照读的时机决定了读到的版本。

对于快照读:通过MVCC来进行控制的,不用加锁。按照MVCC中规定的“语法”进行增删改查等操作,以避免幻读。

对于当前读:通过next-key锁(行锁+gap锁)来解决问题的。

索引(在MySQL中也叫“键key”)是存储引擎快速找到记录的一种数据结构。

索引一般以文件形式存储在磁盘上,索引检索需要磁盘I/O操作

索引是数据结构,而且是实现了高级查找算法的数据结构

帮助MySQL高效获取数据的数据结构

在计算机数据结构体系中,为了加速查找的速度,常见的数据结构有两种:

  • Hash哈希结构,例如Java中的HashMap,这种数据组织结构可以让查询/插入/修改/删除的平均时间复杂度都为O(1);
  • Tree 树 结构 , 这种数据组织结构可以让查询/插入/修改/删除的平均时间复杂度都为O(log(n));

Hash这种类型比Tree树这种类型都要更快一些,那为什么MySQL的开发者既使用Hash类型作为索引,又使用了BTREE呢?

确实用Hash索引更快,因为每次都只查询一条信息(重名的雇员姓名也才几条而已),但实际上业务对于SQL的应用场景是:

order by 需要排个序、group by 还要分个组还要比较大小 大于或小于等等

这种情况下如果继续用HASH类型做索引结构,其时间复杂度会从O(1)直接退化为O(n),相当于全表扫描了,而Tree的特性保证了不管是哪种操作,依然能够保持O(log(n))的高效率。

  • 不要在索引列上做任何操作(计算、函数、(自动或手动)类型转  换),会导致索引失效而转向全表扫描
  • 存储引擎不能使用索引中范围条件右边的列
  • 尽量使用覆盖索引(只访问索引的查询(索引列包含查询列)),  减少select *语句
  • mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全  表扫描
  • 字符串不加单引号索引失效

  • where条件中用不到的字段

  • 频繁作为查询字段可以考虑建索引
  • 查询中与其他表关联的字段、外键建立索引
  • 查询中排序的字段,排序后通过索引去访问将大大提升排序性能

模拟优化器执行SQL语句,从而知道MySQL是 如何处理你的SQL语句的,分析  你的查询语句或者表结构的性能瓶颈。

在 select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,  执行查询时,会返回执行计划的信息,而不是执行这条SQL。

  • 数据读取操作的操作类型
  • 每张表有多少行被优化器查询

会在 explain 的基础上额外提供一些查询优化的信息。 紧随其后通过 show warnings 命令可以 得到优  化后的查询语句,从而看出优化器优化了什么

相比 explain 多了个 partitions 字段,  如果查询是基于分区表的话,会显示查询将访问的分区。

id列越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行。

SIMPLE:简单查询。查询不包含子查询和union

UNCACHEABLE SUBQUERY:无法缓存结果的子查询,必须为外部查询的每一行重新计算

<derivedN>:该行是指用于与该行的派生表结果id的值 N。 例如,派生表可以来自FROM子句

MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,  例如从一个索引列里选取最小值可以通过单独索引查找完成。

该表只有一行(如:系统表)。这是const连接类型的特例

该表最多只有一个匹配行,在查询开头读取。因为只有一行,  所以优化器的其余部分可以将此行中列的值视为常量。  const表非常快,因为它们只读一次。SELECT * FROM tbl_name WHERE primary_key=1;

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

该指数合并访问方法检索与多行 range扫描和他们的结果合并到一个。 此访问方法仅合并来自单个表的索引扫描,而不扫描多个表。

只检索给定范围的行,使用一个索引来选择行。

该联接类型与ALL相同,Full Index Scan,index与ALL区别为index类型只遍历索引树。 这通常比ALL快,因为索引文件通常比数据文件小。

一般来说,得保证查询至少达到range级别,最好能达到ref。

表示查询时,可能使用的索引。( MySQL能使用哪个索引在该表中找到行)

索引的长度 ( 使用的字节数 )。如果索引是NULL,则长度为NULL。不损失精确性的情况下,长度越短越好 。key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

使用哪个列或常数,与索引一起被用于从表中查找索引列上的值。 ( 列与索引的比较,表示上述表的连接匹配条件。)  显示索引的哪一列被使用了,如果可能得话,是一个常数。

MySQL认为它执行查询时必须检查的行数。( 扫描出的行数 [估算的行数 ]。)

通过表条件过滤出的行数的百分比估计值。

Mysql执行情况的描述和详细说明。信息 Extra 的常用值说明:

Using filesort:使用了文件进行排序,效率较低

Using index:使用了覆盖索引,效率较高

在工作中,我们发现慢查询一般有 2 个途径,一个是被动的,一个是主动的。估计大部分人都是被动的在处理慢查询,被动的就是当业务人员反馈某个查询界面响应的时间特别长,你才去处理。主动的就是通过通过分析慢查询日志来主动发现执行效率缓慢的 sql 语句,或者通过 information_schema.processlist 实时查询执行缓慢的 sql。

分析慢查询日志的步骤:

  • 直接打开日志进行查看:vi + file 路径

Time:日志记录时间

sql 语句表示执行的具体语句。

查询当前服务器执行超过 30 秒的 sql,可以通过定时任务周期性的来执行这个 sql,就能找到查询缓慢的 sql 语句。

通过以上两种方式找出查询较慢的 sql,进行优化即可。

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

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

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

我要回帖

更多关于 系统启动以后,需要占用()空间 的文章

 

随机推荐