< Mysql性能调优与架构设计 >

第二章: MYSQL 组成;
     
日志文件:       
     1、错误日志:Error Log
        --如果要开启系统记录错误日志的功能,需要在  启动时开启-log-error 选项。错误日志的默认存放位置在数据目录下,以 hostname.err 命 
名。但是可以使用命令:--log-error[=file_name],修改其存放目录和文件名。
         --为了方便维护需要, 有时候会希望将错误日志中的内容做备份并重新开始记录, 这时候  就可以利用 MySQL 的 FLUSH LOGS 命令来告诉 MySQL 备份旧日志文件并生成新的日志文件。  备份文件名以“.old”结尾。

    2、二进制日志:Binary Log & Binary Log Index
         --二进制日志,也就是我们常说的 binlog,也是 MySQL Server 中最为重要的日志之一。  当我们通过“--log-bin[=file_name]”打开了记录的功能之后,MySQL 会将所有修改数据 库数据的 query 以二进制形式记录到日志文件中, 参数的显式指  定才能开启, 如果未指定 file_name, 则会在数据目录下记录为 mysql-bin.****** (*代表0~  9 之间的某一个数字,来表示该日志的序号) 。
          binlog 还有其他一些附加选项参数:
        --max_binlog_size”设置 binlog 的最大存储上限,当日志达到该上限时,MySQL 会  重新创建一个日志开始继续记录。不过偶尔也有超出该设置的 binlog 产生,一般都是因为  在即将达到上限时,产生了一个较大的事务,为了保证事务安全,MySQL 不会将同一个事务 分开记录到两个 binlog 中。
         --binlog-do-db=db_name”参数明确告诉 MySQL,需要对某个(db_name)数据库记  录 binlog,如果有了“--binlog-do-db=db_name ” 参数的显式指定,MySQL 会忽略针对其他  数据库执行的 query,而仅仅记录针对指定数据库执行的 query。
          --binlog-ignore-db=db_name ”与 “--binlog-do-db=db_name ” 完全相反,它显式指  定忽略某个(db_name)数据库的 binlog 记录,当指定了这个参数之后,MySQL 会记录指定 数据库以外所有的数据库的 binlog。(通过 use db_name 切换后所在的数据库)
          --mysql-bin.index 文件(binary log index)的功能是记录所有 Binary Log 的绝对路  径,保证 MySQL 各种线程能够顺利的根据它找到所有需要的 Binary Log 文件。
   
       3、更新日志:update log
         --更新日志是 MySQL 在较老的版本上使用的,其功能和 binlog 基本类似,从版本 5.0 开始,MySQL 已经不再支持更新日志了。
 
       4、查询日志:query log  
         --查询日志记录 MySQL 中所有的 query,通过“--log[=fina_name]”来打开该功能。由  于记录了所有的 query,包括所有的 select,体积比较大,开启后对性能也有较大的影响,  所以请大家慎用该功能。 一般只用于跟踪某些特殊的 sql 性能问题才会短暂打开该功能。 默 认的查询日志文件名为 hostname.log。

       5、慢查询日志:slow query log   
         --顾名思义,慢查询日志中记录的是执行时间较长的 query,也就是我们常说的 slow   query,通过设--log-slow-queries[=file_name]来打开该功能并设置记录位置和文件名,  默认文件名为 hostname-slow.log,默认目录也是数据目录。
    
       6、Innodb 的在线 redo 日志:innodb redo log 
        --Innodb 是一个事务安全的存储引擎,其事务安全性主要就是通过在线 redo 日志和记录  在表空间中的 undo 信息来保证的。redo 日志中记录了 Innodb 所做的所有物理变更和事务 信息, 通过 redo日志和undo 信息, Innodb保证了在任何情况下的事务安全性。 Innodb的redo 日志同样默认存放在数据目录下,  可以通过 innodb_log_group_home_dir来更改设置日志的 存放位置 ,通过 innodb_log_files_in_group设置日志的数量。

 数据文件:
        不同的 MySQL 存储引擎有各自不同  的数据文件,存放位置也有区别。多数存储引擎的数据文件都存放在和 MyISAM 数据文件位 置相同的目录下,但是每个数据文件的扩展名却各不一样。如 MyISAM 用“.MYD”作为扩展 名,Innodb 用“.ibd ” ,Archive 用“.arc ” ,CSV 用“.csv ” ,等等。
       1.“.frm”文件  
      --与表相关的元数据(meta)信息都存放在“.frm”文件中,包括表结构的定义信息等。  不论是什么存储引擎,每一个表都会有一个以表名命名的“.frm ” 文件。所有的“.frm ” 文 件都存放在所属数据库的文件夹下面。

       2 .“.MYD”文件
      --.MYD”文件是 MyISAM 存储引擎专用,存放 MyISAM 表的数据。每一个 MyISAM 表都会  有一个 “.MYD ” 文件与之对应,同样存放于所属数据库的文件夹下,和“.frm ” 文件在一 起.

       3 .“.MYI”文件
     --.MYI ” 文件也是专属于 MyISAM 存储引擎的,主要存放 MyISAM 表的索引相关信息。对  于 MyISAM 存储来说,可以被 cache 的内容主要就是来源于“.MYI”文件中。每一个 MyISAM 表对应一个“.MYI”文件,存放于位置和“.frm”以及“.MYD”一样。

       4. ibd”文件和 ibdata 文件
     --这两种文件都是存放 Innodb 数据的文件 ,之所以有两种文件来存放 Innodb 的数据( 包  括索引) , 是因为 Innodb 的数据存储方式能够通过配置来决定是使用共享表空间存放存储数 据,还是独享表空间存放存储数据。 独享表空间存储方式使用“.ibd ” 文件来存放数据,且  每个表一个“.ibd”文件,文件存放在和 MyISAM 数据相同的位置。如果选用共享存储表空 间来存放数据,则会使用 ibdata 文件来存放,所有表共同使用一个(或者多个,可自行配 置) ibdata 文件。ibdata 文件可以通过 innodb_data_home_dir 和 innodb_data_file_path  两 个 参 数 共 同 配 置 组 成 , innodb_data_home_dir 配 置 数 据 存 放 的 总 目 录 , 而 innodb_data_file_path 配 置 每 一 个 文 件 的 名 称。

     -- 但是 Innodb 限制了仅仅只有最后一个 ibdata 文件能够配置成自  动扩展类型。 当我们需要添加新的 ibdata 文件的时候, 只能添加在 innodb_data_file_path  配置的最后,而且必须重启 MySQL 才能完成 ibdata 的添加工作。不过如果我们使用独享表 空间存储方式的话, 就不会有这样的问题, 但是如果要使用裸设备的话, 每个表一个裸设 备 , 可能造成裸设备数量非常大,而且不太容易控制大小,实现比较困难,而共享表空间却不会 有这个问题,容易控制裸设备数量。我个人还是更倾向于使用独享表空间存储方式

Replication 相关文件
   
        1、master.info 文件
      --master.info 文件存在于  Slave 端的数据目录下, 里面存放了该 Slave 的 Master 端的  相关信息,包括 Master 的主机地址,连接用户,连接密码,连接端口,当前日志位置,已 经读取到的日志位置等信息
   
        2、relay log 和 relay log index
       --mysql-relay-bin.xxxxxn 文件用于存放  Slave 端的 I/O 线程从 Master 端所读取到  的 Binary Log 信息,然后由 Slave 端的 SQL 线程从该 relay log 中读取并解析相应的 日志信息,转化成 Master 所执行的 SQL 语句,然后在 Slave 端应用。
        --mysql-relay-bin.index 文件的功能类似于 mysql-bin.index ,同样是记录日志的存放位置的绝对路径,只不过他所记录的不是 Binary Log,而是 Relay Log。
      
       3、relay-log.info 文件
       --类似于 master.info,它存放通过 Slave 的 I/O 线程写入到本地的 relay log 的相关信  息。供 Slave 端的 SQL 线程以及某些管理操作随时能够获取当前复制的相关信息。


Others  file 

        1、system config file  
       --MySQL 的系统配置文件一般都是“ my.cnf ” ,U nix/Linux 下默认存放在"/etc"目录下,  Windows 环境一般存放在“c:/windows” 目录下面。 “my.cnf”文件中包含多种参数选项组 (group ) , 每一种参数组都通过中括号给定了固定的组名, 如 “[mysqld] ” 组中包括了 mysqld 
服务启动时候的初始化参数, “[client]”组中包含着客户端工具程序可以读取的参数,此  外还有其他针对于各个客户端软件的特定参数组, 如 mysql 程序使用的 “[mysql] ” , mysqlchk  使用的“[mysqlchk] ” ,等等

        2、pid file
       --pid file 是 mysqld 应用程序在 Unix/Linux 环境下的一个进程文件,和许多其他  Unix/Linux 服务端程序一样,存放着自己的进程 id。
     
        3、socket file
        --socket 文件也是在 Unix/Linux 环境下才有的,用户在 Unix/Linux 环境下客户端连接  可以不通过 TCP/IP 网络而直接使用 Unix Socket 来连接 MySQL。


MySQL r Server 

      逻辑模块组成
       --MySQL 可以看成是二层架构 .第一层我们通常叫做 SQL Layer .包括权限判断,sql 解析,执  行计划优化 uery cache 的处理等等 ; 第二层就是存储引擎层。 

       SQL Layer 中包含了多个子模块 ;
        1、初始化模块  :  初始化模块就是在 MySQL Server 启动的时候,对整个系统做各种各样的初  始化操作,比如各种 buffer , cache 结构的初始化和内存空间的申请,各种系统变量的初始  化设定,各种存储引擎的初始化设置,等等。
       
        2、核心 API :核心 API 模块主要是为了提供一些需要非常高效的底层操作功能的优化实现, 包括各种  底层数据结构的实现,特殊算法的实现,字符串处理,数字处理等,小文件 I/O,格式化输 出,以及最重要的内存管理部分。核心 API 模块的所有源代码都集中在 mysys 和 strings 文件夹下面

       3、网络交互模块: 底层网络交互模块抽象出底层网络交互所使用的接口 api,实现底层网络数据的接收与  发送,以方便其他各个模块调用,以及对这一部分的维护。

       4、Client & Server 交互协议模块:这些协议都是建立在现有的 OS 和网络协议之上的,如 TCP/IP 以及 Unix Socket。

       5、用户模块: 实现的功能, 主要包括用户的登录连接权限控制和用户的授权管理。

       6、访问控制模块 : 访问控制模块  实现的功能就是根据用户模块中各用户的授权信息, 以及数据库自身特有的各种约束, 来控  制用户对数据的访问。 用户模块和访问控制模块两者结合起来, 组成了 MySQL 整个数据库系 统的权限安全管理的功能。

       7、连接管理、连接线程和线程管理: 连接管理模块负责监听对 MySQL Server 的各种请求,接收连接请求,转发所有连接请  求到线程管理模块。
        8、Query 解析和转发模块: 
        9、Query Cache 模块: Query Cache 模块在 MySQL 中是一个非常重要的模块,他的主要功能是将客户端提交给  MySQL 的 Select 类 query 请求的返回结果集 cache 到内存中,与该 query 的一个 hash 值做  一个对应。
     
       10、Query 优化器模块: 就是优化客户端请求的 query,根据客户端请求的 query 语 句,和数据库中的一些统计信息,在一系列算法的基础上进行分析,得出一个最优的策略, 告诉后面的程序如何取得这个 query 语句的结果。

      11、表变更管理模块 : 表变更管理模块主要是负责完成一些 DML 和 DDL 的 query。
      
      12、表维护模块:表的状态检查,错误修复,以及优化和分析等工作都是表维护模块需要做的事情。

      13、 系统状态管理模块:负责在客户端请求系统状态的时候, 将各种状态数据返回给用户, 像  DBA 常用的各种 show status 命令, show variables 命令等。

       14、表管理器:表的定义文件, 也就是*.frm  文件。表管理器的工作主要就是维护这些文件,以及一个 cache,该 cache 中的主要内容是  各个表的结构信息。此外它还维护 table 级别的锁管理。

      15、日志记录模块:日志记录模块主要负责整个系统级别的逻辑层的日志的记录,包括 error log , binary   log,slow query log 等。
     
       16、复制模块: 复制模块又可分为 Master 模块和 Slave 模块两部分,Master 模块主要负责在  Replication 环境中读取 Master 端的 binary 日志, 以及与 Slave 端的 I/O 线程交互等工 作 。  Slave 模块比 Master 模块所要做的事情稍多一些,在系统中主要体现在两个线程上面。一  个是负责从 Master 请求和接受 binary 日志, 并写入本地 relay log 中的 I/O 线程。 另外一 个是负责从 relay log 中读取相关日志事件, 然后解析成可以在 Slave 端正确执行并得到和 Master 端完全相同的结果的命令并再交给 Slave 执行的 SQL 线程。

       17、存储引擎接口模块:目前各种数据库产品  中, 基本上只有 MySQL 可以实现其底层数据存储引擎的插件式管理。




 MySQL 自带工具:

   1、mysql   :  工具; 
            --prompt=name”参数对于做运维的人来说是一个非常重要的参数选项,其主要功能  是定制自己的 mysql 提示符的显示内容
            --tee=name”参数也是对运维人员非常有用的参数选项,用来告诉 mysql,将所有输  入和输出内容都记录进文件。在我们一些较大维护变更的时候,为了方便被查,最好是将整  个操作过程的所有输入和输出内容都保存下来。
     
    2、mysqladmin:  ;
              -- ping 命令可以很容易检测 MySQL Server 是否还能正常提供服务 。 #  mysqladmin -u sky -ppwd -h localhost ping
              --status 命令可以获取当前 MySQL Server 的几个基本的状态值:# /usr/local/mysql/bin/mysqladmin -u root -p -h localhost status
              --processlist 获取当前数据库的连接线程信息:  #  /usr/local/mysql/bin/mysqladmin -u root -p -h localhost status

    3、mysqldump : ;这  个功能实际上是调用了 MySQL 中的 “select * into OUTFILE from ... ” 语句而实现。建议每次执行 mysqldump 程序的时候都通过尽量做到“--default-  character-set=name”显式指定字符集内容,以防止以错误的字符集生成不可用的内容

    4、mysqlimport: mysqlimport 程序是一个将以特定格式存放的文本数据(如通过“select * into   OUTFILE from ...”所生成的数据文件)导入到指定的 MySQL Server 中的工具程序,比如  将一个标准的 csv 文件导入到某指定数据库的指定表中。mysqlimport 工具实际上也只是
“load data infile”命令的一个包装实现。
    
    5、mysqlbinlog : mysqlbinlog 程序的主要功能就是分析 MySQL Server 所产生的二进制日志,
         
    6、mysqlcheck :    mysqlcheck 工具程序可以检查(check ) ,修复( repair ) ,分析( analyze)和优化  (optimize ) MySQL Server 中的表,但并不是所有的存储引擎都支持这里所有的四个功能 ,  像 Innodb 就不支持修复功能。   

     7、 myisamchk : 功能有点类似“mysqlcheck -c/-r ” ,对检查和修复 MyISAM 存储引擎的表,但只能对   MyISAM 存储引擎的索引文件有效,而且不用登录连接上 MySQL Server 即可完成操作

      8、 myisampack : 对 MyISAM 表进行压缩处理,以缩减占用存储空间,一般主要用在归档备份的场景下,  而且压缩后的 MyISAM 表会变成只读,不能进行任何修改操作。

     9、mysqlhotcopy : 仅能在 Unix/Linux 环境下使用。他的主要功能就是对 MySQL 中  的 MyISAM 存储引擎的表进行在线备份操作,其备份操作实际上就是通过对数据库中的表进  行加锁,然后复制其结构,数据和索引文件来完成备份操作,当然,也可以通过指定“--  noindices”告诉 mysqlhotcopy 不需要备份索引文件。





第三章,MySQL 存储引擎简介:

       MyISAM 存储引擎简介
          --MyISAM 存储引擎的表在数据库中,每一个表都被存放为 三个以表名命名的物理文件; 不可缺少的.frm 文件,以及 .MYD和 .MYI文件。
  分别存放表的数据(.MYD)和索引数据(.MYI)。
  
           MyISAM 支持以下三种类型的索引
    
       1、B-Tree 索引 :就是所有的索引节点都按照 balance tree 的数据结构来  存储,所有的索引数据节点都在叶节点。     
       2、R-Tree 索引 :R-Tree 索引的存储方式和 b-tree 索引有一些区别,主要设计用于为存储空间和多  维数据的字段做索引, 所以目前的 MySQL 版本来说, 也仅支持 geometry 类型的字段作索引 。

       3、Full-text 索引:Full-text 索引就是我们长说的全文索引, 他的存储结构也是 b-tree。 主要是为了  解决在我们需要用 like 查询的低效问题。
        --MyISAM 上面三种索引类型中,最经常使用的就是 B-Tree 索引了,偶尔会使用到 Full-  text,但是 R-Tree 索引一般系统中都是很少用到的。另外 MyISAM 的 B-Tree 索引有一个较 大的限制,那就是参与一个索引的所有字段的长度之和不能超过 1000 字节。
        -- MyISAM 的数据存放格式是分为静态(FIXED ) 固  定长度、动态(DYNAMIC)可变长度以及压缩(COMPRESSED)这三种格式.在创建表的时候通过 ROW_FORMAT 来指定  {COMPRESSED | DEFAULT}.
   
        --MyISAM 存储引擎的某个表文件出错之后,仅影响到该表,而不会影响到其他表,更不  会影响到其他的数据库. 可以在线通过 check table 命令来尝试校验他,并可以通过 repair table 命令来尝试修  复。在数据库关闭状态下,我们也可以通过 myisamchk 工具来对数据库中某个(或某些)表  进行检测或者修复。(除非没办法,可以修复,记得备份哦)


         Innodb 存储引擎简介 :
         
         1、支持事务安装,而且实现了 SQL92 标准所定义的所有四个级  别(READ UNCOMMITTED,READ COMMITTED,REPEATABLE READ 和 SERIALIZABLE )。
 
         2、数据多版本读取: Innodb 在事务支持的同时,为了保证数据的一致性已经并发时候的性能,通过对 undo  信息,实现了数据的多版本读取。
   
         3、锁定机制的改进 : Innodb 改变了 MyISAM 的锁机制,实现了行锁。虽然 Innodb 的行锁机制的实现是通过  索引来完成的,但毕竟在数据库中 99%的 SQL 语句都是要使用索引来做检索数据的。

         4、实现外键 : Innodb 实现了外键引用这一数据库的重要特性,使在数据库端控制部分数据的完整性  成为可能。至于是每个表单独存放
还是所有表存放在一起,完全由用户来决定(通过特定配置) ,同时还支持符号链接。

         Innodb 的物理结构分为两大部分:  
       1、数据文件(表数据和索引数据),存放数据表中的数据和所有的索引数据,包括主键和其他普通索引。在 Innodb 中,存  在了表空间(tablespace)这样一个概念,但和 Oracle 的有较大的不同。
           --innodb 表空间分为2种 
              共享表空间,也就是所有表和索引数据被存放  同一个表空间(一个或多个数据文件)中,通过 innodb_data_file_path来指定,增加数  据文件需要停机重启
              独享表空间 ,也就是每个表的数据和索引被存放在一个  单独的.ibd 文件中。
              --可以自行设定使用共享表空间还是独享表空间来存放我们的表, 但是共享表空  间都是必须存在的。因为 Innodb 的 undo 信息和其他一些元数据信息都是存放在共享表空间  里面。共享表空间数据文件可以设置为 固定大小和 可自动扩展大小 种形式的。
              --另外,Innodb 不仅可以使用文  件系统,还可以使用裸设备。另外一个较为令人头疼的就是 Innodb 在给共享表空间增  加数据文件之后, 必须要重启数据库系统才能生效, 如果是使用裸设备, 还需要有两次重 启。(一般使用独享表空间)

        2、日志文件 : Innodb 的日志文件和 Oracle 的 redo 日志比较类似, 同样可以设置多个日志组 (最少 2  个) , 同样采用轮循策略来顺序的写入, 甚至在老版本中还有和 Oracle 一样的日志归档特 性 。 如果你的数据库中有创建了 Innodb 的表, 那么千万别全部删除 innodb 的日志文件, 因为很  可能就会让你的数据库 crash,无法启动,或者是丢失数据。由于有 redo 日志的存在,有 checkpoint 机制的保护,Innodb 完全可以通过 redo 日  志将数据库 Crash 时刻已经完成但还没有来得及将数据写入磁盘的事务恢复, 也能够将所有  部分完成并已经写入磁盘的未完成事务回滚并将数据还原。

        
   NDB Cluster 存储引擎简介
  
            --NDB 存储引擎也叫 NDB Cluster 存储引擎,主要用于 MySQL Cluster 分布式集群环境,Cluster 是 MySQL 从 5.0 版本才开始提供的新功能。Mysql Cluster 实际上就是在无共享存储设备的情况下实现的一种内存数据  库 Cluster 环境。

           Mysql Cluster 的环境主要由一下3部分组成:
          a) 负责管理各个节点的 Manage 节点主机:  --管理节点负责整个 Cluster 集群中各个节点的管理工作,包括集群的配置,启动关闭 
各节点, 以及实施数据的备份恢复等。-->所以他必须是最先被启动的节点 .

           b) SQL 层的 SQL 服务器节点(后面简称为 SQL 节点), 也就是我们常说的 Mysql Server: --  主要负责实现一个数据库在存储层之上的所有事情,比如连接管理,query 优化和响  应,cache 管理等等。可以被认为是一个不需要提供任何存储引擎的 Mysql  服务器,因为他的存储引擎有 Cluster 环境中的 NDB 节点来担任。-->必须要添加 ndbcluster 项,可以添加在  my.cnf 配置文件中,也可以通过启动命令行来指定。

          c) Storage 层的 NDB 数据节点,也就是上面说的 NDB Cluster:-- NDB是一个内存式存储引擎, 他会将所有的数据和索引数据都load到内存中。 但也会将数据持久化到存储设备上。 已经支持用户自己选择数据可以不全  部Load 到内存中了。
               -->NDB 节点主要是实现底层数据存储的功能,保存 Cluster 的数据。每一个 NDB 节点保存 完整数据的一部分(或者一份完整的数据,视节点数目和配置而定-> 受参数控制) ,在 MySQL CLuster 里 面叫 做一个 fragment 。 而每一个 fragment,  正常情况来讲都会在其他的主机上面有一份 (或者多分)完全相同的镜像存在 。这些都是通过配置来完成的,所以只要配置得当,Mysql  Cluster 在存储层不会出现单点的问题。 一般来说, NDB 节点被组织成一个一个的NDB Group  , 一个 NDB Group 实际上就是一组存有完全相同的物理数据的 NDB 节点群

               --> 每个节点都存有全部的数据也可能只保存  一部分数据,主要是受节点数目和参数来控制, 首先在 Mysql Cluster 主配置文件(在管
理节点上面,一般为 config.ini)中,有一个非常重要的参数叫 NoOfReplicas,这个参数  指定了每一份数据被冗余存储在不同节点上面的份数,该参数一般至少应该被设置成 2 , 也 只需要设置成 2 就可以了。 NDB 存储引擎首先保证 NoOfReplicas 参  数配置的要求对数据冗余, 来使用存储节点, 然后再根据节点数目将数据分段来继续使用多  余的 NDB 节点,分段的数目为节点总数除以 NoOfReplicas 所得

            其他存储引擎介绍  :

               ->Merge 存储引擎
              --MERGE 表本身并不存储数据,仅仅只是为多个基表提供一个同意的存储入口,在创  建 MERGE 表的时候,MySQL 只会生成两个较小的文件,一个是.frm 的结构定义文件,还有一 个.MRG 文件,用于存放参与 MERGE 的表的名称(包括所属数据库 schema )。

              --MERGE 表不仅可以提供读取服务,也可以提供写入服务。要让 MERGE 表提供可 INSERT 服务,必须在在表被创建的时候就指明 INSERT 数据要被写入哪一个基表,可以通过  insert_method 参数来控制。如果没有指定该参数,任何尝试往 MERGE 表中 INSERT 数据的 
操作, 都会出错。 此外, 无法通过 MERGE 表直接使用基表上面的全文索引, 要使用全文索 引 , 必须通过基表本身的存取才能实现。

              ->Memory 存储引擎

              --是一个将数据存储在内存中的存储  引擎 ,不会将任何数据存放到磁盘上,仅仅存放了一个表结构相关信息  的.frm 文件在磁盘上面。Memory 表支持索引,并且同时支持 Hash 和 B-Tree 两种格式的索引。
    计算 Memory 表实际需要消耗的内存大小:
    SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)   + SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2) 
    + ALIGN(length_of_row+1, sizeof(char*))

             ->BDB 存储引擎
              --BDB 存储引擎的数据存放也是每个表两个物理文件,一个.frm 和一个.db 的文件,数据  和索引信息都是存放在.db 文件中。此外,BDB 为了实现事务安全,也有自己的 redo 日志, 和 Innodb 一样, 也可以通过参数指定日志文件存放的位置。 在锁定机制方面, BDB 和 Memory  存储引擎一样,实现页级锁定。 。 BDB  在每次启动的时候,都会做一次 check point,并且将之前的所有 redo 日志清空。

             ->FEDERATED 存储引擎
              --FEDERATED 存储引擎所实现的功能,和 Oracle 的 DBLINK 基本相似,主要用来提供对远  程 MySQL 服务器上面的数据的访问借口。如果我们使用源码编译来安装 MySQL,那么必须手 工指定启用 FEDERATED 存储引擎才行,因为 MySQL 默认是不起用该存储引擎的。
     
             ->ARCHIVE 存储引擎
              --ARCHIVE 存储引擎主要用于通过较小的存储空间来存放过期的很少访问的历史数据, ARCHIVE 表不支持索引,通过一个.frm 的结构定义文件,一个.ARZ 的数据压缩文件还有一  个.ARM 的 meta 信息文件。由于其所存放的数据的特殊性,ARCHIVE 表不支持删除修改操  ,仅支持插入和查询操作。锁定机制为行级锁定

               ->BLACKHOLE 存储引擎
        
               --BLACKHOLE 存储引擎是一个非常有意思的存储引擎,功能恰如其名,就是一个“黑洞 ”。  就像我们 unix 系统下面的 “/dev/null ” 设备一样.
                  
                 ->CSV 存储引擎
            
                 --CSV 存储引擎实际上操作的就是一个标准的 CSV 文件,他不支持索引。起主要用途就是  大家有些时候可能会需要通过数据库中的数据导出成一份报表文件, 而 CSV 文件是很多软件  都支持的一种较为标准的格式, 所以我们可以通过先在数据库中建立一张 CVS 表, 然后将生  成的报表信息插入到该表,即可得到一份 CSV 报表文件.


                

第 4  章 ,MySQL 安全管理:      
   
                   -> 权限级别
               
      MySQL 中的权限分为五个级别,分别如下:
       
      1、Global Level:Global Level 的权限控制又称为全局权限控制,所有权限信息都保存在 mysql.user 表  中.Global Level 的所有权限都是针对整个 mysqld 的,对所有的数据库下的所有表及所有  字段都有效。 
       
        

      要授予 Global Level 的权限,则只需要在执行 GRANT 命令的时候,用“*.* ” 来指定适用范围是 Global 的即可,当有多个权限需要授予的时候,也并不需要多次重复执行 GRANT命令,只需要一次将所有需要的权限名称通过逗号( “, ” )分隔开即可,如下: 
          mysql >  GRANT SELECT,UPDATE,DELETE,INSERT ON *.*   TO 'def'@'localhost';

        2、Database Level : 在 Global Level 之下,其他三个 Level 之上的权限级别,其作用域  即为所指定整个数据库中的所有对象 。与 Global Level 的权限相比,Database Level 主要  少了以下几个权限: CREATE USER , FILE , PROCESS , RELOAD , REPLICATION CLIENT , REPLICATION  SLAVE,SHOW DATABASES,SHUTDOWN,SUPER 和 USAGE 这几个权限

       -- 如果要授予 Database Level 的权限,则可以有两种实现方式: 
           a、在执行 GRANT 命令的时候,通过“database.* ” 来限定权限作用域为 database 整个 数据库,如下:
            mysql >  GRANT ALTER ON test.* TO 'def'@'localhost';
            mysql >  SHOW GRANTS FOR   def@localhost ;

           b、先通过 USE 命令选定需要授权的数据库,然后通过“*”来限定作用域,这样授权的  作用域实际上就是当前选定的整个数据库。

              mysql > USE test;
              mysql >  GRANT DROP ON * TO 'def'@'localhost';
              mysql >  SHOW GRANTS FOR  def@localhost ;
    --在授予权限的时候, 如果有相同的权限需要授予多个用户, 我们也可以在授权语句中一  次写上多个用户信息,通过逗号(,)分隔开就可以了,如下:
               mysql > grant create on perf.* to   'abc'@'localhost','def'@'localhost';
               mysql   SHOW GRANTS FOR  def@localhost ;
                mysql   SHOW GRANTS FOR abc @localhost ;

       3、Table Level : Database Level 之下就是 Table Level 的权限了,Table Level 的权限可以 Global   Level 和 Database Level 的权限所覆盖,同时也能覆盖 Column Level 和 Routine Level 的 权限。
           --Table Level 的权限由于其作用域仅限于某个特定的表,所以权限种类也比较少,仅有  ALTER,CREATE,DELETE,DROP,INDEX,INSERT,SELECT UPDATE 这八种权限.

   
       4、Column Level:  针对 Column Level 级别的  权限仅有INSERT , SELECT和UPDATE 这三种     
              
       5、Routine Level:  Routine Level 的权限主要只有 EXECUTE 和 ALTER ROUTINE 两种,主要针对的对象是  procedure 和 function 这两种对象,在授予 Routine Level 权限的时候,需要指定数据库  和相关对象,如:

             mysql > GRANT EXECUTE ON test.p1 to   'abc'@'localhost';
       
       --此外,我们还可以通过 GRANT ALL 语句授予某个 Level 的所有可用权限给某个用户



            ->访问控制实现原理

   

    1、 用户管理  :  所有授权用户都存放在一个系统表中:mysql.user 用户管理模块需要使用的信息很少,主要就是  Host,User,Password 这三项,都在 mysql.user 表中。一个用户要想访问 MySQL,至少需要提供上面列出的这三项数据。
        -- 其中 Host 信息存放的是 MySQL 允许所对应的  User 的信任主机,可以是某个具体的主机名(如:mytest )或域名(如:  www.domain.com ),也可以是以“% ” 来充当通配符的某个域名集合(如:%.domain.com ) ;也可以是一个具体 的 IP 地址( 如: 1.2.3.4),同样也可以是存在通配符的域名集合( 如: 1.2.3.%) ;还可以用 “% ” 来代表任何主机,就是不对访问者的主机做任何限制。如以下设置

       mysql >  SELECT host,user,password FROM user ORDER BY   user;
    
       --但是这里有一个比较特殊的访问限制, 如果要通过 localhost 访问的话, 必须要有一条  专门针对 localhost 的授权信息, 即使不对任何主机做限制也不行。    但是当通过-h 参数,明确指定了访问的主机地址之后就没问题了,如下:  sky@sky :~$ mysql -u def -p -h 127.0.0.1

  2、 访问控制: 
    
      
     


第五章,Mysql备份恢复

          确保 MySQL 打开 log-bin 选项,有了 BINLOG,MySQL 才可以在必要的时候做完 整恢复,或基于时间点的恢复,或基于位置的恢复。
 
          -> MyISAM 存储引擎备份:  MyISAM 存储引擎的物理备份,除了备  份 MySQL 系统的共有物理文件之外,还需备份 记录表结构元数据的“.frm”文  件,存储表数据的“.MYD”文件,以及存储索引数据的“.MYI”文件
    
          ->Innodb 存储引擎备份:  存放数据位置  的配置 为 ”innodb_data_home_dir ”,“ innodb_data_file_path ” 和 
“innodb_log_group_home_dir ” 这三个目录位置指定参数,以及另外一个决定 Innodb 的表 空间存储方式的参数 “innodb_file_per_table ” 。 前面三个参数指定了数据和日志文件的存 放位置,最后一个参数决定 Innodb 是以共享表空间存放数据还是以独享表空间方式存储数
  
              --如果是共享表空间存储方式; 那么innodb需要备份“innodb_data_home_dir”和“innodb_data_file_path”参数所设定的所有数据文件,“datadir”中相应数据库目录下的所有 Innodb 存储引擎表的“.frm”文件;
              --如果是独享表空间存储方式;除了备份上面共享表空间方式所需要备份的所  有文件之外,我们还需要备份“datadir”中相应数据库目录下的所有“.idb”文件,该文 件中存放的才是独享表空间方式下 Innodb 存储引擎表的数据。
              --NDB Cluster 存储引擎备份方式; 的物理备份需要备份的文  件主要有一下三类:
              1、 元数据(Metadata) :包含所有的数据库以及表的定义信息;
              2、 表数据(Table Records) :保存实际数据的文件;
              3、 事务日志数据(Transaction Log) :维持事务一致性和完整性,以及恢复过程中所  需要的事务信息。

              ->NDB Cluster 存储引擎备份方式: NDB Cluster 存储引擎也是一款事务性存储引擎,和 Innodb 一样也有 redo 日志。NDB   Cluter 存储引擎自己提供了备份功能,可以通过相关的命令实现。当然,停机冷备的方法 也是有效的。
              在线联机备份步骤如下
              1、 连接上管理服务器;
              2、 在管理节点上面执行 “START BACKUP” 命令;
              3、 在管理节点上发出备份指令之后,管理节点会通知所有数据节点开始进行备份,并  反馈通知结果。
              4、 管理节点在通知发出备份指令之前会生成一个备份号来唯一定位这次备份所产生  的备份集。当各数据节点收到备份指令之后,就会开始进行备份操作。
              5、 当所有数据节点都完成备份之后, 管理节点才会反馈 “备份完成 ” 的信息给客户 端 。
  
             NDB   Cluster 提供了相应的命令来中断当前正在进行的备份操作,如下
            1、 登录管理节点
            2、 执行 “ABORT BACKUP backup_id ” ,命令中的 backup_id 即之前发起备份命令的  时候所产生的备份号。
            3、 管理结带你上会用消息“放弃指示的备份 backup_id”确认放弃请求,注意,则时  候其实并没有收到数据节点对请求的实际回应。
            4、然后管理节点才会将中断备份的指令发送到所有数据节点上面, 然后当各个数据节  点都中断备份并删除了当前产生的备份文件之后,才会返回“备份 backup_id 因*  **而放弃 ” 。至此,中断备份操作完成。

            --通过 NDB Cluster 存储引擎自己的备份命令来进行备份之后,会将前面所提到的三种  文件存放在参与备份的节点上面,且被存放在三个不同的文件中,类似如下:
            1、 BACKUP-backup_id.node_id.ctl, 内容包含相关的控制信息和元数据的控制文件。 每个  节点均会将相同的表定义(对于 Cluster 中的所有表)保存在自己的该文件中。
            2、BACKUP-backup_id-n.node_id.data,数据备份文件,被分成多个不同的片段来保存,在备份过程中, 不同的节点将保存不同的备份数据所产生的片段, 每个节点保存的文件都会  有信息指明数据所属表的部分, 且在备份片段文件最后还包含了最后的校验信息, 以确保备 份能够正确恢复。
            3、BACKUP-backup_id.node_id.log,事务日志备份文件中仅包含已提 交事务的相关信息,  且仅保存已在备份中保存的表上的事务, 各个阶段所保存的日志信息也不一样, 因为仅仅针 对各节点所包含的数据记录相关的日志信息。
    
  
       备份 : MySQL 中的逻辑备份是将数据库中的数据备份为一个文本文件,备份的文件可以被查  看和编辑。在 MySQL 中,使用 mysqldump 工具来完成逻辑备份



       =>mysqldump逻辑备份 : 
        --备份指定的数据库,或者数据库中某些表;  shell> mysqldump [options] db_name [tables]
        --备份指定的一个或多个数据库; shell> mysqldump [options] ---database DB1 [DB2 DB3...]
        --备份所有数据库 ; shell> mysqldump [options] --all--database
  
   eg:    (1)备份所有数据库:  shell >mysqldump -uroot -p --all-database --compress >/backup/all-database.sql
           (2)备份数据库 test:   shell > mysqldump -uroot -p test > /backup/test.sql
           (3)备份数据库 test 下的表 emp: shell > mysqldump -uroot -p test emp > /backup/emp.sql
           (4)备份数据库 test 下的表 emp 和 dept: shell > mysqldump -uroot -p test emp dept >  /backup/emp_dept.sql
           (5)备份数据库 test 下的所有表为逗号分割的文本,备份到/backup :
                            shell  >mysqldump -uroot -T /backup test emp --fields-terminated-by ','
      --需要强调的是,为了保证数据备份的一致性,MyISAM 存储引擎在备份的时候需要加上-l 参  ,表示将所有表加上读锁,在备份期间,所有表将只能读而不能进行数据更新。但是对于 事务存储引擎(InnoDB 和 BDB)来说可以采用更好的选项--single-transaction,此选项将使 得 InnoDB 存储引擎得到一个快照(Snapshot) ,使得备份的数据能够保证一致性。
            
     -> 完全恢复
      --mysqldump 的恢复也很简单,将备份作为输入执行即可,具体语法如下;  shell>  mysql –uroot –p dbname < bakfile   
     注意,将备份恢复后数据并不完整,还需要将备份后执行的日志进行重做,语法如下: shell>  mysqlbinlog binlog-file | mysql -u root –p***   
     以下是一个完整的 mysqldump 备份与恢复的例子。
       1)上午 9 点,备份数据库: shell > mysqldump -uroot –p –l –F test >test.dmp 
         --其中-l 参数表示给所有表加读锁,-F 表示生成一个新的日志文件.
       2)使用 mysqlbinlog 恢复自 mysqldump 备份以来的 BINLOG。 shell > mysqlbinlog localhost-bin.000015 | mysql -u root –p test
  至此,数据库完全恢复

  -> 基于时间点恢复
 --由于误操作,比如误删除了一张表,这时使用完全恢复是没有用的,因为日志里面还存  在误操作的语句,我们需要的是恢复到误操作之前的状态,然后跳过误操作语句,再恢复后  面执行的语句,完成我们的恢复。这种恢复叫不完全恢复, 在 MySQL 中,不完全恢复分为  基于时间点的恢复和基于位置的恢复

      以下是基于时间点恢复的操作步骤:
   (1)如果上午 10 点发生了误操作,可以用以下语句用备份和 BINLOG 将数据恢复到故 障前
   shell > mysqlbinlog --stop-date="2005-04-20 9:59:59" /var/log/mysql/bin.123456 | mysql -u  root –pmypwd
    (2)跳过故障时的时间点,继续执行后面的 BINLOG,完成恢复 :
   shell > mysqlbinlog --start-date="2005-04-20 10:01:00" /var/log/mysql/bin.123456| mysql -u  root -pmypwd 

      ->基于位置恢复
     --基于时间点的恢复类似, 但是更精确: 
     1)在 shell 下执行如下命令  : shell > mysqlbinlog --start-date="2005-04-20 9:55:00" --stop-date="2005-04-20 10:05:00"
/var/log/mysql/bin.123456 > /backup/mysql_restore.sql
     --该命令将在/backup 目录创建小的文本文件,编辑此文件,找到出错语句前后的位置号,例如前后位置号分别是 368312 和 368315。

     2)恢复了以前的备份文件后,应从命令行输入下面内容 : 
   shell >mysqlbinlog --stop-position="368312" /var/log/mysql/bin.123456  | mysql -u root -pmypwd
   shell >mysqlbinlog --start-position="368315" /var/log/mysql/bin.123456  | mysql -u root -pmypwd 
   --上面的第一行将恢复到停止位置为止的所有事务。 下一行将恢复从给定的起始位置直到二进  制日志结束的所有事务。因为 mysqlbinlog 的输出包括每个 SQL 语句记录之前的 SET   TIMESTAMP 语句,因此恢复的数据和相关 MySQL 日志将反应事务执行的原时间。


       => 物理备份和恢复:
    --物理备份又分为冷备份和热备份两种, 和逻辑备份相比, 它的最大优点是备份和恢复的速度  更快,因为物理备份的原理都是基于文件的 cp。

      MyISAM  存储引擎热备 :
      方法 1:使用 mysqlhotcopy 自带热备工具 :   shell >  mysqlhotcopy db_name [/path/to/new_directory]
      方法 2:手工锁表 copy :
      --在 mysqlhotcopy 使用不正常的情况下,可以手工来做热备份,操作步骤如下: 首先数据库中所有表加读锁:mysql>flush tables for read ;
 然后 cp 数据文件到备份目录即可

      InnoDB 存储引擎
      ibbackup 是 Innobase 公司( www.innodb.com )的一个热备份工具,专门对 InnoDB 存  储引擎进行物理热备份,此工具是收费。
 下面简单介绍一下使用 ibbackup 工具的备份步骤。
(1)编辑用于启动的配置文件 my.cnf 和用于备份的配置文件 backup-my.cnf。
  my.cnf 的例子如下:
[mysqld]
datadir = /home/heikki/data
innodb_data_home_dir = /home/heikki/data
innodb_data_file_path = ibdata1:100M;ibdata2:200M;ibdata3:500M:autoextend
innodb_log_group_home_dir = /home/heikki/data
set-variable = innodb_log_files_in_group=2
set-variable = innodb_log_file_size=20M
(2)如果想备份到/home/heikki/backup,则 backup-my.cnf 的例子如下。
[mysqld]
datadir = /home/heikki/backup
innodb_data_home_dir = /home/heikki/backup
innodb_data_file_path = ibdata1:100M;ibdata2:200M;ibdata3:500M:autoextend
innodb_log_group_home_dir = /home/heikki/backup
set-variable = innodb_log_files_in_group=2
set-variable = innodb_log_file_size=20M
(3)开始备份,具体如下:
$  ibbackup /home/pekka/my.cnf /home/pekka/backup-my.cnf
注意:ibbackup 工具不会覆盖任何重名的文件,因此在新的备份开始之前,需要确保备份目录中 没有重名文件,否则备份很可能会失败。
当主数据库出现故障时,我们需要用备份进行恢复,恢复的步骤如下。
(1)进行日志重做。如前面所述,利用下面的命令对备份数据进行日志重做。
shell>ibbackup --apply-log /home/pekka/backup-my.cnf
(2)恢复后重启数据库服务:
shell>./bin/mysqld_saft --defaults-file=/home/pekka/backup-my.cnf &
(3)服务重启后,利用 BINLOG 日志将备份点与故障点之间的剩余数据进行恢复。
mysqlbinlog binlog-file | mysql -u root –p***
ibbackup 还有一些其他的功能,比如压缩备份、不完全恢复等。


     ->表的导入导出: 
 --在某些情况下, 为了一些特定的目的, 经常需要将表里的数据导出为某些符号分割的纯数据 文本,而不是 SQL 语句。这些应用可能有以下一些:

     用来作为 EXCEL 显示;
     单纯为了节省备份空间;
     为了快速的加载数据,LOAD DATA 的加载速度比普通的 SQL 加载要快 20 倍以上。

方法一: 使用select ... into outfile ...  命令来导出数据,具体语法如下;         
 mysql> SELECT * FROM tablename INTO OUTFILE 'target_file' [option];

其中 option 参数可以是以下选项:
   FIELDS TERMINATED BY 'string' (字段分隔符,默认为制表符’\t’) ;
   FIELDS [OPTIONALLY] ENCLOSED BY 'char'(字段引用符,如果加 OPTIONALLY 选项则只用在 char、  varchar 和 text 等字符型字段上。默认不使用引用符) ; 
   FIELDS ESCAPED BY 'char' (转义字符,默认为’\’) ;
   LINES STARTING BY 'string' (每行前都加此字符串,默认'') ;
   LINES TERMINATED BY 'string'(行结束符,默认为’\n’) ;
   其中 char 表示此符号只能是单个字符,string 表示可以是字符串。
   --其中 char 表示此符号只能是单个字符,string 表示可以是字符串。

eg:  例如,将 emp 表中数据导出为数据文本,其中,字段分隔符为“,” ,字段引用符为“”” (双  引号) ,记录结束符为回车符,具体实现如下:

mysql > select * from emp into outfile '/tmp/emp.txt' fields terminated by "," enclosed by  '"' ;

   发现第一列是数值型,如果不希望字段两边用引号引起,则语句改为:
   mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by "," optionally enclosed by '"' ;


方法 2:用 mysqldump 导出数据为文本
 shell >  mysqldump –u username –T target_dir dbname tablename [option]
   其中 option 参数可以是以下选项:
   --fields-terminated-by=name(字段分隔符) ;
   --fields-enclosed-by=name(字段引用符) ;
   --fields-optionally-enclosed-by=name(字段引用符,只用在 char、varchar 和 text 等字符  型字段上) ; 
   --fields-escaped-by=name(转义字符) ;
   --lines-terminated-by=name(记录结束符) 。

eg:  下面的例子中,采用 mysqldump 生成了指定分隔符分隔的文本:

  shell > mysqldump -uroot -T /tmp test emp --fields-terminated-by ','  --fields-optionally-enclosed-by '"'
   --除了生成数据文件 emp.txt 之外, 还生成一个 emp.sql文件, 里面记录了 emp 表的创建脚本。



  -> 导入: 
   导入也有两种不同的方法, 分别是 LOAD DATA INFILE…和 mysqlimport
  它们的本质是一样的, 区别只是在于一个在 MySQL 内部执行, 另一个在 MySQL 外部执行。 

  方法一: 使用“LOAD DATA INFILE…”命令。
    mysql > LOAD DATA [LOCAL] INFILE ‘filename’ INTO TABLE tablename [option]
     option 可以是以下选项:
   FIELDS TERMINATED BY 'string'(字段分隔符,默认为制表符'\t') ;
   FIELDS [OPTIONALLY] ENCLOSED BY 'char'(字段引用符,如果加 OPTIONALLY 选项则只用  在 char、varchar 和 text 等字符型字段上。默认不使用引用符) ; 
   FIELDS ESCAPED BY 'char'(转义字符,默认为'\') ;
   LINES STARTING BY 'string'(每行前都加此字符串,默认'') ;
   LINES TERMINATED BY 'string'(行结束符,默认为'\n') ;
   IGNORE number LINES(忽略输入文件中的前 n 行数据) ;
   (col_name_or_user_var,...) (按照列出的字段顺序和字段数量加载数据) ;
   SET col_name = expr,...  将列做一定的数值转换后再加载。
    其中 char 表示此符号只能是单个字符,string 表示可以是字符串。
FILELD 和 LINES 和前面 SELECT …INTO OUTFILE…的含义完全相同, 不同的是多了几个不同的选  项,下面的例子将文件“/tmp/emp.txt”中的数据加载到表 emp 中: 
      mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ',' enclosed by  '"' ;

   如果不希望加载文件中的前两行,可以如下操作:
   mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ',' enclosed by  '"' ignore 2 lines;

   如果发现文件中的列顺序和表中的列顺序不符, 或者只想加载部分列, 可以在命令行中加上 列的顺序,如下例所示:

   mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ',' enclosed by   '"' ignore 2 lines (id,content,name);

   如果只想加载第一列,字段的列表里面可以只加第一列的名称
  mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ',' enclosed by   '"' ignore 2 lines (id);

  如果希望将 id 列的内容+10 后再加载到表中,可以如下操作
  mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ',' enclosed by  '"' set id=id+10;


 方法 2:用 mysqlimport 来实现,具体命令如下
  shell>mysqlimport –u root –p*** [--LOCAL] dbname order_tab.txt [option] 

   其中 option 参数可以是以下选项: 
    --fields-terminated-by=name(字段分隔符) ;
    --fields-enclosed-by=name(字段引用符) ;
    --fields-optionally-enclosed-by=name(字段引用符,只用在 char、varchar 和 text 等字符  型字段上) ; 
    --fields-escaped-by=name(转义字符) ;
    --lines-terminated-by=name(记录结束符) ;
    -- ignore-lines=number(或略前几行) 。
这与 mysqldump 的选项几乎完全相同.

shell > mysqlimport -uroot test /tmp/emp.txt --fields-terminated-by=','   --fields-enclosed-by='"'
shell > mysql -uroot test -e 'select * from emp'

注意: :如果导入和导出是跨平台操作的(Windows 和 Linux) ,那么要注意设置参数
line-terminated-by , Windows 上 设 置 为 line-terminated-by=’\r\n’ , Linux 上 设 置 为
line-terminated-by=’\n’。




第六章 ,mysql 复制

   --MySQL 支持一台主服务器同时向多台从服务器进行复制,从服务器同时也可以作为其  他服务器的主服务器,实现链状的复制。
  MySQL 复制的优点主要包括以下 3 个方面:
  1) 如果主服务器出现问题,可以快速切换到从服务器提供服务;
  2) 可以在从服务器上执行查询操作,降低主服务器的访问压力;
  3) 可以在从服务器上执行备份,以避免备份期间影响主服务器的服务。

注意:由于 MySQL 实现的是异步的复制,所以主从服务器之间存在一定的差距,在从服务器上  进行的查询操作需要考虑到这些数据的差异,一般只有更新不频繁的数据或者对实时性  要求不高的数据可以通过从服务器查询,实时性要求高的数据仍然需要从主数据库获得。

       --MYSQL复制是指将主数据的  DDL,DML通过二进制binary日志传 到复制服务器(也叫从服务器)上,然后在从服务器上对这些日志重新执行(也叫重做)。
     


    一主一从配置 or 一主多从: 

    1)确保主从服务器上安装了相同版本的数据库。因为复制的功能在持续的改进中,所  以在可能的情况下推荐安装最新的稳定版本。
    2)在主服务器上,设置一个复制使用的账户,并 授予 REPLICATION SLAVE 权限
      --在这里如果报错: ERROR 1364 (HY000): Field 'ssl_cipher' doesn't have a default value  ? 则需要在my.cnf 或者my.init上配置参数: 
           sql-mode=STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
     修改为
          sql-mode=NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION 
     然后重启MYSQL

     3)修改 主数据库服务器的配置文件 my.cnf,开 启 BINLOG,并设置 server-id 的值。这  两个参数的修改需要重新启动数据库服务才可以生效。
      my.cnf 配置:
[mysqld]
log-bin = /home/mysql/log/mysql-bin.log       -->必须开启。
server-id = 1       -->这个值手动设置,每个节点唯一。

   4)在主服务器上,设置读锁定有效,这个操作是为了确保没有数据库操作,以便获得  一个一致性的快照:
      mysql> flush tables with read lock;

   5) 然后得到主服务器上当前的二进制日志名和偏移量值。 这个操作的目的是为了在从  数据库启动以后,从这个点开始进行数据的恢复。  -->( 一个是file 编号,一个是 position 值

mysql> show master status;
+------------------+----------+--------------+------------------+
File | Position  | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
mysql-bin.000039  |  102  | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

   6)备份主库上的数据文件到 备库中,如果是使用mysqdump 最好一个库一个库备份。 也可以直接在操作系统下 cp 全部的数据文件到从数据库服务器上,也可以通过  mysqldump 导出数据或者使用 ibbackup 工具进行数据库的备份。

    7) 主数据库的备份完毕后,主数据库可以恢复写操作,剩下的操作只需要在从服务器  上执行:
  mysql> unlock tables;

   8)将主数据库的一致性备份恢复到从数据库上。
   9)修改从数据库的配置文件 my.cnf,增加 server-id 参数。注意 server-id 的值必须是  唯一的,不能和主数据库的配置相同,如果有多个从数据库服务器,每个从数据库服务器必 须有自己唯一的 server-id 值。
   
    这里备库1 配置:
    my.cnf 中修改:
   [mysqld]
    server-id = 2

   10)在从服务器上,使用--skip-slave-start 选项启动从数据库,这样不会立即启动从数  据库服务上的复制进程,方便我们对从数据库的服务进行进一步的配置:
[mysql@master1 ]$ ./bin/mysqld_safe --skip-slave-start &   或者:  shell# /etc/init.d/mysqld start --skip-slave-start

  11)对从数据库服务器做相应设置,指定复制使用的用户,主数据库服务器的 IP、端 口以及开始执行复制的日志文件和位置等,具体语法如下: 
mysql> CHANGE MASTER TO    
-> MASTER_HOST='master_host_name',                           -->主机host(IP)
-> MASTER_USER='replication_user_name',                     -->复制的用户user( 如果是主从从,指定的复制用户必须不同)
-> MASTER_PASSWORD='replication_password',            -->复制用户的密码
-> MASTER_LOG_FILE='recorded_log_file_name',             -->对应第5步的 file 编号。
-> MASTER_LOG_POS=recorded_log_position,                 -->对应的POS编号
-> MASTER_PORT=3308;
 
  12)在从服务器上,启动 slave 线程:
mysql> start slave;

  13)这时 slave 上执行 show processlist 命令将显示类似如下进程:
mysql> show processlist \G

  14) 查看master 进程状态: mysql > show master status \G  
   主要查看: Slave_IO_Running 和 Slave_SQL_Running  是否都为YES 
  ==> 如果是一主多从  一样配置。



深入了解复制

已经讨论了关于复制的一些基本东西,下面深入讨论一下复制。

3.1、基于语句的复制(Statement-Based Replication)

     MySQL 5.0及之前的版本仅支持基于语句的复制(也叫做逻辑复制,logical replication),这在数据库并不常见。master记录下改变数据的查询,然后,slave从中继日志中读取事件,并执行它,这些SQL语句与master执行的语句一样。
这种方式的优点就是实现简单。此外,基于语句的复制的二进制日志可以很好的进行压缩,而且日志的数据量也较小,占用带宽少——例如,一个更新GB的数据的查询仅需要几十个字节的二进制日志。而mysqlbinlog对于基于语句的日志处理十分方便。
 
      但是,基于语句的复制并不是像它看起来那么简单,因为一些查询语句依赖于master的特定条件,例如,master与slave可能有不同的时间。所以,MySQL的二进制日志的格式不仅仅是查询语句,还包括一些元数据信息,例如,当前的时间戳。即使如此,还是有一些语句,比如,CURRENT USER函数,不能正确的进行复制。此外,存储过程和触发器也是一个问题。
     另外一个问题就是基于语句的复制必须是串行化的。这要求大量特殊的代码,配置,例如InnoDB的next-key锁等。并不是所有的存储引擎都支持基于语句的复制。

3.2、基于记录的复制(Row-Based Replication)

      MySQL增加基于记录的复制,在二进制日志中记录下实际数据的改变,这与其它一些DBMS的实现方式类似。这种方式有优点,也有缺点。优点就是可以对任何语句都能正确工作,一些语句的效率更高。主要的缺点就是二进制日志可能会很大,而且不直观,所以,你不能使用mysqlbinlog来查看二进制日志。
对于一些语句,基于记录的复制能够更有效的工作,如:
mysql> INSERT INTO summary_table(col1, col2, sum_col3)
    -> SELECT col1, col2, sum(col3)
    -> FROM enormous_table
    -> GROUP BY col1, col2;
     假设,只有三种唯一的col1和col2的组合,但是,该查询会扫描原表的许多行,却仅返回三条记录。此时,基于记录的复制效率更高。
    另一方面,下面的语句,基于语句的复制更有效:
 mysql> UPDATE enormous_table SET col1 = 0;
此时使用基于记录的复制代价会非常高。由于两种方式不能对所有情况都能很好的处理,所以,MySQL 5.1支持在基于语句的复制和基于记录的复制之前动态交换。你可以通过设置session变量binlog_format来进行控制。

3.3、复制相关的文件

除了二进制日志和中继日志文件外,还有其它一些与复制相关的文件。如下:
(1)mysql-bin.index
服务器一旦开启二进制日志,会产生一个与二日志文件同名,但是以.index结尾的文件。它用于跟踪磁盘上存在哪些二进制日志文件。MySQL用它来定位二进制日志文件。它的内容如下(我的机器上):

 (2)mysql-relay-bin.index
该文件的功能与mysql-bin.index类似,但是它是针对中继日志,而不是二进制日志。内容如下:
.\mysql-02-relay-bin.000017
.\mysql-02-relay-bin.000018
(3)master.info
保存master的相关信息。不要删除它,否则,slave重启后不能连接master。内容如下(我的机器上):

 I/O线程更新master.info文件,内容如下(我的机器上):

 

.\mysql-02-relay-bin.000019

254

mysql-01-bin.000010

286

0

52813

 (4)relay-log.info 
包含slave中当前二进制日志和中继日志的信息。

3.4、发送复制事件到其它slave

当设置log_slave_updates时,你可以让slave扮演其它slave的master。此时,slave把SQL线程执行的事件写进行自己的二进制日志(binary log),然后,它的slave可以获取这些事件并执行它。如下:

 

3.5、复制过滤(Replication Filters)

复制过滤可以让你只复制服务器中的一部分数据,有两种复制过滤:在master上过滤二进制日志中的事件;在slave上过滤中继日志中的事件。如下:


4、复制的常用拓扑结构

复制的体系结构有以下一些基本原则:
(1)    每个slave只能有一个master;
(2)    每个slave只能有一个唯一的服务器ID;
(3)    每个master可以有很多slave;
(4)    如果你设置log_slave_updates,slave可以是其它slave的master,从而扩散master的更新。

MySQL不支持多主服务器复制(Multimaster Replication)——即一个slave可以有多个master。但是,通过一些简单的组合,我们却可以建立灵活而强大的复制体系结构。

4.1、单一master和多slave

由一个master和一个slave组成复制系统是最简单的情况。Slave之间并不相互通信,只能与master进行通信。

在实际应用场景中,MySQL复制90%以上都是一个Master复制到一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。因为只要Master和Slave的压力不是太大(尤其是Slave端压力)的话,异步复制的延时一般都很少很少。尤其是自从Slave端的复制方式改成两个线程处理之后,更是减小了Slave端的延时问题。而带来的效益是,对于数据实时性要求不是特别Critical的应用,只需要通过廉价的pcserver来扩展Slave的数量,将读压力分散到多台Slave的机器上面,即可通过分散单台数据库服务器的读压力来解决数据库端的读性能瓶颈,毕竟在大多数数据库应用系统中的读压力还是要比写压力大很多。这在很大程度上解决了目前很多中小型网站的数据库压力瓶颈问题,甚至有些大型网站也在使用类似方案解决数据库瓶颈。

如下:

 如果写操作较少,而读操作很时,可以采取这种结构。你可以将读操作分布到其它的slave,从而减小master的压力。但是,当slave增加到一定数量时,slave对master的负载以及网络带宽都会成为一个严重的问题。
这种结构虽然简单,但是,它却非常灵活,足够满足大多数应用需求。一些建议:
(1)    不同的slave扮演不同的作用(例如使用不同的索引,或者不同的存储引擎);
(2)    用一个slave作为备用master,只进行复制;
(3)    用一个远程的slave,用于灾难恢复;
 

大家应该都比较清楚,从一个Master节点可以复制出多个Slave节点,可能有人会想,那一个Slave节点是否可以从多个Master节点上面进行复制呢?至少在目前来看,MySQL是做不到的,以后是否会支持就不清楚了。

MySQL不支持一个Slave节点从多个Master节点来进行复制的架构,主要是为了避免冲突的问题,防止多个数据源之间的数据出现冲突,而造成最后数据的不一致性。不过听说已经有人开发了相关的patch,让MySQL支持一个Slave节点从多个Master结点作为数据源来进行复制,这也正是MySQL开源的性质所带来的好处。


4.2、主动模式的Master-Master(Master-Master in Active-Active Mode)

Master-Master复制的两台服务器,既是master,又是另一台服务器的slave。这样,任何一方所做的变更,都会通过复制应用到另外一方的数据库中。

可能有些读者朋友会有一个担心,这样搭建复制环境之后,难道不会造成两台MySQL之间的循环复制么?实际上MySQL自己早就想到了这一点,所以在MySQL的BinaryLog中记录了当前MySQL的server-id,而且这个参数也是我们搭建MySQLReplication的时候必须明确指定,而且Master和Slave的server-id参数值比需要不一致才能使MySQLReplication搭建成功。一旦有了server-id的值之后,MySQL就很容易判断某个变更是从哪一个MySQLServer最初产生的,所以就很容易避免出现循环复制的情况。而且,如果我们不打开记录Slave的BinaryLog的选项(--log-slave-update)的时候,MySQL根本就不会记录复制过程中的变更到BinaryLog中,就更不用担心可能会出现循环复制的情形了。

 
如图:

主动的Master-Master复制有一些特殊的用处。例如,地理上分布的两个部分都需要自己的可写的数据副本。这种结构最大的问题就是更新冲突。假设一个表只有一行(一列)的数据,其值为1,如果两个服务器分别同时执行如下语句:
在第一个服务器上执行:
mysql> UPDATE tbl SET col=col + 1;
在第二个服务器上执行:
mysql> UPDATE tbl SET col=col * 2;
那么结果是多少呢?一台服务器是4,另一个服务器是3,但是,这并不会产生错误。
实际上,MySQL并不支持其它一些DBMS支持的多主服务器复制(Multimaster Replication),这是MySQL的复制功能很大的一个限制(多主服务器的难点在于解决更新冲突),但是,如果你实在有这种需求,你可以采用MySQL Cluster,以及将Cluster和Replication结合起来,可以建立强大的高性能的数据库平台。但是,可以通过其它一些方式来模拟这种多主服务器的复制。

4.3、主动-被动模式的Master-Master(Master-Master in Active-Passive Mode)

这是master-master结构变化而来的,它避免了M-M的缺点,实际上,这是一种具有容错和高可用性的系统。它的不同点在于其中一个服务只能进行只读操作。如图:
 
 

4.4 级联复制架构 Master –Slaves - Slaves

在有些应用场景中,可能读写压力差别比较大,读压力特别的大,一个Master可能需要上10台甚至更多的Slave才能够支撑注读的压力。这时候,Master就会比较吃力了,因为仅仅连上来的SlaveIO线程就比较多了,这样写的压力稍微大一点的时候,Master端因为复制就会消耗较多的资源,很容易造成复制的延时。

遇到这种情况如何解决呢?这时候我们就可以利用MySQL可以在Slave端记录复制所产生变更的BinaryLog信息的功能,也就是打开—log-slave-update选项。然后,通过二级(或者是更多级别)复制来减少Master端因为复制所带来的压力。也就是说,我们首先通过少数几台MySQL从Master来进行复制,这几台机器我们姑且称之为第一级Slave集群,然后其他的Slave再从第一级Slave集群来进行复制。从第一级Slave进行复制的Slave,我称之为第二级Slave集群。如果有需要,我们可以继续往下增加更多层次的复制。这样,我们很容易就控制了每一台MySQL上面所附属Slave的数量。这种架构我称之为Master-Slaves-Slaves架构

这种多层级联复制的架构,很容易就解决了Master端因为附属Slave太多而成为瓶颈的风险。下图展示了多层级联复制的Replication架构。

当然,如果条件允许,我更倾向于建议大家通过拆分成多个Replication集群来解决

上述瓶颈问题。毕竟Slave并没有减少写的量,所有Slave实际上仍然还是应用了所有的数据变更操作,没有减少任何写IO。相反,Slave越多,整个集群的写IO总量也就会越多,我们没有非常明显的感觉,仅仅只是因为分散到了多台机器上面,所以不是很容易表现出来。

此外,增加复制的级联层次,同一个变更传到最底层的Slave所需要经过的MySQL也会更多,同样可能造成延时较长的风险。

而如果我们通过分拆集群的方式来解决的话,可能就会要好很多了,当然,分拆集群也需要更复杂的技术和更复杂的应用系统架构。


 4.5、带从服务器的Master-Master结构(Master-Master with Slaves)

这种结构的优点就是提供了冗余。在地理上分布的复制结构,它不存在单一节点故障问题,而且还可以将读密集型的请求放到slave上。

 

级联复制在一定程度上面确实解决了Master因为所附属的Slave过多而成为瓶颈的问题,但是他并不能解决人工维护和出现异常需要切换后可能存在重新搭建Replication的问题。这样就很自然的引申出了DualMaster与级联复制结合的Replication架构,我称之为Master-Master-Slaves架构

和Master-Slaves-Slaves架构相比,区别仅仅只是将第一级Slave集群换成了一台单独的Master,作为备用Master,然后再从这个备用的Master进行复制到一个Slave集群。

这种DualMaster与级联复制结合的架构,最大的好处就是既可以避免主Master的写入操作不会受到Slave集群的复制所带来的影响,同时主Master需要切换的时候也基本上不会出现重搭Replication的情况。但是,这个架构也有一个弊端,那就是备用的Master有可能成为瓶颈,因为如果后面的Slave集群比较大的话,备用Master可能会因为过多的SlaveIO线程请求而成为瓶颈。当然,该备用Master不提供任何的读服务的时候,瓶颈出现的可能性并不是特别高,如果出现瓶颈,也可以在备用Master后面再次进行级联复制,架设多层Slave集群。当然,级联复制的级别越多,Slave集群可能出现的数据延时也会更为明显,所以考虑使用多层级联复制之前,也需要评估数据延时对应用系统的影响。

  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL性能调优架构设计》是一本介绍MySQL数据库性能优化和架构设计的指南。MySQL是一种常用的开源关系型数据库管理系统,广泛应用于互联网、企业和各种应用程序中。但是,在实际应用中,由于数据量的增加和访问负载的变化等原因,MySQL的性能会受到影响,为此需要进行相应的调优和架构设计。 该PDF文件主要介绍了如何通过调优和优化来提高MySQL的性能。首先,它详细介绍了MySQL的架构和基本原理,包括MySQL的体系结构、并发控制、索引优化等。然后,它介绍了如何通过优化查询、优化索引、优化表结构、对数据库进行分库分表等来提高MySQL的性能。此外,还介绍了如何选择合适的硬件和操作系统、配置参数等,以提高MySQL的性能。 此外,该PDF还介绍了MySQL的高可用性架构设计,包括主从复制、主从链式复制、多主复制等。这些架构设计可以提高MySQL的可用性和容错能力,确保数据的安全性和持久性。 总之,MySQL性能调优架构设计是一个重要的课题,涉及到数据库的整体性能和稳定性。对于那些需要处理大量数据和高并发的应用程序来说,MySQL性能调优架构设计是至关重要的,可以提高系统的响应速度和可靠性,保证系统的稳定运行。这本PDF文件详细介绍了MySQL性能调优架构设计的方法和技巧,对开发人员和系统管理员都是很有参考价值的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值