mysql 相关内容

mysql 主从同步原理

1)、复制类型

1.1)、SBR(STATEMENT)模式

基于语句,主库将每一条会修改的sql语句记录到 binlog 中,

优点:不需要记录每一条sql和每一行数据变化,减少 binlog 日志量,节约IO,提高性能

缺点:某些情况下会导致 master 和 slave 的数据不一致(如 sleep()、last_insert_id()、user_defined function(udf)等会出问题)

2)、RBR(ROW)模式

基于行数据,不记录sql语句,只记录哪条数据被修改了

优点:不会出现某些特定情况下的存储过程、function、触发器调用无法被正确复制的问题

缺点:会产生大量的日志,尤其是 alter table 的时候

3)、MBR(MIXED)模式

SBR 和 RBR 两种模式的混合使用,一般的复制使用 SBR 模式保存 binlog,对于 SBR 模式无法复制的操作使用 SBR 模式保存 binlog,mysql会根据执行的sql选择日志保存方式

2)、工作原理

2.1)、开启bin log 功能后,master 操作发生了变化就会记录到 binlog(binary log) 二进制日志中

2.2)、slave 会启动一个单独的 IO thread 连接 master,请求 master 从指定位置更新的 bin log 内容

2.3)、master 会创建一个 log dump 线程用于发送 binlog 内容,在读取 binlog 过程中 master 会对该文件加锁,读取完成之后释放锁

2.4)、slave 获取到 binlog 日志后保存到自己的 reply log 日志文件中

2.5)、slave 有一个 sql thread 定时检查 reply log 是否有变化,有变化就更新数据

mysql select查询过程

查询主要经过了 连接处理、sql 语法解析(sql语法树)、sql优化、sql执行 这四个步骤

sql优化

优化分为 子查询优化、条件化简、语义优化、多表连接优化、外连接优化、嵌套连接优化、视图重写、谓词重写等

mysql事务原理

mysql的事务是通过 redo log 、undo log 、MVCC(乐观锁)和 锁(悲观锁)来实现的

1)、redo log

定义:重做日志,用来实现事务的持久化,它包含 redo log buffer(重做日志缓冲,在内存中)和 redo log(重做日志文件,在磁盘上),事务没有提交前将事务操作存入 redo log buffer 缓存中 ,当事务成功提交后,则会将 redo log buffer 中的缓存事务持久化到redo log 文件中

作用:用于持久化已提交事务,防止事务信息丢失,用于恢复数据保障

mysql为了提高性能不会每次修改都直接实时同步到磁盘中,而是先缓冲到 Buffer Pool(缓冲池) 中,然后使用后台线程定时做Buffer Pool与磁盘的同步,这里就会有事务丢失的问题,而 redo log的解决了此问题


2)、undo log

定义:回滚日志,每次写入数据或者修改数据之前都会把修改前的信息记录到 undo log 中,和 redo log(记录修改后的数据信息) 正好相反

作用:用于回滚数据,保障未提交事务的原子性

如果系统错误或者发生rollback操作而需要回滚的话,可以根据 undo log 信息来进行回滚到被修改前的状态

mysql一个整体事务处理如下图所示:

mysql 相关内容_第1张图片

MVCC乐观锁

定义:MVCC (Multi-Version Concurrency Control) 是一种多版本并发控制协议,只有在 InnoDB 存储引擎下存在

作用:实现一致性非锁定读,这就有保证在同一个事务中多次读取相同的数据返回的结果是一样的,解决了不可重复读的问题,实现事务的隔离性,通过版本号避免同一数据在不同事务间的竞争

原理:通过在每行记录后面增加两个隐藏的数据列来实现,这两个列一个保存的是行的事务版本号(可以理解为创建时间),一个保存的是行的删除版本号(可以理解为删除时间)

每开始一个新的事务,事务版本号就会递增,行的系统版本号都会更新成事务的当前版本号,用来和查询到的每行记录做版本号比较

select: 查询出来的记录必须符合以下两个条件:

1)、行版本号小于等于当前事务版本号,这样可以确保事务读取的行要么是在事务开始之前存在的,要么就是事务自身插入或者修改过的

2)、无删除版本号或者删除版本号大于当前事务版本号,这样可以确保事务是在删除操作之前进行的,读取的数据当然也是没有被删除的

insert: InnoDB 为每一个新增的行保存事务版本号作为行版本号

delete: InnoDB 为每一个删除的行保存事务版本号作为行删除标识(删除版本号)

update: InnoDB 为每一个新增的行保存事务版本号作为行版本号,同时将当前事务的版本号作为原来的行的删除版本号,使大多数操作都不用加锁。 缺点是每行记录都需要额外的存储空间来存储删除了的数据行

MVCC 只适用于 mysql 中的 RC(读已提交)、RR(可重复读/可幻读)隔离级别,不适合 RU(读未提交)和 Serializable(串行化)隔离级别,原因如下:

1)、MVCC创建的版本号只有在事务提交之后才会产生,所以必须是 RC,而不能是 RU

2)、Serializable 隔离级别时mysql会对整张表加锁,此时自然不会存在事务并发问题

MVCC 主要作用于事务的,有行锁控制的数据库模型,主要用于读并发控制,因为更新时都会加锁,使用 MVCC 并没有太大意义

InnoDB 通过 MVCC(多版本并发控制) 解决不可重复读问题,加上间隙锁(并发控制)解决幻读问题

InnoDB 的 RR(可幻读)隔离级别实际上实现了串行化的效果,而且还保留了好的并发性能

事务的隔离性是通过乐观锁(MVCC)实现的,而事务的一致性、原子性和持久性是通过事务日志实现的

sql优化过程

1)、打开慢查询日志,监控到慢sql

2)、分析sql是否可以加索引

创建索引规则如下:

2.1)、索引并非越多越好,大量的索引不仅会占用很大的磁盘空间,而且会影响 insert、update 和 delete 的性能

2.2)、对于频繁更新的表尽量少见索引,如果要建索引的话(经常要查询的列),索引的列尽可能的少

2.3)、对于数据少的表不要建索引,数据较少,查询时间可能比遍历索引还要短,索引可能被不会产生优化效果

2.4)、频繁排序或者分组的列建立索引,如果排序的列有多个,可以建立联合索引

2.5)、区分度低(不同值很少的字段,例如男、女)的字段不要建索引

3)、使用 explain 命令分析sql是否用到了索引,如果没有用到的话则修改sql用上索引

4)、索引也无法优化的情况下,使用代码将复杂查询拆分成多次查询

5)、使用ES搜索引擎做查询

索引分类

物理存储角度:聚簇索引和非聚簇索引

数据结构角度:B+树索引、hash索引、FULLTEXT全文索引、R-Tree索引

逻辑角度:主键索引、普通索引、唯一索引、联合索引、空间索引(空间索引是对空间数据类型的字段建立的索引,MYSQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON)

hash索引

hash索引使用某种哈希算法将键值转换为新的哈希值。不需要像B +树那样从根节点到叶节点逐步搜索。只需要一种哈希算法,就可以立即找到对应的位置,速度非常快

优点:如果只是查询某个条件的等价查询(hash冲突低),hash索引非常高效

缺点:

1)、hash索引无法支持范围查询

2)、hash索引无法使用索引排序和模糊匹配

3)、hash索引不支持联合索引的最左匹配规则

4)、键值大量冲突的情况下,hash索引效率很低,需要遍历链表来匹配查找数据

mysql某表建了多个单索引,查询多个条件时如何走索引的?

这里主要就是看优化器是如何选择索引的,优化器会评估出使用哪个索引最优,然后执行查询

mysql在优化器中有一个 Range 优化器,负责进行范围查询的优化,该优化器计算成本有两种方式: index dive 和 index statistics,它们是对开销代价的估算方法

一、index dive

统计速度慢但是能得到精准的值

计算成本方式:COST = CPU COST + IO COST

COST 是总花销时间,CPU COST 是处理返回记录数据花销时间,IO COST 是操作IO所花销的时间

mysql会对查询条件中用到的每个索引进行上述成本估算,最后以最小成本来选择索引执行sql

二、index statistics

统计速度快但是数据不精准

计算成本方式:SHOW INDEX FROM tbl_name [FROM db_name]

查询出来的结果中有一个列名为 Cardinality,表示索引列中不重复值得个数(即唯一值得个数),这个值越大说明数据区分度越高,优化器会选择 Cardinality 值最高的索引,反之优化器会认为这个索引对语句查询没有太大帮助而放弃选择该索引

在某些情况下mysql执行 index dive 的成本太大,因此优化器会选择以index statistics方式进行估算成本

 

select * from t where a = 1 查询时,IO次数,考虑最多,单表3000万数据时

1)、覆盖索引的话,最多3次,也可以说最多2次,看是否考虑mysql启动那次

2)、主键索引,最多3次

3)、辅助索引,最多6次

4)、之前查询过了的话,0次

 

 

你可能感兴趣的:(mysql)