MySQL

MySql体系结构

一,连接层功能:

1,TCP/IP或者Socket的链接方式

2,验证用户名密码功能

3,连接线程(客服):接收SQL语句,返回执行结果

 

二,SQL层

1,语法检查模块,检查上层发过来的SQL语句,进行语法检查

2,权限检查模块,检测当前登录用户是否有权限操作数据库对象

3,语义检查模块,识别语句种类

4,解析器,解析出SQL语句所有可能的执行方式,这些方式被称为“执行计划”

5,优化器,基于执行代价(系统资源的消耗作为维度(cpu、内存、IO),管理员可以通过间接的方法,干扰优化器的选择)

6,执行器,按照优化器选择的“最优”的执行计划,执行SQL语句。得出结论:某某磁盘的某某位置,发送给存储引擎层。

7,提供查询缓存:有局限性。一般会用Redis产品来替代

8,记录查询日志

   

SQL语句的分类:

DDL:数据定义语言

DCL:数据控制语言

DML:数据操作语言

DQL:数据查询语言

 

三,存储引擎层:

和“磁盘”(文件系统)打交道的层次

根据SQL层执行的结果,去磁盘上找到对应的数据。结构化成表的模式,返回给用户。

  

MySql逻辑结构组成:

一,库(库名字,库属性)

 二,库(库名字,列(列名字,列属性)表属性,表数据)

 

MySQL索引

  MySQL索引分类

存储引擎管理

一,索引管理以及原理

1,索引的种类

B树(B+tree  B*tree b-tree)

B-tree:针对某个明确值的查询

查找顺序:根节点——>枝节点——>叶子节点

B+tree:针对明确的范围的查询

缺点:无法同时包含回表查询以及其它列的查询

 

辅助索引:(B TREE)

alter table t1 add index idx_num(telnum);

怎么生成的:

根据创建索引时,指定的列的值,进行排序后,存储在叶子节点中

优点:

1,优化了查询,减少CPU 内存  IO消耗

2,减少了文件排序

 

覆盖索引:(联合索引)

通过一个索引列把需要查询的列都添加到索引树里面去

直接在索引树里面直接有,减少或尽量避免回表查询操作

优点:减少回表查询的操作的几率

聚集索引

同一等级情况下效率最高

大部分情况下辅助索引和聚集索引结合使用

辅助索引:where 条件   有id列的时候,比如id=28

随机读​ 顺序读

建表时,如果有主键列,自动生成聚集索引

没有主键列,会去找unique列

优点:

减少回表查询

将随机IO转换成顺序IO

加强了缓存的应用,查询效率提升

 

2,R树

3,hash索引

4,全文索引

2,B树索引的类型

  1,聚簇索引(cluster index):一般是基于主键的

  2,辅助索引(普通辅助索引:回表查询;覆盖索引;不回表查询;唯一性索引)

  3,唯一索引

3,索引管理

索引的作用:在mysql数据库中,索引是用来优化查询的

除缓存之外,数据的查询有两种方式:

1,全表扫描

2,索引扫描

优化器索引扫描要优于全表扫描

索引管理:

索引就是一张表

创建索引的语句:

为某张表基于某列建索引:alter table 表名 add index idx_name(列名)

 

  MySQL不走索引的情况(开发规范)

重点关注:

1,没有查询条件,或者查询条件没有建立索引

  select * from tab ;全表扫描

  select * from tab where 1=1;

  在业务数据库中,特别是数据库量比较大的表,是没有全表扫描这种需求的,当然我们也应该避免这种情况

    1,对用户查看是非常痛苦的

    2,对服务器来说是毁灭性的

    (1) select * from tab

    SQL改写成以下语句:

    select * from tab order by price limit 10 ;       需要在price列上建立索引

    (2) select * from tab where name=‘zhangsan';   name列没有索引

2,查询结果集是原表中的大部分数据,应该是25%以上。

  查询的结果集,超过了总数行数25%,优化器就会觉得没有必要走索引了。

  假如:tab表 id,name      id:1-100w,id列有索引

  select * from tab where id>50000;

3,索引本身失效,统计数据不真实

  大量的操作插入删除操作,对表内容变化比较频繁的情况下,有可能会出现索引失效的情况。

4,查询条件使用函数在索引上,或者列进行计算,运算包括(+,-,*,/,!等)

  算数运算

  函数运算

  子查询

例子:

  错误的例子:select * from test where id-1=9;

  正确的例子:select * from test where id=10;

5,隐式转换导致索引失效,这一点应当引起重视,也是开发中经常遇到会犯的错误!

 6,<>,not in 不走索引

    单独的 >,<,in有可能走,也有可能不走,和结果集有关,尽量结合业务添加limit

    or或 in  尽量改成 union

7,like "%_"百分号在前面不走索引

    %link%类的搜索需求,可以使用elasticsearch 专门做搜索服务的数据库产品

8,单独引用联合索引里非第一位置的索引列,作为条件查询时不走索引。

例子:

  复合索引

  DROP TABLE t1

  CREATE TABLE t1(id INT,NAME VARCHAR(20),age INT , sex ENUM('m','f'),money INT );

   ALTER TABLE t1 ADD INDEX t1_idx(money,age,sex);

  DESC t1

  SHOW INDEX FROM t1

  走索引的情况测试:

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30  AND  sex='m'; 

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30 ;

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND sex='m';   ----->部分走索引

  不走索引的情况;

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30;

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30  AND  sex='m';  

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE sex='m'; 

 

MySQL存储引擎

查看存储引擎:

show engines;

show create table world.city;

插件式,即插即用存储引擎,是在表级别设定的。

mysql5.5以后默认的是InnoDB

InnoDB与MyISAM存储引擎的区别:

MVCC: innoDB支持,MyISAM不支持

锁(行级别): innodb支持,myisam表级别

外键: innodb支持,myisam不支持

事务: innodb支持,myisam不支持

热备份: innodb支持,myisam温备份

CSR(故障断电自动恢复)innodb支持,myisam不支持

InnoDB

MVCC

 锁定粒度

外键

MyISAM

MEMORY(memory)

ARCHIVE(archive)

 

 

也可以使用第三方的存储引擎

TokuDB  ------>zabbix

myrocks

 

InnoDB存储引擎的物理存储方式:

表空间(TBS)的管理模式:

来自于Oracle

表存储到磁盘上是以表空间的管理模式来存储

共享表空间:类似于Oracle管理模式

独立表空间:每个表单独使用表空间存储

5.5默认:共享表空间

5.6以后:默认管理模式独立表空间存储,共享表空间也存在

 

表空间存储数据的分类:

共享表空间:ibdata1   

存了什么?

系统数据

undo日志

磁盘临时表

独立表空间:

t1.ibd  ----->t1表的数据和索引

t1.frm ------>t1表的列相关信息

表空间操作:

共享表空间:

我们建议,在数据库初始化的时候就配置好

一般建议2-3个,512M

/etc/my.cnf

innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend

mysql_install_db

 

独立表空间:一个表一个ibd文件,存储表数据和索引

show variables like 'innodb_file_per_table';

 

事务

InnoDB存储引擎核心特性:

1,事务

  简单来说:

    事务会把业务流程中的多条语句放到一个执行(工作)单元里面,保证这多条语句要么全部成功,要么全部失败。

    保证交易类业务完整性

  官方:

  一组数据操作执行步骤,这些步骤被视为一个工作单元

  用于对多个语句进行分组

  可以在多个客户机并发访问同一个表中的数据时使用

  所有步骤都成功或者都失败

  如果所有步骤正常,则执行

  如果步骤出现错误或不完整,则取消

  

2,事务是保证数据的ACID特性

  Atomic(原子性)

    所有语句作为一个执行单元全部成功执行或全部取消执行。

    保证了稳定性。

  Consistent(一致性)

    如果数据库在事务开始时处于一致状态,则在执行该VT事务期间将保留一致状态。

  Isolated(隔离性)

    事物之间不相互影响

  Durable(持久性)

    事务成功完成后,所做的所有更改都会准确地记录在VT数据库中,所做的更改不会丢,即使数据库宕机

 

3,标准的事务控制语句:

  事务常见生命周期:

  周期一:

  begin;    开启事务

  DML

  DML

  commit;   结束事务

 

  周期二:   开启事务

  begin;

  DML

  DML

  rollback;   撤销事务

  常识:MySQL5.5版本以后不需要自己手动来写begin语句,写DML语句时自动生成

  注意:正常的遵循事务的ACID特性的事务,对于autocommit=1,需要手动关闭,默认等于1处于开启状态,自动提交功能

    临时关闭,临时生效

    set  autocommit=0;

    set  global  autocommit=0;

    永久关闭

    在my.cnf设置

    autocommit=0;

4,隐式提交

  用于隐式提交的SQL语句:
     START TRANSACTION
     SET AUTOCOMMIT = 1
  导致提交的非事务语句:
     DDL语句:  ALTER、CREATE、DROP
     DCL语句:  GRANT、REVOKE、SET PASSWORD
     锁定语句  LOCK TABLES 和 UNLOCK TABLES
  导致隐式提交的语句:
     TRUNCATE TABLES
     LOAD DATA INFILE
     SELECT FOR UPDATE

  隐式提交的几种情况:

    情况一:

      begin

      DML1

      DML2

      begin

    情况二:

      begin

      DDL

      DDL

    情况三:

      begin

      DCL

      DDL

5,innodb存储引擎物理存储层

  表空间(t1.ibd)----->

  段    一个表就是一个段(除了分区表)

  区    连续的多个页

  页    page(16KB)

  每个数据页作为一个存储单元

6,存储引擎日志 -----物理层面

Redo:重做日志

 

  Redo记录的是内存数据页的变化过程

  Rudo:事务日志的一种,在事务ACID过程中,实现的是“D”持久化的作用,AC特性也和它有关

  Rudo:CSR过程中实现前滚

  存储位置:数据路径下存放,默认两个日志,默认标准大小50M,轮询覆盖形式使用文件日志

    通过这两个参数控制,可以按照自己需求设定文件大小

      innodb_log_file_size=50331648

      innodb_log_files_in_group=2

    ib_logfile0

    ib_logfile1

    查看标准大小:

      mysql -uroot  -p

      show varables like '%log%';

   LSN:日志序列号(也就是数据变化的版本号)

    哪些地方会有日志序列版本号:

      data page      磁盘数据页

      logfile

      data buffer

      redo log  buffer  日志的内存区域

      

    数据库要求:启动时,必须保证data page 与logfile 中LSN号一致才能正常打开数据库,否则就会进行数据恢复

 

 

undo:回滚日志

  undo记录了什么?

    undo:记录数据页变化之前的数据状态以及TXID(数据页的id)

   undo:事务日志的一种,在事务ACID过程中,实现的是“ACI”原子性,一致性的作用

  undo作用:

    1,rollback

    2,CSR过程中实现回滚

  事务没有进行commit提交的情况下:

    先Rudo前滚

    再undo回滚

 

  四种隔离级别:

    READ UNCOMMITTED  脏读

      允许事务查看其他事务所进行的未提交更改

    READ COMMITTED     幻读

      允许事务查看其他事务所进行已提交更改

        有可能出现幻读的现象,企业中坚决避免

    REPEATABLE READ******可重复读,防止幻读现象

      确保每个事务的SELECT 输出一致

      InnoDB默认级别

    SERIALIZABLE

      将一个事务的结果与其他事务完全隔离

        会阻塞其他事务的所有操作,只保证当前事务正常运行

 

  Innodb事务锁机制

  锁:顾名思义就是锁定的意思

  种类:行级锁与表级锁

  作用:在事务ACID过程中,锁和隔离级别一起来实现隔离性的作用

  锁的粒度:

    MyIasm:低并发锁  ——表级锁

    InooDB:高并发锁  ——行级锁

  事务出现冲突,出现锁争用:也名冲突事务

  冲突事务例子:

    例子:

        1,事务1想要把a=1修改成a=2,,而这时事务2想要把a=1修改成a=3,这种情况下

        2,两个事务同时更新一条数据

 

 InnoDB体系结构扩展:

  1,内存结构

  2,线程结构

  3,事务工作更详细流程

  4,InnoDB存储引擎在安全和性能上的体现

  5,Double  Write

  6,Db crash恢复流程

 

 

 

日志管理

1,错误日志

  a,作用:

    记录启动关闭日常运行过程中,状态信息,警告,错误

  b,配置:

    默认就是开启状态:/数据路径下/hostname.err

    手动设定:

      vim /etc/my.cnf

      log_error=/var/log/mysql.log

      重启生效:

      show variables like 'log_error';

   c,查看日志内容

      主要关注[error],看上下文

2,二进制日志:binlog

   1,作用:

      1,备份恢复

      2,主从环境

   2,binlog配置(5.7必须加server_id)

      vim /etc/my.cnf

      server_id=6

      log_bin=/data/mysql/mysql-bin

      binlog_format=row

      重启生效

      注意:=/data/mysql 必须事先创建好,必须对mysql有权限

   3,binlog记录了什么?

      记录mysql数据库所有变更类的SQL语句

      DDL,DCL,记录方式:SQL语句直接记录

      DML记录三种方式:  只记录已经commit的DML

        row       5.7默认

          特点:记录数据行的变化,可读性不高,日志量较大,记录数据精确

        statment    5.6默认

          特点:可读性较高,日志量较少,但是以后恢复数据可能会是错误数据

        mixed

   4, event二进制的最小记录单元

      对于DDL,DCL,一个事务就是一个event

      对于DML,一个事务就被分为了四个event:

          begin;

          DML1

          DML2

          commit;

      event组成:开始位置 + 事件内容 +结束位置

   5,日志文件查看

      log_bin参数设置的路径,可以找到二进制日志

      show binary logs;

      show master status;

   6,日志内容查看

      show master status;

      show master status in 'mysql-bin.000002';

 

      录入数据,看事件信息:

      create database testdb;

      create table t1(id int);

      insert into t1 values(1);

      commit;

      show binlog events in 'mysql-bin.000002;

 

      查看binlog文件详细内容:

      mysqlbinlog /data/mysql/mysql-bin.000002;

      mysqlbinlog --base64-output=decode-rows      -vvvv /data/mysql/mysql-bin.000002;

      mysqlbinlog -d testdb /data/mysql/mysql-bin.000002;

   7,日志截取

      mysqlbinlog --start-position   --stop-position

      恢复:

      set sql_log_bin=0;

      source /tmp/binlog.sql

      set sql_log_bin=1;

   8,二进制日志恢复数据

    数据库的故障(损坏),原因:

      1,软件损坏了

      2,数据损坏了

      3,硬件损坏,数据文件,数据页

      4,逻辑损坏

      5,SQL导致的误删除,误修改

    只要拥有全量的binlog,就可以把数据库恢复到任意的时间点

 

3,慢日志(slow_log)

  1,作用:

    记录慢SQL语句的日志

  2,开启慢日志,默认没开启

    配置:

    开启慢日志:

      slow_query_log=1

    文件位置以及名字:

      slow_query_log_file=/data/mysql/slow.log

    设定慢查询时间:

      long_query_time=0.01

    没走索引的语句也记录:

      log_queries_not_using_indexes  

    

    服务器端配置,几条语句加进去就可以了

      vim /etc/my.cnf

        slow_query_log=1

        slow_query_log_file=/data/mysql/slow.log

        long_query_time=0.01

        log_queries_not_using_indexes

      /etc/init.d/mysql  restart

   3,分析慢日志

     mysqldumpslow

     mysqldumpslow  -s c -t  10 /data/mysql/slow.log

备份恢复

1,备份类型

  热备:在数据库正常业务是,备份数据,并且能够一致性恢复

  冷备:关闭数据库业务,数据库没有任何变更的情况下,进行备份数据

  温备:锁表备份,只能查询不能修改

2,备份方式,工具

  逻辑备份:基于SQL语句进行备份:mysqldump,mysqlbinlog

  物理备份:基于磁盘文件备份:cp,xtrabackup(XBK)

3,备份策略

  1,全备:全库备份

  2,增量:备份变化的数据

  备份周期:多久全备,多久增量

  

 

4,恢复备份

5,故障恢复

6,迁移

 

 

主从复制

前提:

  1,准备2个以上的mysql实例,有主有从

     2,每台实例server_id不同

  3,主库方面创建专用的复制用户

  4,主库必须开启二进制日志

  5,从库需要初始化数据,保证和主库数据在一个时间点上数据一致

1,搭建主从复制

  1,准备多个mysql实例(3307(master),3308(slave1),3309(slave2))

    具体环境配置文档(待QAQ续)  

  2,主库必须授权一个专门用作主从复制的用户

    在创建一个复制用户

    mysql  -S /data/3307/mysql.sock

    grant  replication slave on *.* ro repl@'10.0.0.%' indextified  by '123';

  3,全备主库数据,恢复到从库

    mysqldump -S /data/3307/mysql.sock -A  -R  --triggers  --master-data=2 --single-transaction >/tmp/full.sql

    

    mysql  -S /data/3308mysql.sock

    set sql_log_bin=0;

    source  /tmp/full.sql

  4,开启主从复制

    mysql -S /data/3308/mysql.sock

    命令两条:

      忘记了请记得让我们的help小姐姐来帮你QAQ: help change master to

      CHANGE MASTER TO

        MASTER_HOST='10.0.0.51',         填写主库ip

        MASTER_USER='repl',          填写主库复制用户名

        MASTER_PASSEORD='123',          填写主库复制用户密码

        MASTER_[PORT=3307,          填写主库端口号

        MASTER_LOG_FILE='mysql-bin.000001',  填写需要复制二进制日志名

        MASTER_LOG_POS=325,         填写需要复制的二进制日志复制的起点

        MASTER_CONNECT_RETRY=10;      重连重试次数

        

        启动复制线程:

          start slave;

           查看主从状态:

            show slave status G

          当你看到这两条命令为Yes,那么恭喜你成功了!

            Slave_IO_Running:Yes

            Slave_SQL_Running:Yes

 2,主从复制存在原因

    1,辅助备份

       解决物理损坏

    2,演变高可用架构

       在主库发生故障时,自动进行故障转移,对于应用透明

    3,演变高性能架构

      读写分离

      分布式

 

 3,延时从库

 

 4,过滤复制

  控制过滤

    从主库方面控制:复制指定的库到从库,对主库业务数据进行垂直拆分

    从从库方面控制:只接收主库某个库复制过来的内容   

 

  1,从主库方面控制

    show master status;

    Binlog_Do_DB=白名单,在此参数中的库,记录二进制日志

    Binlog_Ignore_DB=黑名单,在此参数中的库,不记录二进制日志

 

  2,从库方面控制

    Replicate_Do_DB:  白名单,在此参数中的库,复制

    Replicate_Ignore_DB:  黑名单,在此参数中的库,不复制

    Replicate_Do_Table:  白名单,在此参数中的表,复制

    Replicate_Ignore_Table:  黑名单,在此参数中的表,不复制

    模糊的表名字    

    Replicate_Wild_Do_Table:  wolrd.t*

    Replicate_Wild_Ignore_Table:

    写法:

    vim /data/3308/my.cnf

    replicate_do_db=world

    replicate_do_db=oldboy

 

5,主从复制之架构扩展GTID复制

1,环境准备

  环境准备Centos拿db01克隆两台虚拟机

  干掉原来数据库,并清理/application/mysql/data下所有数据,保证环境一致,干净

    pkill mysqld

    rm -rf  /application/mysql/data*

  1,备份三台机器/etc/my.cnf文件

    mv/etc/my.cnf  /tmp

  2,书写配置文件:

    master:10.0.0.51

    vim/etc/my.cnf  

    

    [mysqld]

    dasedir=/application/mysql

    datadir=/application/mysql/data

    socket=/tmp/mysql.sock

    log-error=/var/log/mysql.log

    log-bin=/data/mysql/mysql-bin

    binlog_format=row

    skip-name-resolve

    server-id=51

    gtid-more=on

    enforce-gtid-consistency=true

    log-slave-updates=1

    [client]

    socket=/tmp/mysql.sock

    

    slave1:10.0.0.52

    vim /etc/my.cnf

    [mysqld]

    dasedir=/application/mysql

    datadir=/application/mysql/data

    socket=/tmp/mysql.sock

    log-error=/var/log/mysql.log

    log-bin=/data/mysql/mysql-bin

    binlog_format=row

    skip-name-resolve

    server-id=52

    gtid-more=on

    enforce-gtid-consistency=true

    log-slave-updates=1

    [client]

    socket=/tmp/mysql.sock

 

    slave2:10.0.0.53

    vim /etc/my.cnf

    [mysqld]

    dasedir=/application/mysql

    datadir=/application/mysql/data

    socket=/tmp/mysql.sock

    log-error=/var/log/mysql.log

    log-bin=/data/mysql/mysql-bin

    binlog_format=row

    skip-name-resolve

    server-id=53

    gtid-more=on

    enforce-gtid-consistency=true

    log-slave-updates=1

    [client]

    socket=/tmp/mysql.sock

 

  3,重新初始化三台机器数据

    /application/mysql/scripts/mysql_install_db  --basedir=/application/mysql/ --datadir=/application/mysql/data  --user=mysql

  4,分别启动三台数据库服务器

    etc/init.d/mysqld start

 

 2,GTID介绍

  GTID是对于一个已提交事务的编号,并且是一个全局唯一的编号

   官方定义:

   GTID=source_id :transaction_id

  7E11FA47-31CA-19E1-9E56-C43AA21293967:29

  

  1,什么是sever_uuid和Server-id区别?

  source_id  也叫uuid   默认是在第一次启动数据库时,自动生成的

  /application/mysql/data/auto.cnf

  手动删除掉此文件,重启数据库,可以生成新的

 

  2,重要参数

  gtid-mode=on            --启动gtid类型,否则就是普通的复制架构

  erforce-gtid-consistency=true     --强制GTID的一致性

  log-slave-updates=1          --slave更新是否记入日志

 

  3,基于GTID的复制构建

    master:51

    slave:52,53

    51:

    grant  replication  slave  on  *.* to  repl@'10.0.0.%' identified by '123';

    5253:

    source bak.sql

    change master to msater_host ='10.0.0.51',master_user='repl',master_password='123',MASTER_AUTO_POSITION=1;

    start  slave;

    change master to msater_host ='10.0.0.51',master_user='repl',master_password='123',MASTER_AUTO_POSITION=1; 

 

 

高可用以及读写分离

 

 

分布式系统

 

 

 

数据库优化

  搜索引擎优化

  SQL语句优化

原文地址:https://www.cnblogs.com/Rglin/p/11280867.html