大数据兼云计算(王明龙)讲师-MYSQL-DAY02-体系结构

**

MySQL体系结构

**

mysql是由SQL接口,解析器,优化器,缓存,存储引擎组成的。

MySQL体系结构
![这里写图片描述](https://img-blog.csdn.net/20180809200530412?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdtaW5nbG9uZzE5ODk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)


1、Connectors  : 指的是不同语言中与SQL的交互

2、Management Serveices & Utilities  : 系统管理和控制工具

3、Connection Pool : 连接池
      管理缓冲用户连接,线程处理等需要缓存的需求。

4、SQL Interface : SQL接口
      接受用户的SQL命令,并且返回用户需要查询的结果。比如select from就是调用SQL Interface。

5、Parser: 解析器
      SQL命令传递到解析器的时候会被解析器验证和解析。解析器是由Lex和YACC实现的,是一个很长的脚本。
  
      主要功能:
  a . 将SQL语句分解成数据结构,并将这个结构传递到后续步骤,以后SQL语句的传递和处理就是基于这个结构的 。
  b. 如果在分解构成中遇到错误,那么就说明这个sql语句是不合理的。

6、Optimizer: 查询优化器
  SQL语句在查询之前会使用查询优化器对查询进行优化。他使用的是选取-投影-联接策略进行查询。
  用一个例子就可以理解: select uid,name from user where gender = 1;
  这个select 查询先根据where 语句进行选取,而不是先将表全部查询出来以后再进行gender过滤。
  这个select查询先根据uid和name进行属性投影,而不是将属性全部取出以后再进行过滤。
  将这两个查询条件联接起来生成最终查询结果。

7、Cache和Buffer: 查询缓存
  如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。
  这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key缓存,权限缓存等。

8、Engine :存储引擎
  存储引擎是MySql中具体的与文件打交道的子系统。也是Mysql最具有特色的一个地方。
  Mysql的存储引擎是插件式的。它根据MySql AB公司提供的文件访问层的一个抽象接口来定制一种文件访问机制(这种访问机制就叫存储引擎)。
  现在有很多种存储引擎,各个存储引擎的优势各不一样,最常用的MyISAM,InnoDB,BDB。
  默认下MySql是使用MyISAM引擎,它查询速度快,有较好的索引优化和数据压缩技术。但是它不支持事务。
  InnoDB支持事务,并且提供行级的锁定,应用也相当广泛。
  Mysql也支持自己定制存储引擎,甚至一个库中不同的表使用不同的存储引擎,这些都是允许的。





MySQL体系结构以及各种文件类型学习汇总


一.mysql体系结构
由数据库和数据库实例组成
数据库:物理操作系统文件或者其它文件的集合,在mysql中,数据库文件可以是frm、myd、myi、ibd等结尾的文件,当使用ndb存储引擎时候,不是os文件,是存放于内存中的文件。
数据库实例:由数据库后台进程/线程以及一个共享内存区组成,共享内存可以被运行的后台进程/线程所共享。






二. mysql文件类型

Mysql主要文件类型有如下几种:
-------------------------------------------
参数文件:mysql实例启动的时候在哪里可以找到数据库文件,并且指定某些初始化参数,这些参数定义了某种内存结构的大小等设置,还介绍了参数类型以及定义作用域。
日志文件:记录mysql对某种条件做出响应时候写入的文件。
Socket文件:当用linux的mysql命令行窗口登录的时候需要的文件
Pid文件:mysql实例的进程文件
Mysql表结构文件:存放mysql表结构定义文件
存储引擎文件:记录存储引擎信息的文件。



1 , 参数文件  my.cnf
=======================================================================
Mysql实例启动时,会先读取配置参数文件my.cnf

Mysql参数文件中的参数可以分为2种类型:
1) 动态(dynamic)参数
2) 静态参数(staitic)

动态参数:意味着可以在mysql实例运行中进行修改,set global sort_buffer_size=32999999;修改后,别的connection重新进行连接就可以生效了。
               生效范围分为:global(全局)和session(当前会话)
静态参数:说明在整个mysql实例运行期间不得进行修改,就类似一个只读的read only



2,日志文件
=======================================================================
日志文件记录了影响mysql数据库的各种类型活动


常见的日志文件有
------------------------
1) 错误日志
2) 查询日志
3) 二进制日志
4) redo日志
5) undo日志



1) 错误日志
----------------
错误日志对mysql的启动、运行、关闭过程进行了记录,mysql dba在遇到问题时候,第一时间应该查看这个错误日志文件,该文件不但记录了出错信息,
还记录了一些警告信息以及正确信息,这个error日志文件类似于oracle的alert文件,只不过默认情况下是以error结尾。


查看错误日志位置2种方法

1. show variables like 'log_error';




vim my.cnf
---------------------------------------------------------
log-error=/usr/local/mysql/mysqld.log
---------------------------------------------------------

我们可以在错误日志文件里面看到一些数据库启动信息,以及告警信息还有就是报错信息





2 ) 查询日志
------------------------------

Mysql提供了两种查询日志
普通日志(general log)
慢查询日志(slow log)


General log(全查询日志,也叫普通查询日志)
--------------------------------------------------------------
1. Geleral log记录了服务器接收到的每一个查询或是命令,无论这些查询或是命令是否正确甚至是否包含语法错误,general log 都会将其记录下来 
2. 记录的格式为 {Time ,Id ,Command,Argument }。也正因为mysql服务器需要不断地记录日志,开启General log会产生不小的系统开销,因
    此,Mysql默认是把General log关闭的。 我们可以通过修改Mysql全局变量来开启General log功能或是更改日志存放路径。 
3. mysql5.0版本,如果要开启slow log、general log,需要重启,从MySQL5.1.6版开始,general query log和slow query log开始支持写到文件或者
    数据库表两种方式,并且日志的开启,输出方式的修改,都可以在Global级别动态修改。


1)首先查看log_output,确认日志输出到文件还是数据库。
--------------------------------------------------------------------------------

mysql> show variables like 'log_output';

+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| log_output       |  FILE |
+-------------------+-------+
1 row in set (0.00 sec)

通过以上结果可以发现,log_output的值为FILE,证明是输出到日志文件,如果为TABLE则输出到默认'mysql'数据库中的相应日志表。



2)接下来通过如下命令可以查看 mysql默认的 General log 配置。
--------------------------------------------------------------------------------------

mysql> show global variables like '%general%';

+------------------+----------------------------+
| Variable_name    | Value               |
+------------------+----------------------------+
| general_log      | OFF                   |
| general_log_file | /var/run/mysqld/mysqld.log |
+------------------+----------------------------+
2 rows in set (0.00 sec)


general_log的值为OFF,所以当前general_log是关闭的。general_log_file变量的值是日志文件的路径。



3)通过 set global general_log = on; 命令开启General log。
---------------------------------------------------------------------------------

set global general_log = on;



4)最后我们可以从 /var/run/mysqld/mysqld.log 文件中查看相应日志信息。
-----------------------------------------------------------------------------------------------------



Slow log(慢查询日志):
----------------------------------
就是记录运行较慢的sql语句信息,给sql语句的优化带来很好的帮助,可以设置一个阀值,将运行时间超过该阀值的sql语句的运行信息都记录到slow log日志里面去。
该阀值可以通过long_query_time来设置,也可以设置到毫秒微秒: 以小数点前是s计位


1、我们首先来看一下与慢日志相关的全局变量与日志位置
------------------------------------------------------------------------------

mysql> show global variables like '%slow%';

+---------------------+---------------------------------+
| Variable_name       | Value                    |
+---------------------+---------------------------------+
| log_slow_queries    | OFF                      |
| slow_launch_time    | 2                        |
| slow_query_log      | OFF                      |
| slow_query_log_file | /var/run/mysqld/mysqld-slow.log |
+---------------------+---------------------------------+
4 rows in set (0.00 sec)


特点:
1. 慢速日志的确提供了很多有用的信息,但是不代表出现的查询一定一直都是慢的。如果同样的查询在慢速日志里出现了多次,那么它的确需要优化,但是如果只是出现了偶尔一两次,
    则有可能是其他客观原因造成的,比如某些锁,I/O磁盘物理性问题,网络问题等等。
2. 慢速日志的slow_launch_time的时间单位为秒,可以通过网上第三方补丁将其更改为毫秒级,用于更加精细的日志记录和分析,但是这需要重新编译mysql。
3. 我们通常在日志中查找下面几个信息:长查询、影响比较大的查询和新查询。这可能需要我们自己写一下脚本或是借助某些第三方工具进行日志分析。 
4. General log 系统开销比较大,一般不建议开启。


2. 查看慢查询日志定义
----------------------------------------------------------------------------------

show variables like 'long_query_time';               //小数点前以秒为单位,可以看下面是1s,代表查询时间大于1秒的查询都会被记录到slow log中




但是需要注意一点:对于运行时间等于该阀值的,就不会记录在内了。

另外一个参数是log_queries_not_using_indexes,如果运行的sql没有使用索引,只要超过阀值了也会记录在慢查询日志里面的。
long_query_time=0 (记录所有sql可以做审计) ,dba可以通过这个审计来推动业务的发展,可以知道哪些业务开展的好那些业务开展的不好,
通过慢sql可以分析出哪些应用性能较差需要优化改进,dba的最大职能以及贡献就在于通过对数据库的维护来推动业务的发展和进步。从数据到业务,
这是我们需要一直努力的方向。


3. 打开记录未使用索引的sql语句的功能
-----------------------------------------------------------------------------------------------------------------------------------------------------
show variables like 'log_queries_not_using_indexes';              //查看记录索引参数的使用状态
set global log_queries_not_using_indexes=1;                        //打开记录未使用索引的sql语句的功能






慢查询日志还可以记录在table里面,
Slow_log表,也可以将慢查询日志放入一张表里面

show variables like 'log_output';
---------------------------------------------------------
查看结果是 “file” 就存放在slow log里面
查看结果是 “table” 就在slow_log表里面。


show variables like 'log_output';





启用 slow log
在 my.cnf 中设置
[mysqld] 
slow_query_log=on                         //启用slow log
slow_query_log_file=mysql-slow        //定义show log位置与show log的开头文件名



3) 二进制日志
------------------------------
记录了对数据库进行变更的操作,但是不包括select操作以及show操作,因为这类操作对数据库本身没有没有修改,如果你还想记录select和show的话,
你就需要查看前面的全查询日志,另外binlog还包括了执行数据库更改操作时间和执行时间等信息。

二进制的主要作用有如下2个:
(1):恢复 recovery。某些数据的恢复需要二进制日志,在全库文件恢复后,可以在此基础上通过二进制日志进行point-to-time的恢复。
(2):复制(replication)。其原理和恢复类似,通过复制和执行二进制日志使得一台远程的mysql数据库(slave)于一台mysql数据库(master)进行实时同步。

通过在my.cnf里面设置log-bin =/home/data/mysql/binlog/mysql-bin.log生效,默认是在数据目录datadir下面



binlog日志参数:

1) max_binlog_size:
-------------------------------
指定了单个二进制文件的最大值,如果超过了该值,就会产生新的日志文件,后缀名+1,并且记录到.index文件里面。默认值是1G,不过从多年的dba生涯总结来说,64M是通用的大小设置。


2) binlog_cache_size:
--------------------------------
使用innodb存储引擎时候,所有未提交uncommitted的二进制日志会被记录到一个缓存中,等该事务提交时committed直接将缓冲中的二进制日志写入二进制日志文件里面,而该缓冲的大小就
由binlog_cache_size来决定,这个缓冲区是基于session的,也就是每一个线程需要事务的时候,mysql都会分配一个binlog_cache_size的缓存,因此改值设置需要非常小心,不能设置过大,免
得内存溢出了。


3) sync_binlog:
--------------------------------
sync_binlog=N:
参数优化介绍过,大概就是表示每次写缓冲N次就同步到磁盘文件中,如果将N设置为1的话,每次都会写入binlog磁盘文件中,这是最保险最安全的,如果N>1,在意外发生的时候,就表示会有
N-1个dml没有被写入binlog中,有可能就会发生主动数据不一致的情况。


4) binlog-do-db、binlog-ingore-db:
--------------------------------------------------
表示需要写入或者忽略写入哪些库的日志,默认为空,表示可以将所有库的日志写入到二进制文件里面。


5) log-slave-update:
-------------------------------
启用从机服务器上的slave日志功能,使这台计算机可以用来构成一个镜像链(A->B->C)  ,可以让从库上面产生二进制日志文件,在从库上再挂载一个从库。


6) binlog-format:日志格式
---------------------------------------

mysql 复制主要有三种方式:
-------------------------------------------------------------------------------
1. 基于SQL语句的复制(statement-based replication, SBR)
2. 基于行的复制(row-based replication, RBR)
3. 混合模式复制(mixed-based replication, MBR)
-------------------------------------------------------------------------------


binlog 也有三种格式:
--------------------------------------------
statement:基于SQL语句的复制
row:基于行的复制
mixed:混合模式复制
--------------------------------------------


1. statement 模式(SBR)
----------------------------------------
优点:每一条会修改数据的sql语句会记录到binlog中。优点是并不需要记录每一条sql语句和每一行的数据变化,减少了binlog日志量,节约IO,提高性能。
缺点:是在某些情况下会导致master-slave中的数据不一致(如sleep()函数, last_insert_id(),以及user-defined functions(udf)等会出现问题)

2. row 模式(RBR)
------------------------------
优点:不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了,修改成什么样了。而且不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。
缺点:是会产生大量的日志,尤其是alter table的时候会让日志暴涨。

3. mixed 模式(MBR)
--------------------------------
以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。




4) redo日志
-----------------------------------
所有的数据库都是日志先行,先写日志,再写数据文件,所以才会有redo log的规则。

1. 默认情况下会有2个文件名称分别为ib_logfile0 和ib_logfile1 ,在mysql数据库目录下可以看到这2个文件,这个对innodb存储引擎非常重要,因为它们记录了
    对于innodb存储引擎的事务日志。

2. 重做日志文件的主要目的是:万一实例或者介质失败media failure,重做日志就可以派上用场,如果数据库由于所在主机掉电导致实例失败,innodb存储引擎
    会使用重做日志恢复到掉电前的时刻,以此来保证数据的完整性。

3. 每个innodb存储引擎至少有一个重做日志组,每组至少有2个重做日志文件,如默认的ib_logfile0 和ib_logfile1,为了得到更高的可靠性,你可以设置多个组,
    也可以将每组放在不同的磁盘上面,来提高性能

3. LSN logsequence number:递增产生的,可以唯一的标记一条redo日志,对于我们数据库故障恢复都是非常重要的,可以唯一定位数据库运行状态,至于如何定位细节,大家可以去看
    下redo、undo的源码,源码:在"storage/innobase/include/log0log.h"

查看参数设置:show variables like 'innodb%log%';



要记住,MySQL的二进制日志和InnoDB Redo log之间的区别
**************************************************************************************************************
1、首先2者都是记录数据的改变,不同的是,binlog是记录所有数据的改变信息,而innodb的redo log只是记录所有innodb表数据的变化。
2、binlog是记录已经提交完毕之后的dml以及ddl sql语句,而innodb redo log是正在执行中的dml以及ddl语句
3、binlog可以作为恢复数据使用 redo log可以作为异常down机或者介质故障后的数据恢复使用
4、在db文件目录下,也分属于不通的日志文件中。

简单说,
binlog :是mysqld 记录全局数据结构变化的log,用于复制和恢复
innodb redo log:是innodb 引擎自己记录事务过程的log,用于回滚和故障恢复
**************************************************************************************************************




5) undo日志 
-----------------------------------------
存在于共享表空间ibdata1里面,有一个回滚段地址,里面存放了头信息,配置头信息,段的头信息,里面存储了与redo相反的数据更新操作,如果rollback的话,
就把undo段里面数据回写到数据文件里面。

如果用了独立表空间的话,则直接存储到表私自的空间中,而不存储到共享表空间中。在innodb存储引擎中,undo log用来完成事务的回滚以及MVCC的功能
Redo与undo他们并不是各自独立没有关系的,他们是有关联的,交替合作来保证数据的一致性和安全性





3 , 套接字socket文件
=======================================================================

mysql.socket文件是服务器与本地客户端进行通信的Unix套接字文件


可以通过如下3种方式查看:
---------------------------------------------

1)ps -ef | grep mysql | grep socket

2)show variables like 'socket';




3) cat my.cnf | grep socket

socket = /usr/local/mysql/mysql.sock




4,pid文件
=======================================================================

当mysql实例启动的时候,会将自己的进程id写入一个文件中,该文件即为pid文件,由参数pid_file控制,默认路径位于数据库目录下,
可以通过以下三种方式查看:

1) show variables like 'pid_file';




2) ps -ef | grep mysql | grep pid

3) cat my.cnf  | grep pid



5,表结构文件
=======================================================================
*.frm
*.ibd




6,innodb存储文件
=======================================================================

innodb存储引擎在存储设计上模仿了oracle,该文件就是默认的表空间文件,可以通过参数innodb_data_file_path来进行设置,

格式如下:
innodb_data_file_path= IBdata1:128M;IBdata2:128M:autoextend




可以用多个文件组成一个表空间,同时制定文件的属性,
IBdata1和IBdata2位于不同的磁盘组上,则可以对性能带来一定程度的提升。文件后面的属性表示文件大小,autoextend表示还可以扩展。
但是如果设置了innodb_file_per_table为true后,那么表数据文件就会在单独的.ibd文件里面,不在这个ibdata文件里面了。




binlog,redo log,undo log区别


一. binlog

1.binlog概念
binlog日志用于记录所有更新且提交了数据或者已经潜在更新提交了数据(例如,没有匹配任何行的一个DELETE)的所有语句。语句以事件的形式保存,它描述数据更改。

2.binlog作用
1.恢复使能够最大可能地更新数据库,因为二进制日志包含备份后进行的所有更新。
2.在主复制服务器上记录所有将发送给从服务器的语句。

3.binlog 主要参数

log_bin
设置此参数表示启用binlog功能,并指定路径名称

innodb_flush_log_at_trx_commit = N:
N=0  每隔一秒,把事务日志缓存区的数据写到日志文件中,以及把日志文件的数据刷新到磁盘上;

N=1  每个事务提交时候,把事务日志从缓存区写到日志文件中,并且刷新日志文件的数据到磁盘上;

N=2  每事务提交的时候,把事务日志数据从缓存区写到日志文件中;每隔一秒,刷新一次日志文件,但不一定刷新到磁盘上,而是取决于操作系统的调度;

sync_binlog = N:

N0  每向二进制日志文件写入N条SQL或N个事务后,则把二进制日志文件的数据刷新到磁盘上;

N=0  不主动刷新二进制日志文件的数据到磁盘上,而是由操作系统决定;

推荐配置组合:

N=1,1  适合数据安全性要求非常高,而且磁盘IO写能力足够支持业务,比如充值消费系统;

N=1,0  适合数据安全性要求高,磁盘IO写能力支持业务不富余,允许备库落后或无复制;

N=2,0或2,m(0m100)  适合数据安全性有要求,允许丢失一点事务日志,复制架构的延迟也能接受;

N=0,0  磁盘IO写能力有限,无复制或允许复制延迟稍微长点能接受,例如:日志性登记业务;



二. Undo Log

Undo Log是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用UndoLog来实现多版本并发控制(简称:MVCC)。

-事务的原子性(Atomicity)
事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作。如果在执行的过程中发了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过。

-原理
Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为UndoLo)。
然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用UndoLog中的备份将数据恢复到事务开始之前的状态。
除了可以保证事务的原子性,Undo Log也可以用来辅助完成事务的持久化。

-事务的持久性(Durability)
事务一旦完成,该事务对数据库所做的所有修改都会持久的保存到数据库中。为了保证持久性,数据库系统会将修改后的数据完全的记录到持久的存储上。

-用 Undo Log 实现原子性和持久化的事务的简化过程
假设有A、B两个数据,值分别为1,2。
A.事务开始.
B.记录A=1到undolog.
C.修改A=3.
D.记录B=2到undolog.
E.修改B=4.
F.将undolog写到磁盘。
G.将数据写到磁盘。
H.事务提交

这里有一个隐含的前提条件:数据都是先读到内存中,然后修改内存中的数据,最后将数据写回磁盘。
之所以能同时保证原子性和持久化,是因为以下特点:

A.更新数据前记录Undo log。
B.为了保证持久性,必须将数据在事务提交前写到磁盘。只要事务成功提交,数据必然已经持久化。
C.Undo log必须先于数据持久化到磁盘。如果在G,H之间系统崩溃,undo log是完整的,可以用来回滚事务。
D.如果在A-F之间系统崩溃,因为数据没有持久化到磁盘。所以磁盘上的数据还是保持在事务开始前的状态。

缺陷:每个事务提交前将数据和Undo Log写入磁盘,这样会导致大量的磁盘IO,因此性能很低。
如果能够将数据缓存一段时间,就能减少IO提高性能。但是这样就会丧失事务的持久性。因此引入了另外一种机制来实现持久化,即



三. Redo log
记录的是新数据的备份。在事务提交前,只要将Redo Log持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,
但是RedoLog已经持久化。系统可以根据RedoLog的内容,将所有数据恢复到最新的状态。

-Undo+Redo事务的简化过程
假设有A、B两个数据,值分别为1,2.
A.事务开始.
B.记录A=1到undolog.
C.修改A=3.
D.记录A=3到redolog.
E.记录B=2到undolog.
F.修改B=4.
G.记录B=4到redolog.
H.将redolog写入磁盘。
I.事务提交

-Undo+Redo事务的特点
A.为了保证持久性,必须在事务提交前将RedoLog持久化。
B.数据不需要在事务提交前写入磁盘,而是缓存在内存中。
C.RedoLog保证事务的持久性。
D.UndoLog保证事务的原子性。
E.有一个隐含的特点,数据必须要晚于redolog写入持久存

猜你喜欢

转载自blog.csdn.net/wangminglong1989/article/details/81543179