Skip to main content

Mysql总结

Mysql

读多写少 读写分离

数据不同步怎么办?

主库从库 是采用异步复制数据,如果这两者之间数据还没有同步怎么办?

主库刚写完数据,从库还没来得及拉取最新数据, 请求就来了,给用户的感觉,数据丢了???

解决方案:

1)针对不用的业务诉求,区别性对待,如果对数据的 实时性 要求非常高,比如金融类业务。我们可以在客户端代码标记下,让查询强制走主库。如果是对数据的 实时性 要求不是很高,比如:大V有千万粉丝,发布一条微博,粉丝晚几秒钟收到这条信息,并不会有特别大的影响。这时,可以走 从库

2)我们可以考虑引入缓存作为缓冲介质

处理过程:

  • 客户端 SQL ,操作主库
  • 同步将缓存中的数据删除
  • 当客户端读数据时,优先从缓存加载
  • 如果 缓存中没有,会强制查询主库预热数据

3)在执行业务SQL操作时,先判断从库是否已经同步最新数据。从而决定是操作主库,还是操作从库。 缺点:无论采用上面哪一种方案,如果主库的写操作频繁不断,那么从库的值永远跟不上主库的值,那么读流量永远是打在了主库上。

这个问题跟 MQ消息队列 既要求高吞吐量又要保证顺序是一样的,从全局来看确实无解,但是缩小范围就容易多了,我们可以保证一个分区内的消息有序。

回到 主从库 之间的数据同步问题,从库查询哪条记录,我们只要保证之前对应的写binglog已经同步完数据即可,可以不用管主从库的所有的事务binlog 是否同步。

mixed 格式 的binlog 是个啥?

由于 statement 格式的binlog 可能会导致主库、备库间的数据同步不一致,因此我们会采用 row 格式。

但是,row 格式占用的空间很大,写 binlog 也要占用大量的 IO 资源。

所以,官方提出一种mixed混合模式,集成了两者的优点。

内容如下:

  • mysql会自动判断statement格式,是否会引发主备不一致的问题
  • 如果statement格式会引起主备不一致的问题,自动使用row格式。
  • 如果statement格式不会引起主备不一致的问题,那么就用statement格式。

事务

数据库有四种隔离级别,分别是:

  • 读未提交(READ UNCOMMITTED)
  • 读已提交 (READ COMMITTED)
  • 可重复读 (REPEATABLE READ)
  • 串行化 (SERIALIZABLE)

分页查询优化

如果要开发一个列表展示页面并支持翻页时,我们通常会这样写 SQL

select * from 表  limit #{start}, #{pageSize};

随着翻页的深度加大, start 值越来越大,比如:limit 10000 ,10

看似只返回了 10 条数据,但数据库引擎需要查询 10010 条记录,然后将前面的 10000 条丢弃,最终只返回最后的 10 条记录,性能可想而知

针对这个问题,我们通常有另一种解决方案:

先定位到上一次分页的最大 id,然后对 id 做条件索引查询。由于数据库的索引采用 B+ 树结构,这样可以一步到位

select * from 表 where id > #{id}  limit  #{pageSize};

任何事情,有利就有弊 这种翻页方式只支持 上一页下一页 ,不支持跨越式直梯翻页

我觉得这个问题属于mysql自己的设计问题,设计缺陷。他不应该这么设计,结果反而成为了开发人员的负担。。。

索引

是否命中索引,并不是评判 SQL 性能好坏的唯一标准。

其实,还有一个重要指标,那就是 扫描行数

当一个表很大时,不仅要关注是否有索引,还要关注索引的过滤性是否足够好。