Mysql(上)

81 阅读9分钟
  • Mysql架构
  • 1.0 单机架构-》2.0主从架构-》3.0分库分表架构-》4.0云数据库
  • mysql体系架构
  • 客户端连接器、系统管理和控制工具、连接池、SQL接口、解析器、查询优化器、缓存、可插拔存储引擎、系统文件、日志
  • 日志文件:
  • 错误日志:默认开启,show variables like '%log_error%'
  • 查询日志:默认关闭
  • 二进制日志:可以用作恢复
  • 慢查询日志:记录执行时间超时的sql,默认10s
  • 配置文件
  • .ini
  • 数据文件
  • data文件夹下
  • db.opt 字符集
  • ...
  • pid文件
  • socket文件
  • 运行机制
  • 建立连接SQL->查询缓存-》解析器-》解析树-》预处理器-》新解析树-》查询优化器-》执行计划-》查询执行引擎-》innodb/myisam
  • 1.建立连接
  • 全双工:同时发送和接收数据,例如打电话
  • 半双工:要么发送,要么接收
  • show processlist查看用户正在执行的线程信息
  • 2.查询缓存
  • 如果有相同的SQL直接返回结果
  • 缓存结果和Sql语句
  • 3.解析器、查询优化器
  • 等价变换
  • 优化count/min/max函数
  • Innodb min找索引左边
  • in 先二分查找再排序
  • 4.执行引擎机制
  • 返回结果过多,增量返回
  • MYSQL存储引擎
  • innoDB和Myisam对比
  • innodb:支持事务,可以提交回滚回复能力,事务安全
  • myisam:不支持事务和外键,访问速度快
  • (缓存,读操作)innodb_buffer_pool_size可以调整为总内存的60%-80%
  • 写操作缓存:chaange bugger,占用25%的bufferpool
  • 更新记录时在bufferpool中存在直接修改,如果不存在,则在changebuffer进行内存操作,减少磁盘Io
  • logbuffer:日志缓存
  • 日志文件刷新时间时间为1秒,最多丢失1秒的数据
  • tablespaces(磁盘结构):
  • 系统表空间
  • 独立表空间
  • 通用表空间
  • undo:撤销日志空间
  • 临时表空间
  • Doublewrite buffer:双写缓存,
  • 撤销和回滚
  • mysql5.7版本可以安装时自由指定undo文件大小和数量
  • 临时表空间可以根据会话存储
  • innodb线程模型
  • Master thread:负责调度其他线程,优先级最高,将缓存池的数据刷新到磁盘
  • IO thread:异步io,4个读4个写线程
  • purge thread:清理undo日志
  • page cleaner thread:将脏数据刷到磁盘
  • 文件存储结构
  • tablespace(ibd文件):
  • segment(段)->
  • 管理多个extent
  • extent(区)->
  • 包含64个页大小为1M
  • page(页)->
  • 大小为16k
  • row(行)
  • 包含了记录字段,事务id,滚动指针,字段指针
  • page是文件的最基本单位,由page header,page trailer,page body组成
  • innodb文件存储格式
  • binlog:记录所有数据库表结构变更以及表数据修改的二进制日志
  • 主从复制
  • 数据恢复
  • 三种记录模式1,ROW 2.STATMENT 3.MIXED
  • 事件触发机制:log event保存在binlog_cache_mngr数据结构中
  • 在事务提交阶段产生log event
  • mysqlbinlog --start-position=xxxx --stop-positon=xxx
  • xxx | mysql - uroot -pxxx
  • binlog和redo log的区别
  • 1.redolog是属于innodb引擎功能,binlog是mysql server自带功能,是二进制
  • 2.redo log是物理日志 ,记录状态内容,binlog是逻辑日志,更新过程
  • 3.redo log是循环写入,空间大小固定,binlog是追加写入,递增
  • 4.redo log是作为服务器异常宕机事务数据恢复,binlog是可以作为主从复制和人为删除数据恢复使用,但是没有自动恢复能力
  • MYSQL索引
  • 所以可以提升查询速度,影响where查询,以及order by排序
  • 有B tree结构,有hash结构,fulltext全文索引,R tree索引
  • 1.普通索引
  • create index on tablename(字段名)
  • 2.唯一索引
  • create unique index<索引名称>on tablename(字段名)
  • 3.主键索引
  • 4.复合索引
  • 尽量减少复合索引的字段,窄索引更有效
  • 5.全文索引
  • 必须在字符串和文本字段建立
  • 在数据量较少时可以使用Like模糊查询,数据量大时效率低。5.6之后myisam和Innodb都支持,5.6之前innodb不支持
  • 用match和against关键字使用
  • 根据最大和最小匹配参数位数来匹配(innodb:3-84,myisam:4-84)
  • 有切词符切分后的内容匹配(按syntax字符切割)
  • like可以加入*号用boolean值匹配(默认等值匹配)
  • 二分查找法(有序的数据)
  • 优点:等值查询、范围查询性能优秀
  • 缺点:更新数据,新增数据,删除数据维护成本高
  • Left和right指针,
  • 相加再除2,大于目标值right移动,小于left移动,直到锁定目标值
  • Hash结构
  • 自适应哈希索引:一次性查找就能定位数据,等值查询效率高
  • B+tree结构
  • 非叶子节点不存储节点数据,只存储索引值,叶子节点包含所有的索引值和数据,叶子节点用指针连接
  • 从根节点开始二分查找,如果没有找到,再到子节点二分查找
  • 聚集索引:主键索引,Innodb必须有主键索引,B+的叶子节点就是主键索引排序
  • 辅助索引:先通过辅助索引树找到id再通过主键索引找到数据
  • EXPLAIN:执行计划
  • select_type:查询类型,
  • SIMPLE:简单查询,没有子查询
  • PRIMARY:表示最外层
  • UNION:表示查询是UNION的第二个或者后续的查询
  • DEPENDENT UNION:UNION使用了外层的查询结果
  • UNION RESULT:UNION结果
  • SUBQUERY:子查询
  • DEPENDENT SUBQUERY:子查询依赖外层查询结果
  • type:可以判断查询方式,是全表扫描还是索引
  • all:全表扫描
  • index:基于索引的全表扫描
  • range:范围查找
  • ref:表示使用非唯一索引进行单值查询
  • eq_ref:多表Join查询中主表只匹配附表一条记录
  • consf:主键或者唯一索引,等值查询
  • null:不访问表,直接查找
  • 以上类型从上至下效率依次增强
  • key_len:表示查询使用的字节数量。可以判断是否全部使用了组合索引
  • rows:扫描多少行
  • keys:索引
  • Extra:using index是用了索引
  • 回表查询:using where
  • 先通过辅助索引定位主键,再通过聚合索引定位数据就叫回表
  • 覆盖索引:
  • 用覆盖索引可以不用回表,方法是将查询的字段建立组合索引
  • 复合索引只能从最左边的字段开始匹配
  • like模糊查询,索引是否能起作用
  • 只有右模糊起作用
  • 如果某列有Null值,索引是否有效:是有效的
  • 排序中,where条件中用索引字段范围查询不走索引
  • 当有where等值查询和Order by用组合索引
  • 查询优化:
  • 开启慢查询日志
  • long_query_time:慢查询的阀值
  • 提高索引的过滤性:索引字段值多
  • 设置虚拟列
  • 慢查询的原因:全表扫描,全索引扫描、索引过滤性不好、频繁回表
  • 分页查询优化:
  • show profiles;显示sql执行时间
  • 查询数据量小于100条时,查询时间基本不变,记录量越大查询时间越长
  • 偏移量超过100,查询时间花费多
  • 1.可以通过覆盖索引,只查询索引字段
  • 2.利用子查询优化
  • MYSQL的事务和锁
  • ACID
  • 原子性:每一个事务是一个逻辑操作单元,要么全成功,要么全不成功
  • 每一个事务,都会修改bufferpool,再更新磁盘。如果中途数据库挂了可以通过redo和undo日志恢复
  • 一致性:事务开始和事务结束后,数据的完整性未被破坏,分为约束一致性和数据一致性
  • 隔离性:事务不会互相干扰,隔离性从低到高为读未提交、读提交、可重复读、串行化
  • 持久性:事务一旦提交,改变是永久性的
  • 更新丢失:多个事务同时更新同一条记录,会产生更新丢失
  • 脏读:一个事务读取到了另一个事务未提交的数据
  • 不可重复读:一个事务中多次读取同一行记录不一致
  • 幻读:一个事务多次同条件查询结果不一致,多了或者少了记录
  • 互斥锁:支持并发,阻塞式
  • 读写锁:读和读之间不加锁
  • MVCC:多版本控制,空间换时间,可以支持读写和写读的并行,每次修改之前生成一个副本可以支持其他事务读
  • 乐观锁和悲观锁
  • MYSQL默认可重复读的隔离级别
  • 锁机制
  • 表锁,行锁,页锁(INNODB没有)
  • 从操作分类(行锁)
  • 读锁:
  • 写锁:
  • 性能分
  • 乐观锁和悲观锁
  • Recorde lock:单行记录锁
  • gaplock:间隙锁,锁住当前行和前后的间隙不能插入数据
  • Next-key lock:行锁和间隙锁,如果碰到唯一健,降级为单行锁
  • 悲观锁
  • 表级锁:
  • 表级读锁,不允许增删改操作,写锁当前连接可以做任何操作
  • 共享锁(行锁中的读锁)lock in share mode:只能读取不能修改
  • 排他锁(行锁中的写锁)for update:除了当前连接都不允许访问
  • !!如果字段未加索引,会锁表
  • 乐观锁:
  • 冲突检测,使用version或者时间戳字段
  • Mybatis有optimisticlocker插件
  • 死锁:
  • 1.表死锁:A用户访问A表,又访问B表,用户B访问B表,又访问A表。A由于B锁住B表,B用户又等待A表锁释放。
  • 是由于程序逻辑问题
  • 2.行死锁
  • 执行没有索引的查询,引发全表扫描,全表锁定,多个事务执行容易死锁和阻塞。
  • 优化sql、防重放、乐观锁
  • show engine innodb status
  • MYSQL分库分表
  • 垂直拆分:表过多或者字段过多,拆分后业务清晰,容易维护,缺点是冗余列,事务管理复杂
  • 水平拆分:表数据过多,按规则将数据打散,高并发性能好,表结构相同,只用路由规则,缺点是拆分规则难以抽象,join性能差,分布式事务一致性,扩容相对难
  • 分库分表主键策略
  • UUID/COMB/SNOWFLAKE/数据库id表/redis
  • 分片策略
  • 范围分片、hash取模、一致性hash
  • 扩容方案
  • 横向扩容,数据迁移、分片规则改变、数据同步和一致性
  • 1.停机扩容
  • 2.平滑扩容:double数据库
  • Mysql性能优化
  • 成本:SQL《表结构《系统配置《硬件升级
  • 效果:SQL》表结构》系统配置》硬件
  • 修改内存池大小my.cnf