首页 > 数据库 >关系型数据库(mysql/InnoDB)的前世今生

关系型数据库(mysql/InnoDB)的前世今生

时间:2024-10-16 17:50:01浏览次数:3  
标签:事务 今生 查询 索引 InnoDB mysql 日志 数据 id

博主专注于Java程序开发,旨在与各路大神做技术交流,觉得不错的朋友,点个关注,有想深度交流,也可参考博主其他文章:java知识体系搭建-CSDN博客

前言

本文将汇总介绍关系型数据库的常用知识,理论偏多,希望大家都能对关系型数据库有个总体的认识。具体应用,大家需要在工作中自行融汇。

介绍关系型数据库之前,希望大家先思考一个问题,一个关系型数据库都需要包涵哪些东西,也就是说,如果让你设计一个关系型数据库系统,你会怎么设计?

1.数据库设计

首先一个数据库系统,肯定需要包含两个部分:程序实例(负责对存储进行逻辑上的管理) 以及 文件存储系统(负责持久化数据)。

1.1 程序实例

作用:负责对存储内容进行逻辑上的管理

a. sql解析模块

作用:可缓存编译好的sql

b. 存储管理模块

作用:数据按照块或者页的方式储存(存储的数据单位),也可以减少IO

c. 缓存机制

作用:减少IO,优化执行效率

d. 锁管理

作用:支持并发,线程安全

e. 索引管理

作用:优化数据查询效率

f. 日志管理

作用:记录操作日志

g. 权限划分

作用:多用户管理

h. 容灾机制

作用:数据恢复,数据备份

1.2 存储(文件系统)

作用:负责持久化数据

2. 索引

在对关系型数据库有个整体的了解之后,接下来,我们再一部分一部分的慢慢学习其中的细节。在细节上,我首先想讲的,可以说是一个数据库最关键的部分,数据库索引。同样,我们先思考一个问题,关系型数据库,为什么要使用索引

2.1 为什么使用索引

数据库的第一个作用,是提供查询,但当数据量较大时,数据库的全表扫描会很慢,而索引可以避免全表扫描,提升查询效率 

2.2 什么样的数据可以成为索引

为了更好的提升查询效率,那么能使数据具备一定区分度的字段,比如主键,区分度越高的字段,作为索引的效果自然越好。

2.3 索引数据结构

一般,为了优化查询效率,数据库的索引 通常会采用以下几种结构,树,hash 以及 BitMap,就像大家都知道mysql的索引结构是B+树,那究竟什么是B+树?

2.3.1 树结构简介

a.二叉树

每个节点最多有两个子树

b.平衡二叉树

左右子树的高度相差不超过 1 的树为平衡二叉树

c.二叉查找树

1) 对于任意节点的值均大于左子树所有节点且小于右子树所有节点

2) 每个节点最多有两个子树

3) 查找效率:二分查找,与树的高度有关,即O(logn)

d.B tree(平衡多路查找树)
1) B tree 遵守约束

   a) 根节点至少两个孩子

   b) 每个节点最多m个孩子,则该树叫m阶树(m>=2),m表示路也表示叉

   c) 除根节点和叶节点外,其他每个节点至少有ceil(m/2)个孩子(ceil表示向上取整)

   d) 所有叶子节点位于同一层 (最底层)

   e) 排序约束

    所有节点关键字K1,K2,KM-1是按递增次序排列,并遵循左小右大原则

    枝节点的关键字数量大于等于ceil(m/2)-1个且小于等于M-1个

    非叶子节点的指针,P1,P2...PM,其中P1指向关键字小于K1的字数,PM指向关键字大于K(M-1)的指数,其他Pi指向关键字属于(K(i-1),Ki)的子树

2) 约束原因

约束原因:尽可能让树的高度尽可能低,从而减少IO

3) 查找效率

查找效率:与树的高度有关,B树的高度比较低,O(logn)

e. B+tree(B+树)
1) 定义:B树的变体
2) 与B树的区别

  非叶子节点的关键字个数与子树指针个数相同(节点可存储更多关键字)

  非叶子节点的指针Pi指向关键字属于(K(i-1),Ki)的子树

  非叶子节点仅用来做索引,数据都保存在叶子节点中

     注:B+树的检索,一定是从根节点到叶子节点

     非叶子节点不存储数据,就可以存储更多的关键字,使得树的高度进一步降低

  所有叶子节点均有一个链指针指向下一个叶子节点 

     作用:支持范围统计,即定位到某个叶子节点后,可横向做范围统计

 3) 优点

   B+树的磁盘读写更低,节点不存储数据,可存储更多关键字,减少了IO。

   B+树查询效率更稳定,查询高度一致

   B+树更有利于范围查询

2.3.2 hash索引

a. 优点:查询效率更高
b. 缺点

1) 仅能满足“=”,IN,不能使用范围查询

2) 无法被用来数据排序操作

3) 对于组合索引,不能利用部分索引健查询

4) 不能避免表扫描

5) 大量hash值相同时,会导致速率低下

c. 支持

mysql不显示支持hash索引,oracle支持

2.3.3 BitMap

介绍:位图索引,Oracle支持,当数据只有几种值时

缺点:锁的粒度会很大

应用:适用于统计场景

2.4 密集索引与稀疏索引

2.4.1 密集索引

密集索引文件中的每个搜索码值都对应一个索引值

密集索引的叶子节点包含行数据信息

2.4.2 稀疏索引

稀疏索引文件只为索引码的某些值建立索引项,即表的数据与索引是分开存储

2.4.3 存储引擎 

a.MyIsam

1) 所有索引均为稀疏索引

2) 查询时,不管是通过主键,还是其他健查询,都只能拿到一个行数据地址,然后再去数据文件中查找对应的数据

b. InnoDB(常用)

1) 有且仅有一个密集索引

   如果主键被定义,则主键为密集索引

   如果没有主键被定义,则该表的第一个唯一非空索引为密集索引

   上述条件都不满足,innodb会生成一个隐藏主键作为密集索引

2) 其他非主键索引(密集索引),即稀疏索引,并不存储行数据的物理地址,而是存储主键值,所以包含两次查找

2.5 SQL优化(应用)

2.5.1步骤

1) 根据日志,定位慢sql
2) 使用explain分析sql (字段详解)
a. id

select查询的数字序列号,表示查询中执行select子句、或多表联合查询时操作表、的顺序

分类:

   1) id相同,执行顺序由上至下

     a.用于连表查询从t1、t2、t3三张表中查询t2表的全部,查询条件是:t1.id=t2.id 、t1.id=t3.id、t1的other_column=''

     b.优化器对于同一个where内部的条件,默认是从右往左读取的; 所以三张表的执行顺序是:t1 -> t3 -> t2

  2) id不同,id越大执行优先级越高(用于嵌套查询时)

  3) id同时存在相同和不同的情况,id不同的id大的优先执行,id相同的从上到下执行

     a.衍生虚表查询(Derived):从原表中截取部分信息,组成的结果集可以构成一张新表

     b.子查询+连表:从表t3中查询id,查询条件是其他字段为空)将结果集作为一张虚表s1,然后从虚表s1、表t2中,查询表t2的全部,查询条件是s1.id=t2.id

    c.查询的顺序是:t3 -> derived2 -> t2 derived2指表t3的结果集衍生构成的虚表s1

b. select_type

含义:查询的类型

分类:

   1)SIMPLE

     简单查询,查询中不包含子查询、union(联合查询)

   2)PRIMARY

     查询中若包含子查询,则最外层查询被标记为PRIMARY

   3)SUBQUERY

     在select或where列表中的子查询

   4)DERIVED

     典型语法:from ( 子查询 ) s1, 在from列表中包含的子查询,被标记为DERIVED(衍生),这个子查询执行后的结果集放在一张虚表s1中;

    5)UNION

     若第二条select出现在union之后,则标记为union联合多表查询;

     若union包含在from字句的查询中,即select 属性 from(子查询1 union 子查询2)s1,这种外层的select被标记为DERIVED;

    6)UNION RESULT

     从UNION表中获取结果的SELECT

c. type

对表访问方式,表示MySQL在表中找到所需行的方式,又称“访问类型”。

1) ALL: 全表扫描,FULL TABLE SCAN,遍历全表找到匹配的行;速度最慢,避免使用;

2) index: 全索引扫描,FULL INDEX SCAN,只遍历索引树,通常比ALL快; (index与ALL都是全表查询,但index是从索引中读取,ALL是从全表中读取)

3) range: 范围查询,where后面的列表中是between、<、>、in等的查询

4) ref: 非唯一索引扫描,对于每个索引键,表中可能对应多行数据,当满足索引的最左前缀规则,或者索引不是主键也不是唯一索引时才会发生。

5) eq_ref:唯一性索引扫描,对于每个索引键,表中只对应一行数据,常见于主键,性能仅次于system及const

6) const、system:

  const是常量查询,是最优化的查询方式,表示通过索引Index一次就找到了,用于比较 primary key=常量 和 unique=常量 这种索引;

   system是系统查询,指表中只有一行数据,这是const的特例

d. rows

索引查询时,大致估算出查询到所需记录读取的行数,rows越小越好;

e.possible_keys

查询的字段上若存在索引,则将索引列出,一个或多个,但不一定在查询时实际使用;

f.key

实际使用的索引,若为NULL,则没有使用索引,常见的可能原因:

(1)没有建索引

(2)sql语句写法错误,索引失效;

(3)possible_key也为NULL时,表示用不到索引

g. key_len

可以通过key_len看出索引字段的个数,74指1个,78指2个,140指3个

h.ref

显示使用索引的是哪个字段,可以是一个const常量;

I.Extra

额外信息,包含以下三种

1)Using filesort

   说明建立的、准备使用的索引index并没有被用到,执行了文件排序; 可能是sql语句写法有问题,与之前建立的索引index冲突了,一般与order by 有关系(where 与 order by作用到了不同的列)

2)Using temporary

   使用了临时表来保存中间结果,说明建立的索引没有使用完全; 常见于排序order by和分组查询group by

3)Using index

   select操作中用到了覆盖索引(Covering Index),说明sql执行的效率不错!

3)修改sql,尽量让sql走索引

2.5.2 联合索引

a. 最左匹配原则

场景:联合索引(a,b,c)

1) 原理

对于联合索引a,b,c,索引的B+树 会先按照a排序,当a的值相等时,再按照b排序,b相等时,按照c排序。

2) 注意

对于(a,b,c)联合索引而言,实际上有三个索引即,a ,ab ,abc

a.where 条件只有c时,无法走索引,原因:单纯的对于c来说,是没有顺序的

b.对于where条件 a=1and b>2 and c=3,mysql会一直向右匹配,直到遇到范围查询(<,>,between,like)就停止匹配

即:a,b可以用到索引,但因为b>2时,c是没有顺序的,c无法再用索引,对于上述情况,可建立索引(a,c,b),即通常范围查询的字段,尽量放在联合索引的右边

c.=和in可以乱序

a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式

b. 优点
1) 减少开销

建一个联合索引(col1,col2,col3),实际相当于建了(col1),(col1,col2),(col1,col2,col3)三个索引。每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减少开销!

2) 覆盖索引

对联合索引(col1,col2,col3),如果只查询col1,col2,col3,可以无需回表,减少了IO操作

3) 效率高

索引列越多,通过索引筛选出的数据越少

2.5.3 索引失效

a. 不满足最左匹配原则
b. 无法使用覆盖索引

select *  from table

c. 索引列上有计算

explain select * from user where id+1=2;

d.索引列用了函数

explain select * from user where SUBSTR(height,1,2)=17;

e.字段类型不同(加引号没问题)

code字段为varchar,使用select * from user where code=101; 没有引号,导致索引失效,反过来如果code是int ,查询的时候加了引号,索引不会失效

f.模糊查询,like左边包含%

索引就像字典中的目录。一般目录是按字母或者拼音从小到大,从左到右排序,是有顺序的。

g.列对比

select * from user where id=height,即使id,和height都加了索引,也会失效

h.使用or关键字

or连接的字段必须都有索引,只要有一个没有,就会失效

i.反向范围查询not in和not exists
j.order by使用不同的索引

select * from user order by code, height limit 100;code 与height 是两个索引

k.order by 使用不同的排序顺序

select * from user order by code asc,age desc limit 100 ,code与age是联合索引且满足最左匹配,也会失效

2.5.4 分页越往后越慢

a.原因

没有用到索引,全表扫描,约往后需要扫描的数据越多

b.解决

可以用覆盖索引,先查出id,然后借助子查询或关联查询,用主键去对数据进行过滤

3.锁

讲完索引的部分,接下来要讲的,是mysql的另一个核心,锁。

3.1锁的分类

mysql的锁,会根据不同的维度,有多种分类方式

3.1.1粒度划分(MyISAM与InnoDB)

a.表级锁

mysql里,表级锁最典型的应用场景就是MyISAM引擎

  1)MyISAM默认使用的是表级锁,不支持行级锁 

  2)MyISAM不支持事务,在查询时,会给表加读锁(共享锁),在修改表时,会给表加上写锁(排他锁),都是表级锁。

  3)MyISAM适合场景:增删改的频率不高,查询频繁;频繁执行全表count ;没有事务的场景

b.行级锁

与表及锁对应,行级锁最典型的应用场景则是InnoDB引擎

  1)InnoDB默认使用行级锁,也支持表级锁-即当sql不走索引时,会升级为表锁

  2)InnoDB支持事务,默认事务自动提交,开销比MyISAM更大

  3)适合场景:数据增删改查都比较频繁;可靠性要求比较高,支持事务

c.页级锁

3.1.2 级别划分

a.共享锁
b.排他锁
c.InnoDB意向锁
1)意向共享锁(IS锁)

指事务在获取低级别(行锁或页锁)共享锁的同时,在高级别上也获取特殊的共享锁,这种特殊的共享锁是意向共享锁

高级别可能是多条记录组成的范围锁(页),也可能直接就是表意向锁

所谓高低级别,体现在锁的粒度上,例如,innodb引擎,在获取行粒度的共享锁的同时,也要获取表级别的意向共享锁,意向锁的粒度要比待加锁本身的粒度大

注意:由于InnoDB存储引擎支持的是行级别的锁,而意向锁一般都是表锁,因此意向锁只会阻塞表层面上的其他锁,故不会阻塞出全表扫以外的任何请求,因为锁的不是一个对象。

2)意向排他锁(IX锁)

指事务在获取获取低级别(行锁或页锁)独占锁的同时,在高级别上也获取特殊的独占锁,这种特殊的独占锁是意向独占锁

3)关于意向锁的说明

意向锁表示某个事务正在某些行持有了锁、或该事务准备去持有锁,他的表现形式是,事务在请求S锁前,要先获得IS锁,事务在请求X锁前,要先获得IX锁

作用:innodb同时支持表锁与行锁,意向锁的产生是为了协调行锁和表锁的关系,比如我们都知道如果一个表有排他锁,那该表的任何行都不能再上锁,但如果有事务A已经对一张表的某行上了锁,如果事务B要对整张表上锁时,需要逐行去排查,这样效率是极低的,但意向锁的存在避免了这个问题,事务A会在获取行锁前,对整张表加意向锁,这样就提升了事务B判断获取锁时的效率

兼容:

a.意向共享锁和共享锁兼容(这是肯定的),还和意向独占锁兼容。------所以加了意向共享锁的时候,可以修改行级非共享锁的记录

b.意向锁之间互相兼容(意向独占与意向独占夜兼容),但意向独占锁与表的共享锁不兼容------当事务A在修改表中某行数据时,事务B不能在整张表加共享锁,但可以查询其他行数据(快照读不加锁)

3.1.3 加锁方式

a.自动锁
1)意向锁

意向锁是数据库在获取共享锁或排他锁之前自动上的

2)myisam的表锁
b.显示加锁
1)select for update
2)lock in share mode

3.1.4 操作划分

a. DDL锁
b. DML锁

3.1.5 使用方式划分

a.乐观锁

使用数据版本,增加version字段

不会死锁,但可能会不可预料的结果

b.悲观锁

3.2 数据库事务

3.2.1 事务的四大特性

概述:如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性

a. 原子性Atomic

原子性由undolog日志来保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql

b.一致性Consistency
c.隔离性Isolation

数据库引擎可以借助锁保证一定的隔离性,而隔离性是有级别划分的,但并不是说数据库的隔离级别不同会影响锁之间的共存性

数据库的隔离级别
1) Read uncommitted (读未提交)

最低级别,任何情况都无法保证

2) Read committed (读已提交)

可避免脏读的发生。

oracle默认的隔离级别

RC下,快照读与当前读,读到的数据版本一样,都是最新版本(在另一个事务已经提交的前提下),每次当前读都会生成一个新的readview

3) Repeatable read (可重复读)

可避免脏读、不可重复读的发生。 

mysql(innodb)默认的隔离界别

innodb 在可重复读的隔离级别通过next-key锁避免了幻读

RR下,快照读可以读到旧版本数据

RR下,通过mvcc避免了快照读的幻读,但当前读的避免幻读还是通过间隙锁实现的

4) Serializable (串行化)

可避免脏读、不可重复读、幻读的发生。 

d. 持久性Durability

持久性由redolog来保证,mysq|修改数据的时候会在redolog中记录一份日志数据,就算数据没有保存成功,只要日志保存成功了,数据仍然不会丢失

3.2.2 事务并发的问题

常见的并发问题,有以下几类

a.更新丢失

数据库层面会避免这个问题,所以不好模拟

b.脏读

场景:事务A读到事务B未提交的数据,此时事务B回滚,导致事务A的后续逻辑出错

c.不可重复度

场景:事务B先修改了某条记录,但未提交,事务A读该数据时,并未读到修改后的数据,但当事务B提交之后,事务A再次读,发现数据发生了变化,隔离性不够

d.幻读

场景:事务A读取了一个范围数据,事务B对该范围的数据修改(插入了一条新的记录,并提交),事务A再次读该范围时,发现多了一条数据,多出来的数据,也就是说,幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行

避免:串行化的情况下,事务B在插入时会阻塞

3.2.3 MVCC

a. 简述

MVCC全称是多版本并发控制 (Multi-Version Concurrency Control),在MVCC之前,只有读读可以并发,读写,写读,写写都会发生阻塞,例如MyISAM的表锁,innodb引入了MVCC后,满足了只有写写才会阻塞,即实现了所谓的非阻塞读。

Innodb实现了伪MVCC,因为并非真的有多版本,而是借助了undo日志)。但通过MVCC实现的非阻塞读,让innodb在不使用锁的前提下,也可以获取一致性的版本,满足了事务的四种隔离级别,并且由于不使用锁所以性能更好

b. Innodb读的分类
1) 当前读

加了锁的读法,就是当前读,不但读取的是最新的记录,也避免其他事务修改

共享锁: select ... lock in share mod

排他锁: select... for update

排他锁: update,delete,insert

2) 快照读

在非串行化的隔离级别下,不加锁的非阻塞读都是快照读,即select

在串行化的隔离级别下,快照读会退化为当前读

好处:提升并发性能

c.InnoDB mvcc实现机制
1) undo日志

简述:对记录做变更操作时会产生undo记录,即复制出来的老版本记录,老版本记录中也包含隐藏字段,从而实现了数据多版本

分类:

  insert undo log: 事务在insert数据时产生,在事务回滚时需要,事务提交后可丢弃

  update undo log: delete或update产生,只有在数据库中所使用的快照不涉及该日志记录时,才会被丢弃

2) 数据行的隐藏字段

DB_TRX_ID:

    a.标识最近一次对本行做修改的事务id

    b.对于某一条数据来说,同一时间只允许一个事务修改,除非该事务提交。

    c.DB_TRX_ID 虽然不一定是递增的,但一定不会在几个值之间反复。所以由回滚指针形成的数据链表一定是条版本链表

DB_ROLL_PTR: 回滚指针,指向undo log中旧版本的DB_ROW_ID

DB_ROW_ID: 记录行号,自增

3) read view

a.作用:做可见性判断,当快照读时,mysql会针对查询的数据创建出一个readview,来决定当前的事务能看到这些数据的哪个版本

b.原理: 原理包含以下三部分

(1)readview字段包含以下

   a.m_ids:当前活跃的事务的id列表,表示生成readview时,还未提交的事务

   b.min_trx_id:当前活跃事务的最小id,即m_ids中最小的id

   c.max_trx_id:是指下一个要生成的事务 id。下一个要生成的事务 id 肯定比现在所有事务的 id 都大

   d.creator_trx_id:当前的事务id

(2)可见性算法

将查询数据的db_trx_id与readview中的字段做对比,如果db_trx_id max_trx_id,表明生成该版本的事务在生成ReadView 后才生成,所以该版本不可以被当前事务访问,如果db_trx_id在min_trx_id与max_trx_id之间,那么判断db_trx_id是否在m_ids集合中,如果不在,表明该版本稳定已提交,可以访问。

如果某个版本的数据对当前事务不可见的话,那就顺着版本链找到下一个版本的数据,继续按照上边的步骤判断可见性,依此类推,找到最稳定的那个版本

(3) 结论:当trx_id在m_ids中,或者大于m_ids列表中最大的事务id的时候,这个版本就不能被访问

c.RC与RR区别:

RC隔离级别,每次快照读都会创建一个新的readview,而RR隔离级别,第一次快照读创建readview后,便不会再变,可重复读及时readview可以重复使用

4)工作

事务1将某行记录的字段A修改,会复制一份老版数据在zaundo log中,即老版本1,同时将当前行记录的DB_TRX_ID填写为事务1,DB_ROLL_PTR字段指向 undo log 中的老版本1,这时事务2将该行记录的字段B修改,会再复制一份老版本数据(包含隐藏字段)在undo log,即为老版本2,同时修改当前记录的DB_TRX_ID为事务2,DB_ROLL_PTR字段指向 undo log 中的老版本2,这样新版本的DB_ROLL_PTR指向 老版本2,老版本2的DB_ROLL_PTR指向老版本1,从而形成类似链表结构。

d.next-key锁(行锁+gap锁)
1) gap锁目的

gap锁的目的在于避免幻读

2) 场景

a.RR及串行化的隔离级别才有gap锁

b.当前读才会加锁,快照读不会加

c.where条件用主键索引或唯一索引的当前读

   如果where条件全部命中,则不会用gap锁

   如果where条件部分命中,或全不命中,会加gap锁

d.用在非唯一索引或者不走索引的当前读中

   a) 非唯一索引:非唯一索引的gap的范围,是按当前已有索引值分段之后,左开右闭区间,比如某个索引字段有(5,7,11)那改索引的gap区间有(-∞,5],(5,7],(7,11],(11,+∞)

    1) 当我们操作7时,为了避免幻读,7的周围都会上锁,所以(5,11]的间隙都会被锁

    2) 锁的范围除了会锁索引本身记录外,也会锁主键聚集索引,所以插入一条数据是否被锁与主键的值也会有关联

  b) 不走索引,会对该字段所有gap都上锁,相当于锁全表

3)总结

正常开发中,主键或唯一索引部分命中的场景较少,但是对于非唯一索引,即使where命中也会加间隙锁,这种场景更多,需要尽量避免,否则会很容易死锁

4.日志

实际开发过程中,在生产环境,可能会碰到数据库层面各种各样的奇怪问题,这个时候,我们排查问题时,免不了要借助数据库日志,所以,也要求我们对数据库的各种日志有初步认识。

4.1 错误日志(error log)

记录mysql服务的启停时正确和错误的信息,还记录启动、停止、运行过程中的错误信息

可以使用" --log-error=[file_name] "来指定mysqld记录的错误日志文件,如果没有指定file_name,则默认的错误日志文件为datadir目录下

4.2查询日志(general log)

记录建立的客户端连接和执行的语句,建议关闭这种日志(默认是关闭的)

未超出变量 long_query_time 指定时间的值

4.3慢查询日志(slow log)

记录所有执行时间超过long_query_time的所有查询或不使用索引的查询。

查询获取锁(包括锁等待)的时间不计入查询时间内。

4.4二进制日志(bin log)

4.4.1介绍

对于事务表来说,一个事务中可能包含多条二进制日志事件,它们会在提交时一次性写入。而对于非事务表的操作,每次执行完语句就直接写入

记录数据库表结构和表数据变更的二进制日志,比如insert、update、delete、create、truncate等等操作,不会记录select、show操作,因为没有对数据本身发生变更。

4.4.2查看

以二进制文件的方式记录日志,可使用mysqlbinlog命令查看

4.4.3模式

a.row 行模式

日志中会记录每一行数据被修改的形式,然后在slave端再对相同的数据进行修改

特点:会非常清楚的记录下每一行数据修改的细节,不会出现某些特定的情况下的存储过程或function,以及trigger的调用和触发无法被正确复制的问题,但会产生大量的日志内容

b.Statement 模式(默认)

每一条会修改数据的sql都会记录到master的bin-log中。slave在复制的时候sql进程会解析成和原来master端执行过的相同的sql来再次执行

特点:不需要记录每一行数据的变化,减少bin-log日志量,节约IO,提高性能,但在使用了某些定的函数或者功能的时候复制数据会出现问题。

c.mixed模式

MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志格式,也就是在Statement和Row之间选择一种

4.4.4作用

主从复制:需要master节点打开binlog日志,从机订阅binlog日志的信息

数据恢复:指定--start-position和--stop-position,或者指定--start-datetime和--stop-datetime,那么就可以恢复指定区间的数据

4.5 Innodb特有事务日志

4.5.1 redo log 重做日志

记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来

redo log是循环使用,文件内容是会被覆盖的,当内存数据刷新到磁盘中,redo log的数据就失效了,可以用来恢复在内存更新后,还没来得及刷到磁盘的数据,例如:数据库掉电,InnoDB存储引擎会使用redo log恢复到掉电前的时刻,以此来保证数据的完整性

作用:数据恢复,提供前滚操作

4.5.2 undo log

作用:提供回滚和多个行版本控制(MVCC)

undo日志属于逻辑日志,所谓逻辑日志是undo log是记录一个操作过程,sql执行delete或者update操作都会记录一条undo日志

4.6 关键语法

4.6.1 group by

如果使用groupby, 那么select所查询的列要么是分组列,要么是其他表的列,要么是使用了列函数的列

a. 统计函数(列函数) sum/count/min/max/avg

4.6.2 having

通常与group by 一起使用,如果没有group by ,那么作用会类似where

出现同一sql的顺序:where>group by>having

where 是过滤行的,having 是过滤组的

4.7 读写分离

4.7.1介绍

基于主从复制架构,简单来说,就搞一个主库,挂多个从库。

4.7.2 主从复制实现

主库将变更写入 binlog 日志,然后从库连接到主库之后,从库有一个 IO 线程,将主库的 binlog 日志拷贝到自己本地,写入一个 relay 中继日志中。接着从库中有一个 SQL 线程会从中继日志读取 binlog,然后执行 binlog 日志中的内容,也就是在自己本地再次执行一遍 SQL,这样就可以保证自己跟主库的数据是一样的

4.7.3 主从同步延时问题

a.查看 Seconds_Behind_Master ,可以看到从库复制主库的数据落后了几 ms

b.在生产环境高峰期,写并发达到了 2000/s,这个时候,主从复制延时大概是在小几十毫秒

c.解决

1)分库,将一个主库拆分为多个主库,每个主库的写并发就减少了几倍,此时主从延迟可以忽略不计

2)插入数据时立马查询可能查不到,延迟一段时间后再查

3)如果确实是存在必须先插入,立马要求就查询到,然后立马就要反过来执行一些操作,对这个查询设置直连主库。不推荐这种方法,你要是这么搞,读写分离的意义就丧失了。

     

标签:事务,今生,查询,索引,InnoDB,mysql,日志,数据,id
From: https://blog.csdn.net/qq_25611585/article/details/142958276

相关文章

  • 高可用 proxysql + mysql MGR
    MGR配置安装系统:centos7.9yuminstallhttps://repo.percona.com/yum/percona-release-latest.noarch.rpmpercona-releaseenable-onlyps-8x-innovationreleasepercona-releaseenabletoolsreleaseyuminstallpercona-server-server第一台机器配置#mgr#basic......
  • 倒排索引及ES相关概念对比MySQL
    一、倒排索引1、先把文档内容进行分词,形成词条与文档ID的对应关系,叫做词条库,词条具备唯一性,建立索引2、对搜索内容进行分词,分词后得到一个关键词列表,根据关键词去词条库中匹配,在找对应的文档ID列表3、然后根据文档ID列表,找到对应的文档信息对比:   二、ES相关概念对比My......
  • Elasticsearch相关概念对比mysql
    一、简介ElasticSearch是强大的搜索和分析引擎。能快速存储、检索和处理大量数据,提供实时搜索结果,擅长处理复杂查询,助力企业从海量数据中获取有价值信息,优化业务决策和提升用户体验。二、术语2.1索引Elasticsearch中的索引类似MySQL中的表,是相同类型文档的集合。它如同表......
  • 5大主流方案对比:MySQL千亿级数据线上平滑扩容实战
    在项目初期,我们部署了三个数据库A、B、C,此时数据库的规模可以满足我们的业务需求。为了将数据做到平均分配,我们在Service服务层使用uid%3进行取模分片,从而将数据平均分配到三个数据库中。如图所示:图片后期随着用户量的增加,用户产生的数据信息被源源不断的添加到数据库中......
  • Windows安装MySQL(zip安装)
    1.下载#dev.mysql.com>Download>下载MySQLCommunity(GPL)Downloads2.配置my.ini[mysqld]#一定要加这个,默认启动端口是3306,一般不会用默认端口port=50013#设置mysql的安装目录,一定要\\,否则不识别basedir=G:\\soft\\mysql-8.4.3-winx64#设置mysql数据库的数据的......
  • C#连接MySQL8.0数据库失败
    环境.net7MySQL8.0报错提示:未经处理的异常System.AggregateException:“Oneormoreerrorsoccurred.(Authenticationmethod'caching_sha2_password'failed.Eitheruseasecureconnection,specifytheserver'sRSApublickeywithServerRSAPublicKeyFile,......
  • 三:mysql条件查询
    三:mysql条件查询1:查询工资等于5000的员工 ......
  • 二:MySQL的操作
    二:MySQL的操作1:创建数据库    createdatabase bjpowernode;2:使用数据库   usebjpowernode;3:导入数据库文件sql   source 然后把SQL文件拖过来就可以了4:删除数据库     draopdatabase bjpowernode;5: 查看一个数据库中有什么表格  ......
  • 一:MYsql安装登录,服务开启和停止,和连接数据库
    一:MYsql安装登录,服务开启和停止,和连接数据库一、卸载不要的环境下面演示安装的版本为5.7版本,安装先把身份切换为root,方便操作首先先检测自己的环境,是否存在mariadb和系统自带MySQL,如果存在需要进行停止相应服务psajx|grepmariadbpsajx|grepmysql我的环境没有mariadb......
  • ES相关概念对比MySQL
    elasticsearch是面向文档(Document)存储的,可以是数据库中的一条商品数据,一个订单信息。文档数据会被序列化为json格式后存储在elasticsearch中:因此,原本数据库中的一行数据就是ES中的一个JSON文档;而数据库中每行数据都包含很多列,这些列就转换为JSON文档中的字段(Field)。1.3.2.索引......