mysql

作者: go_2021 | 来源:发表于2022-01-29 13:35 被阅读0次

耐心是一切聪明才智的基础。

3范式理解

 字段不可拆分,不冗余,都和id相关。

InnoDB

  • 支持事务,行级锁,外键(外键约束),崩溃恢复。
  • 5.6之后都支持FULLTEXT。
    • 可以创建在char varchar text字段上创建。
    • 类似于like,但是比like快n倍,貌似对中文支持不好。
  • 数据是存于聚集索引,而myisam数据和索引是分开文件存储的,可以更利于压缩,占用更小内存,适用于读插入频繁的操作。

其他数据库区别

  • redis
    内存,提供数据结构类型。(字符,hash,队列,集合, 有序集合)
  • hbase,clickhouse
    列式存储,不用一次把一行的数据加载到内存,更高的压缩率。行式修改比较费时,随机写。所以一般应用于离线大数据分析统计。
  • 芒果db
    文档性数据库,不像关系数据库,列是固定的,修改结构快。
  • es
    对倒排索引lucence的封装,类型mysql中的like,不过这个是专门做全文索引的,高可用,高性能。

表结构设计

  • 最好 非null 给默认值
    https://mp.weixin.qq.com/s/nvBvrHjPojoVez8W2VqjGg
    null也是占空间 。
    null程序逻辑判断 需要判断 要不容易出现 空指针异常。
    不利于索引的优化。
  • 时间类型 datetime 还是 int(百度是i) timeStamp
  • 字段空间 合适 TINYINT 不用 int。
    mybatis用map去接受tinyint数据 长度为1时 会自动转为布尔。。
  • 创建索引。

分库表

  • 统计:主从
  • 千万:
    分表 主要解决 查询问题 一个大树分成多个小树 查询快
    share jdbc(应用) mycat(proxy)
    分库 主要解决并发问题 提高吞度量
  • 硬件方面 普通硬盘 固态硬盘 raid磁盘阵列 提高并发和建立副本

问题排查

  • show processlist 命令查看当前所有连接信息
    show status like '%lock%';# 查询锁状态
    kill SESSION_ID; # 杀掉有问题的session
  • 开启慢查询日志,查看慢查询的 SQL。

buffer pool

  • free链(池外)+ LRU链(池内) = 全量数据

  • flush链(LRU链的子级)记录需要刷新到硬盘的数据,刷新之后,添加到free链里。

  • 判断数据是否在池内,有个数据页缓存哈希表key为表空间id+数据页id,value为缓存地址。

  • 转换过程:
    • 启动时,硬盘数据会存在free链中。
    • 从mysql读数据是 free链->LRU链的过程。
    • 写入mysql 是LRU链节添加到flush链->写入到硬盘->free链的过程。
    • 定时把LRU链上的冷数据回收->free链。
  • 预读机制

分层

  • 服务层
    连接层->词法,语法分析(有缓存走缓存)->
    优化层-> 执行层->
    缓存层(key是SQL语句,value是查询结果,类似于mybatis的二级缓存,all session共享)
  • 存储引擎
    (Innodb,pool buff也算是缓存)

3层最大数据

  • 下一层存储数据条数=上一层最大数据条数*一页数据条数
  • 第一层,一条数据大小按照(8bitint+8索引)16byte来算,一页16kb,所以大约最多存1024条数据。
  • 第二层,存储数据条数=1024\*1024 = 100w
  • 第三层,一条数据大小按照1kb算,一页数据条数就是16.
    存储数据条数=100w\*16 = 1600w

https://juejin.cn/post/6953442154249191454

基数

  • 列的不同值数量,例如性别列的基数为2。
    更新时机是默认大于条数10%时更新。
    值是估算的默认20个数据页抽查。
    可以主动去更新表的基数值。
    默认基数不会持久化,可以开启,提高重启速度。

记录数据插入的过程

  • 1.先锁定写入的数据页,表最大记录的数据页还有位置就用这个数据页,否则就在硬盘上找一个新的数据页。
    2.记录undolog,为提供事务隔离性。
    3.写入页缓存,存上flush链(异步刷新到磁盘,每秒会以一定比例落盘,当redolog不可用,mysql关闭,flush链数据达到一定比例也会触发落盘)。
    4.写入到redologbinlog,写入redolog会有2次提交,第一次会写入状态标记为准备,第二次改为已提交。(两种日志格式个功能不一样,必须保证同步)

change buff

占有pool buff的一部分默认是25%,用于提升二级索引的写入性能。

慢查分析优化

  • 默认long_query_time 是10s,所以一般都是需要调整这个参数。
    5.1之后,可以修改为table模式,会添加到表里记录。
show variables like '%slow%';//查看相关的设置。
show processlist;
mysqldumpslow -s a1 -n 10  mysql.slow_log

优化器,索引,分表
优化器会考虑字段基数。
扫描行数,期望用二级索引,但是考虑到回表可能会直接走主键。
排序倾向于本来有序的字段。

MVCC

  • readView+undolog
    readView在事务开始时生成,当前事务id,活跃事务ids,活跃最小事务ids,下一个事务id。
    undolog记录修改数据记录和事务id绑定。
    事务61事务62同时开启:
    [61, [61,62], 61 , 63]
    [62, [61,62], 61 , 63]
    事务1读id为1的记录,在undolog中有事务60的记录,因为60不在活跃事务里,所以是已经提交的可以直接读。
    事务2修改id为1的记录,undolog中会有事务60,事务62的记录。
    这是事务2没有提交,事务1再次读id为1记录拿到的是事务62的记录,对比在活跃事务里但是比自己大,不能查看,继续找到事务60的记录查看。
    这时候事务62提交了,事务61readview会更新为[61, [61], 61 , 63],再去读undo中事务62的记录,发现不在活跃事务列表里了说明是已经提交的版本,可以查看。

undolog

  • 事务隔离性,以及事务回滚。
    逻辑日志,记录了事务中操作中插入的id,修改和删除字段原值,已备回滚。
    日志格式会记录事务id,下一条undolog位置(形成一个链表),表空间字段值等一些信息。
    默认是共享表空间,可以通过设置单独文件存储,在MySQL5.7中允许用户在线truncate undo log。
    回滚是逻辑回滚。

redolog

  • 崩溃恢复能力。
    innodb引擎为保证持久化,物理层面的,数据页偏移量,关注宕机后如何恢复已提交但是还没有落盘的数据。
    以redoblock(512kb)形式记录,head,tail,body,其中按照事务id进行分组;
    会先写入redologbuff(16M),写入硬盘可以配置参数,innodb_flush_log_at_trx_commit,
    0:每秒落盘一次;
    1:提交就落盘;(默认)
    2:依托os,每秒落盘一次。
    checkpoint记录redolog写入磁盘的位置,如果发生重启,按照checkpoint恢复之后的redolog即可。

binlog

  • 数据备份,恢复,主从。
    逻辑概念,对表做了什么修改,是server层的什么引擎都会记录。
    默认不开启,线上一般都是主从会开启。
    statement,row,maxed3种模式。
    row会比第一种多记录一些信息。
    一般是binlog_row_image=FULL + row格式进行记录,尽量详细记录。
//查看binlog
./mysqlbinlog -vv  --start-position=234 ../var/mysql-bin.000001
//恢复binlog
./mysqlbinlog start-positon=956,stop-position=1230 ../var/mysql-bin.000003 | ./mysql-uroot -p
//开启gtid需要添加
--skip-gtids=true

可以查看对应位置的语句。
gtid记录事务的唯一id,可以根据这个方便主从之间的同步,哪些事务需要同步。
sync_binlog
0 不主动落盘,依赖os的调度。(默认)
1 提交就落盘。(推荐)
n 分组到多少组,一并落盘。

相关文章

网友评论

    本文标题:mysql

    本文链接:https://www.haomeiwen.com/subject/kdzxkrtx.html