杂谈-202109

9月1日答疑:

1、InnoDB如何保证数据页写入时,页损坏的数据也能被正常修复。

首先明确以下概念:

页损坏:MySQL的单个page有16k大小,而文件系统的1页只有4k。因此在刷新脏页时,实际上是4次写入,若在中途发生断电之类的故障,就会出现页损坏。

Double write buffer

InnoDB使用了DWB(double write buffer)用于保证在数据真正写入数据页之前,由double write buffer 先落到对应的磁盘,这样即使出现了由于断电引起的页损坏,也能够恢复。

请添加图片描述

如果是异常退出,Mysql重启过程:

(1)检测到上次为异常关闭

(2)尝试恢复ibd数据,失败(因为出现了页损坏的数据)

(3)从DWB中恢复写了一半的页

相关博文:https://blog.csdn.net/liuxiao723846/article/details/103509226

扩展一个问题:

DWB如果在第二部即 DWB往数据磁盘上存数据时,此时如果断电了,会怎么样?

此时,我们可以考虑一个问题,当我们DWB往数据磁盘上存数据时,还没有将数据页真正的落盘,理论上应该不存在页损坏问题。我们可以考虑使用redolog进行数据恢复。

dirtyPage中持久化到redolog

事务中修改的任何数据,将最新的数据备份存储的位置(RedoLog),重做日志

关于redolog可以参考:https://blog.csdn.net/tiancaideshaonian/article/details/119719734
请添加图片描述请添加图片描述
关于执行顺序:

1 先执行

2、3同时执行

4、执行

这里需要针对两个点

buffer pool中脏页刷盘的行为是通过dwb进行保证的

log buffer 生成 redolog由于数据不丢失需要通过redolog进行保证,因此针对某条记录而言redolog的刷盘行为应该会先于数据刷盘

因此针对上述问题,由于此时实际上的还没开始刷到磁盘,而redolog中会存在重放日志,因此我们可以通过redolog恢复数据。

2、MySQL中的某数据页的磁盘空间仅剩1B。此时,将某VARCHAR字段的值从’1’修改为’100’,也就需要额外的2B空间。但此时数据页没有足够的磁盘空间,这种情况下是否会产生页分裂?

先明确一个概念:

页合并:当你删了一行记录时,实际上记录并没有被物理删除,记录被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。当页中删除的记录达到MERGE_THRESHOLD(默认页体积的50%),InnoDB会开始寻找最靠近的页(前或后)看看是否可以将两个页合并以优化空间使用。

规则就是:页合并发生在删除或更新操作中,关联到当前页的相邻页。如果页合并成功,在INFOMATION_SCHEMA.INNODB_METRICS中的index_page_merge_successful将会增加。

页分裂:

首先我们知道,innodb中的数据是以页为存储单元。如果此时页中已经存了99%的空间,新的数据需要进来,发现空间不满足(比如第10页),就会找下一页满足的,如果下一个也就是第11页也满了,此时,为了保证数据的顺序性,需要调整页之间的关系

page-9<-page-10<-page-12<-page-11

规律总结:页分裂会发生在插入或更新,并且造成页的错位(dislocation,落入不同的区)

参考资料:https://zhuanlan.zhihu.com/p/98818611

针对上述前半段问题,我们需要引入一个概念:溢出页。

参考资料:https://www.jb51.net/article/200618.htm

MySQL想让一个数据页中能存放更多的数据行,至少也得要存放两行数据。否则就失去了B+Tree的意义。B+Tree也退化成一个低效的链表。

你可以品一下这句蓝色的话,他说的每个数据页至少要存放两行数据的意思不是说 数据页不能只存一行。你确确实实可以只往里面写一行数据,然后去吃个饭,干点别的。一直让这个数据页中只有一行数据。

当你往这个数据页中写入一行数据时,即使它很大将达到了数据页的极限,但是通过行溢出机制。依然能保证你的下一条数据还能写入到这个数据页中。

更改数据类型其实并不会对原有数据产生影响。

3、常用nosql,以及一些使用场景

https://blog.csdn.net/wyz0516071128/article/details/80877984

自己的一些总结:

目前使用较多的相对来说 redis比较多。

mogodb主要用于存储一些文本信息,或者json串之类的。也可以用于解决海量数据的访问效率问题

Hbase 采用列式存储,同样也可以用于海量数据的存储访问。

9月8日答疑

1、问题描述:报表类应用如何设计缓存?

背景:数据库类有约1000W明细数据,包含交易大区,交易小区,城市,业务类型,一级负责人,二级负责人等近10个维度字段。前端提供基于这些维度字段的自由分类,汇总,排序等操作的报表,也会下钻查看明细数据。这样的系统如何进行缓存的设计?

(1)mongodb存储数据。因为MongoDB查询相对于快点,一般修改比较少,存入的数据可以嵌套,然后mongoDB提供了一下聚合函数。

(2)利用ES建立索引

(3)如果使用Redis做一个缓存的话,可以利用Hash (a维度_b维度__c维度 -> value)

之前见过一个 利用ES + HBase 实现快速查询的案例,后面可以翻出来看看

2、关于延时双删的加锁阶段

请添加图片描述

在更新数据库时,对key进行了加锁操作。

强一致性很难,这个方案也只是追求最终一致性。延时时间内如果有其他线程读取了缓存确实就会读到旧的,但是延时后就是正常的数据了。

3.一个服务挂了配多长时间重试?

针对上述问题从以下两个方面进行分析

1.是自己的服务器挂了

此时需要通过运维,针对自己的应用服务器,以及应用实现实时告警以及CPU预警等。尽量早的参与到修障过程。

2.依赖外部的服务结构

a.是否需要重试

一些不重要的日志信息,可以直接忽略重试机制

b.重试按照什么维度:通知频率?

后台通知交互时,如果微信收到商户的应答不符合规范或超时,微信会判定本次通知失败,重新发送通知,直到成功为止(在通知一直不成功的情况下,微信总共会发起多次通知,通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m),但微信不保证通知最终一定能成功。

4.对于分库分表,怎么实现分页查询

a.基于一些中间件如shardingjdbc进行分页查询。

1.通过不同的分库规则,实现多个分片,

2.每个分片分别进行分页查询,再在内存中进行汇总,最后再进行一次分页查询,就可以得出最终的结果。
3.分页的总条数,是另一次查询,不在上面的步骤中计算

b.引入es

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值