架构:C/S
Connectors: 连接器
- 可供Native C API、JDBC、ODBC、NET、PHP、Perl、Python、Ruby、Cobol等连接mysql;
- 站在编程角度可以理解为连入数据库管理系统的驱动,站在mysql角度称作专用语言对应的链接器;
- 任何链接器连入mysql以后,mysql是单进程多线程模型的,因此,每个用户连接,都会创建一个单独的连接线程;
- 用户连入mysql后,创建一个连接线程,完成之后,能够通过这个连接线程完成接收客户端发来的请求,为其处理请求,构建响应报文并发给客户端;
- 由于是单进程模型,就意味着必须要维持一个线程池,需要一个线程池来管理这众多线程是如何对众多客户端的并发请求,完成并发响应的,组件connection pool就是实现这样功能;
connection pool:线程池
- authentication认证,用户发来的账号密码是否正确要完成认证功能;
- thread reuse线程重用功能,一般当一个用户连接进来以后要用一个线程来响应它,而后当用户退出这个线程有可能并非被销毁,而是把它清理完以后,重新收归到线程池当中的空闲线程中去,以完成所谓的线程重用;
- connection limit 线程池的大小决定了连接并发数量的上限,例如,最多容纳100线程,一旦到达此上限后续到达的连接请求则只能排队或拒绝连接;
- check memory用来检测内存;
- caches实现线程缓存;
- 以上内容都属于线程池的功能.当用户请求之后,通过线程池建立一个用户连接,这个线程一直存在,然后用户就通过这个会话,发送对应的SQL语句到服务器端.
SQL Interface:
- 服务器收到SQL语句后,要对语句完成执行,首先要能理解sql语句需要有sql解释器或叫sql接口sqlinterface就可理解为是整个mysql的外壳,就像shell是linux操作系统的外壳一样;用户无论通过哪种链接器发来的基本的SQL请求,当然,事实上通过native C API也有发过来的不是SQL 请求,而仅仅是对API中的传递参数后的调用;不是SQL语句不过都统统理解为sql语句罢了;对SQL而言分为DDL 和DML两种类型,但是无论哪种类型,提交以后必须交给内核,让内核来运行,在这之前必须要告诉内核哪个是命令,哪个是选项,哪些是参数,是否存在语法错误等等;因此,这个整个SQL 接口就是一个完完整整的sql命令的解释器,并且这个sql接口还有提供完整的sql接口应该具备的功能,比如支持所谓过程式编程,支持代码块的实现像存储过程、存储函数,触发器、必要时还要实现部署一个关系型数据库应该具备的基本组件例如视图等等,其实都在sql interface这个接口实现的;SQL接口做完词法分析、句法分析后,要分析语句如何执行让parser解析器或分析器实现.
Parse分析器:
- parser是专门的分析器,这个分析器并不是分析语法问题的,语法问题在sql接口时就能发现是否有错误了,一个语句没有问题,就要做执行分析,所谓叫查询翻译,把一个查询语句给它转换成对应的能够在本地执行的特定操作;比如说看上去是语句而背后可能是执行的一段二进制指令,这个时候就完成对应的指令,还要根据用户请求的对象,比如某一字段查询内容是否有对应数据的访问权限,或叫对象访问权限;在数据库中库、表、字段、字段中的数据有时都称为object,叫一个数据库的对象,用户认证的通过,并不意味着就能一定能访问数据库上的所有数据,所以说,mysql的认证大概分为两过程都要完成,第一是连入时需要认证账号密码是否正确这是authentication,然后,验证成功后用户发来sql语句还要验证用户是否有权限获取它期望请求获取的数据;这个称为object privilege,这一切都是由parser分析器进行的.
Optimizer路径优化:
- 分析器分析完成之后,可能会生成多个执行树,这意味着为了能够达到访问期望访问到的目的,可能有多条路径都可实现,就像文件系统一样可以使用相对路径也可使用绝对路径;它有多种方式,在多种路径当中一定有一个是最优的,类似路由选择,因此,优化器就要去衡量多个访问路径中哪一个代价或开销是最小的,这个开销的计算要依赖于索引等各种内部组件来进行评估;而且这个评估的只是近似值,同时还要考虑到当前mysql内部在实现资源访问时统计数据,比如,根据判断认为是1号路径的开销最小的,但是众多统计数据表明发往1号路径的访问的资源开销并不小,并且比3号路径大的多,因此,可能会依据3号路径访问;这就是所谓的优化器它负责检查多条路径,每条路径的开销,然后评估开销,这个评估根据内部的静态数据,索引,根域根据动态生成的统计数据来判定每条路径的开销大小,因此这里还有statics;一旦优化完成之后,还要生成统计数据,这就是优化器的作用;如果没有优化器mysql执行语句是最慢的,其实优化还包括一种功能,一旦选择完一条路径后,例如用户给的这个命令执行起来,大概需要100个开销,如果通过改写语句能够达到同样目的可能只需要30个开销;于是,优化器还要试图改写sql语句;所以优化本身还包括查询语句的改写;一旦优化完成,接下来就交给存储引擎完成.
Caches和Buffers:
- 事实上,整个存取过程,尤其是访问比较热点的数据,也不可能每一次当用户访问时或当某SQL语句用到时再临时从磁盘加载到内存中,因此,为了能够加上整个性能,mysql的有些存储引擎可以实现,把频繁访问到的热点数据,统统装入内存,用户访问、修改时直接在内存中操作,只不过周期性的写入磁盘上而已,比如像InnoDB,所以caches和buffers组件就是实现此功能的;MySQL为了执行加速,因为它会不断访问数据,而随计算机来说io是最慢的一环,尤其是磁盘io,所以为了加速都载入内存中管理;这就需要MySQL 维护cache和buffer缓存或缓冲;这是由MySQL 服务器自己维护的;有很多存储引擎自己也有cache和buffer
Pluggable Storage Engines: 数据存储引擎插件
- mysql是插件式存储引擎,它就能够替换使用选择多种不同的引擎(已经100种之多),MyISAM是MySQL 经典的存储引擎之一,InnoDB是由Innobase Oy公司所开发,2006年五月由甲骨文公司并购提供给MySQL的,NDB主要用于MySQL Cluster 分布式集群环境,archive做归档的等等,还有许多第三方开发的存储引擎;存储引擎负责把具体分析的结果完成对磁盘上文件路径访问的转换,数据库中的行数据都是存储在磁盘块上的,因此存储引擎要把数据库数据映射为磁盘块,并把磁盘块加载至内存中;进程实现数据处理时,是不可能直接访问磁盘上的数据的,因为它没有权限,只有让内核来把它所访问的数据加载至内存中以后,进程在内存中完成修改,由内核再负责把数据存回磁盘;对于文件系统而言,数据的存储都是以磁盘块方式存储的,但是,mysql在实现数据组织时,不完全依赖于磁盘,而是把磁盘块再次组织成更大一级的逻辑单位,类似于lvm中的PE或LE的形式;其实,MySQL的存储引擎在实现数据管理时,也是在文件系统之上布设文件格式,对于文件而言在逻辑层上还会再次组织成一个逻辑单位,这个逻辑单位称为mysql的数据块datablock 一般为16k ,对于关系型数据库,数据是按行存储的;一般一行数据都是存储在一起的,因此,MySQL 在内部有一个datablock,在datablock可能存储一行数据,也可能存放了n行数据;将来在查询加载一行数据时,内核会把整个一个数据数据块加载至内存中,而mysql存储引擎,就从中挑出来某一行返回给查询者,是这样实现的;所以整个存储是以datablock在底层为其最终级别的.
File system和Files&Logs:
- 一个数据库提供了3种视图,物理视图就是看到的对应的文件系统存储为一个个的文件,MySQL的数据文件类型,常见的有redo log重做日志,undo log撤销日志,data是真正的数据文件,index是索引文件,binary log是二进制日志文件,error log错误日志,query log查询日志,slow query log慢查询日志,在复制架构中还存在中继日志文件,跟二进制属于同种格式;这是mysql数据文件类型,也就是物理视图;逻辑视图这是在mysql接口上通过存储引擎把mysql文件尤其是data文件,给它映射为一个个关系型数据库应该具备组成部分,比如表,一张表在底层是一个数据文件而已,里面组织的就是datablock,最终映射为磁盘上文件系统的block,然后再次映射为本地扇区的存储,但是整个mysql需要把他们映射成一个二维关系表的形式,需要依赖sql接口以及存储引擎共同实现;所以,把底层数据文件映射成关系型数据库的组件就是逻辑视图;DBA 就是关注内部组件是如何运作的,并且定义、配置其运作模式,而链接器都是终端用户通过链接器的模式进入数据库来访问数据;数据集可能非常大,每一类用户可能只有一部分数据的访问权限,这个时候,最终的终端用户所能访问到的数据集合称作用户视图;
Managment Services & Utilites:
- 为了保证MySQL运作还提供了管理和服务工具,例如:备份恢复工具,安全工具,复制工具,集群服务,管理、配置、迁移、元数据等工具
存储引擎
MyISAM
- MyISAM 引擎特点
- 不支持事务
- 表级锁定
- 读写相互阻塞,写入不能读,读时不能写
- 只缓存索引
- 不支持外键约束
- 不支持聚簇索引
- 读取数据较快,占用资源较少
- 不支持MVCC(多版本并发控制机制)高并发
- 崩溃恢复性较差
- MySQL5.5.5 前默认的数据库引擎
- MyISAM 存储引擎适用场景
- 只读(或者写较少)
- 表较小(可以接受长时间进行修复操作)
- MyISAM 引擎文件
- tbl_name.frm 表格式定义
- tbl_name.MYD 数据文件
- tbl_name.MYI 索引文件
InnoDB
- InnoDB引擎特点
- 行级锁
- 支持事务,适合处理大量短期事务
- 读写阻塞与事务隔离级别相关
- 可缓存数据和索引
- 支持聚簇索引
- 崩溃恢复性更好
- 支持MVCC高并发
- 从MySQL5.5后支持全文索引
- 从MySQL5.5.5开始为默认的数据库引擎
MySQL 中的系统数据库
mysql 数据库
- 是mysql的核心数据库,类似于Sql Server中的master库,主要负责存储数据库的用户、权限设置、关键字等mysql自己需要使用的控制和管理信息
information_schema 数据库
- MySQL 5.0之后产生的,一个虚拟数据库,物理上并不存在information_schema数据库类似与"数据字典",提供了访问数据库元数据的方式,即数据的数据。比如数据库名或表名,列类型,访问权限(更加细化的访问方式)
performance_schema 数据库
- MySQL 5.5开始新增的数据库,主要用于收集数据库服务器性能参数,库里表的存储引擎均为PERFORMANCE_SCHEMA,用户不能创建存储引擎为PERFORMANCE_SCHEMA的表
sys 数据库
- MySQL5.7之后新增加的数据库,库中所有数据源来自performance_schema。目标是把performance_schema的把复杂度降低,让DBA能更好的阅读这个库里的内容。让DBA更快的了解DataBase的运行情况
服务器配置和状态
可以通过mysqld选项,服务器系统变量和服务器状态变量进行MySQL的配置和查看状态【存在即是选项也是变量的配置】
- 注意:
- 其中有些参数支持运行时修改,会立即生效
- 有些参数不支持动态修改,且只能通过修改配置文件,并重启服务器程序生效
- 有些参数作用域是全局的,为所有会话设置
- 有些可以为每个用户提供单独(会话)的设置
mysqld服务器选项
特点
- 服务器选项用横线,不用下划线
- 可以通过配置到文件中持久保存
服务器系统变量
特点
- 分全局变量和局部变量
- 系统变量使用下划线,不使用横线
- 非选项的变量不可以配置到文件中永久保存
服务器状态变量
特点
- 分全局和会话两种
- 状态变量只读,用于保存mysqld运行中的统计数据的变量,不可更改
服务器变量 SQL_MODE
特点
- 对其设置可以完成一些约束检查的工作,可分别进行全局的设置或当前会话的设置
- 根据设置的选项值不同,同样的sql语句可能会有不同的查询结果以及报错方式
- 常见MODE:
- NO_AUTO_CREATE_USER: 禁止GRANT创建密码为空的用户
- NO_ZERO_DATE:在严格模式,不允许使用'0000-00-00'的时间
- ONLY_FULL_GROUP_BY: 对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么将认为这个SQL是不合法的
- NO_BACKSLASH_ESCAPES: 反斜杠"\"作为普通字符而非转义字符
- PIPES_AS_CONCAT: 将"||"视为连接操作符而非"或"运算符
INDEX 索引
索引:是排序的特殊数据结构,定义在作为查找条件的字段上,又称为键key,索引通过存储引擎实现
- 优点
- 索引可以降低服务需要扫描的数据量,减少了IO次数
- 索引可以帮助服务器避免排序和使用临时表
- 索引可以帮助将随机I/O转为顺序 I/O
- 缺点
- 占用额外空间
- 影响插入速度
索引结构
B+Tree索引:
- 按顺序存储,每一个叶子节点到根结点的距离是相同的
- 左前缀索引,适合查询范围类的数据
经典面试题:InnoDB中一颗的B+树可以存放多少行数据?
使用B+Tree索引的方式
- 全值匹配
- 范围匹配,给定开头和结尾
- 从左往右查找原则。比如匹配最左前缀
- 只访问索引的查询
- 限制
- 如不从最左列开始,则无法使用索引
- 不能跳过索引中的列
*建立主键时会默认以主键为索引。
索引优化
语法
EXPLAIN 工具
可以通过EXPLAIN来分析索引的有效性,获取查询执行计划信息,用来查看查询优化器如何执行查询
语法
使用 profile 工具
- 分析SQL执行性能
并发控制
机制:
- 读锁:共享锁,也称为 S 锁,只读不可写(包括当前事务) ,多个读互不阻塞;加了S锁,所有会话都不能执行写入操作。
- 比如数据库备份
- 写锁:独占锁,排它锁,也称为 X 锁,写锁会阻塞其它事务(不包括当前事务)的读和写;加了X锁,只能加锁者会话执行读写操作,其他会话不能读写。缺点是并发性差。
- S 锁和 S 锁是兼容的,X 锁和其它锁都不兼容。
- 举个例子,事务 T1 获取了一个行 r1 的 S 锁,另外事务 T2 可以立即获得行 r1 的 S 锁,此时 T1 和 T2 共同获得行 r1 的 S 锁,此种情况称为锁兼容,但是另外一个事务 T2 此时如果想获得行 r1 的 X 锁,则必须等待 T1 对行 r1 锁的释放,此种情况也称为锁冲突
锁粒度:
- 表级锁:MyISAM
- 行级锁:InnoDB 对同一条数据写入操作时,会执行第一条语句,其他执行失败(行级锁特性)。
实现:
- 存储引擎:自行实现其锁策略和锁粒度
- 服务器级:实现了锁,表级锁,用户可显式请求
分类:
- 隐式锁:由存储引擎自动施加锁
- 显式锁:用户手动请求
锁策略:在锁粒度及数据安全性寻求的平衡机制
语法
事务
事务 Transactions:一组原子性的 SQL语句,或一个独立工作单元
事务日志:记录事务信息,实现undo,redo等故障恢复功能
事务特性(ACID)
A:atomicity 原子性;整个事务中的所有操作要么全部成功执行,要么全部失败后回滚
C:consistency一致性;数据库总是从一个一致性状态转换为另一个一致性状态,类似于能量守恒定律
I:Isolation隔离性;一个事务所做出的操作在提交之前,是不能为其它事务所见;隔离有多种隔离级别,实现并发
D:durability持久性;一旦事务提交,其所做的修改会永久保存于数据库中
语法
注意:只有事务型存储引擎中的DML语句方能支持此类操作,DDL命令无法撤销。比如drop table 无法回滚
sql执行效率提升
由于原子性的特点,IO操作极大的减少。就像中国式过马路,凑够一拨人就过,比一个一个的过效率更快
事务隔离级别(一般用2和3策略)
READ UNCOMMITTED 读未提交
- 可读取到未提交数据,产生脏读
READ COMMITTED 读提交
- 可读取到提交数据,但未提交数据不可读,产生不可重复读,即可读取到多个提交数据,导致每次读取数据不一致
REPEATABLE READ 可重复读(属于默认策略,适用于备份策略)
- 可重复读,多次读取数据都一致,产生幻读,即读取过程中,即使有其它提交的事务修改数据,仍只能读取到未修改前的旧数据。此为MySQL默认设置
SERIALIZABLE 序列化
- 可串行化,未提交的读事务阻塞写事务(加读锁,但不阻塞读事务),或者未提交的写事务阻塞读和写事务(加写锁,其它事务的读,写都不可以执行)。加锁独占,虽然不会出现脏读、读取数据变动、幻读等问题,但会导致并发性能差。
策略更改语法
日志管理
transaction log 事务日志
redo log:记录某数据块被修改后的值,数据更新前先记录redo log(即使未执行,也会被记录)提供数据的增删改记录
undo log:保存与执行的操作相反的操作,即记录某数据被修改前的值,可以用来在事务失败时进行rollback行rollback
图解
命令
事务日志执行策略优化
error log 错误日志
- mysqld启动和关闭过程中输出的事件信息
- mysqld运行中产生的错误信息
- event scheduler运行一个event时产生的日志信息
- 在主从复制架构中的从服务器上启动从服务器线程时产生的信息
general log 通用日志
通用日志:记录对数据库的通用操作过程,包括:错误的SQL语句
负载均衡时可以观察是在那个服务器上执行了sql命令
slow query log 慢查询日志
记录执行查询时长超出指定时长的操作
开启后生成信息在/var/lib/mysql/xxxx-slow.log文件中
语法
工具
binary log 二进制日志(备份)*
- 记录导致数据改变或潜在导致数据改变的SQL语句
- 记录已提交的日志
- 不依赖于存储引擎类型
事务日志和二进制日志区别
- 事务日志在线,二进制离线
- 事务日志记录事务执行的过程,包括提交和未提交,二进制日志记录只记提交的过程
- 事务日志只支持innodb,二进制都支持MyiSAM和innoDB
功能:通过"重放"日志文件中的事件来生成数据副本
注意:建议二进制日志和数据文件分开存放
具体的配置方式将和MySQL 备份和恢复章节一起整理。
我是moore 大家一起加油!