侧边栏壁纸
博主头像
Haenu的Blog 博主等级

坚持学习,慢慢进步!

  • 累计撰写 35 篇文章
  • 累计创建 10 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Mysql笔记

Haenu
2024-06-24 / 0 评论 / 0 点赞 / 61 阅读 / 0 字

基础部分

Mysql 字段类型

数值类型: int bigint smallint tinyint mediumint

float double decimal

字符串 : char varchar text tinytext mediutext bigtext

日期 year time date datetime timestamp

Mysql的执行流程

先经过连接器 身份认证和权限 然后查询缓存 有缓存就返回 没有就去走分析器 去看我们的语句是干嘛的 然后走优化器 去选择索引最后走执行器 操作引擎返回结果

这其中我讲一下执行器吧 执行器调用引擎API接口 然后写到redo log里 但是 redo log此时不提交 他做个prepare状态通知我们的执行器 执行器接收到后去写到binlog里 然后将redo log 提交

这样的好处就是 解决了数据不一致的问题

假如我们先提交redolog 后提交binlog 他中间宕机了 就会导致我们主从同步出现数据不一致问题

如果我们先提交binlog 后提交redolog 我们本机缺一条数据 但是binlog又有数据 就会数据不一致

所以采用了这个prepare

然后数据极端情况 数据库异常重启

他先会判断 redolog 是否完整 完整就返回 不完整就报错

如果redolog是预提交 他会看binlog是不是完整 完整就commit 不完成就回滚走事务

MyISAM和InnoDB有什么区别?

MyISAM 只支持表级锁 不支持行级锁

M 不能用外键 不能用事务

M不支持安全恢复 InnoDB可以根据redolog来进行恢复

InnoDB的一次更新事务是怎么实现的?

1、在Buffer Pool中读取数据:当InnoDB需要更新一条记录时,首先会在Buffer Pool中查找该记录是否在内存中。如果没有在内存中,则从磁盘读取该页到Buffer Pool中。

2、记录UndoLog:在修改操作前,InnoDB会在Undo Log中记录修改前的数据。Undo Log是用来保证事务原子性和一致性的一种机制,用于在发生事务回滚等情况时,将修改操作回滚到修改前的状态,以达到事务的原子性和一致性。UndoLog的写入最开始写到内存中的,然后由1个后台线程定时刷新到磁盘中的。

3、在Buffer Pool中更新:当执行update语句时,InnoDB会先更新已经读取到Buffer Pool中的数据,而不是直接写入磁盘。同时,InnoDB会将修改后的数据页状态设置为“脏页”(Dirty Page)状态,表示该页已经被修改但尚未写入磁盘。

4、记录RedoLog Buffer:InnoDB在Buffer Pool中记录修改操作的同时,InnoDB 会先将修改操作写入到 redo log buffer 中。

5、提交事务:在执行完所有修改操作后,事务被提交。在提交事务时,InnoDB会将Redo Log写入磁盘,以保证事务持久性。

6、写入磁盘:在提交过程后,InnoDB会将Buffer Pool中的脏页写入磁盘,以保证数据的持久性。但是这个写入过程并不是立即执行的,是有一个后台线程异步执行的,所以可能会延迟写入,总之就是MYSQL会选择合适的时机把数据写入磁盘做持久化。

7、记录Binlog:在提交过程中,InnoDB会将事务提交的信息记录到Binlog中。Binlog是MySQL用来实现主从复制的一种机制,用于将主库上的事务同步到从库上。在Binlog中记录的信息包括:事务开始的时间、数据库名、表名、事务ID、SQL语句等。

日志部分

slow query log(慢查询日志)

如何去定位慢查询

方案:Mysql自带慢查询日志

黑马回答

嗯~,我们当时做压测的时候有的接口非常的慢,接口的响应时间超过了2秒以上,因为我们当时的系统部署了运维的监控系统Skywalking ,在展示的报表中可以看到是哪一个接口比较慢,并且可以分析这个接口哪部分比较慢,这里可以看到SQL的具体的执行时间,所以可以定位是哪个sql出了问题

如果,项目中没有这种运维的监控系统,其实在MySQL中也提供了慢日志查询的功能,可以在MySQL的系统配置文件中开启这个慢日志的功能,并且也可以设置SQL执行超过多少时间来记录到一个日志文件中,我记得上一个项目配置的是2秒,只要SQL执行的时间超过了2秒就会记录到日志文件中,我们就可以在日志文件找到执行比较慢的SQL了。


如何优化慢查询

可以用EXPLAIN来获取sql语句的执行计划 ,然后根据key 和 key_len来判断是否命中索引

还可以根据Extra来查询是否出现了回表的情况

然后还有一个type字段

黑马回答

面试官:那这个SQL语句执行很慢, 如何分析呢?

候选人:如果一条sql执行很慢的话,我们通常会使用mysql自动的执行计划explain来去查看这条sql的执行情况,比如在这里面可以通过key和key_len检查是否命中了索引,如果本身已经添加了索引,也可以判断索引是否有失效的情况,第二个,可以通过type字段查看sql是否有进一步的优化空间,是否存在全索引扫描或全盘扫 描,第三个可以通过extra建议来判断,是否出现了回表的情况,如果出现了,可以尝试添加索引或修改返回字段来修复


binlog(二进制日志)

binlog 是什么?

binlog是二进制日志文件 他把每一条更改语句进行了保存 包括表结构和数据

binlog 的格式有哪几种?

有三种模式

第一种是statement 他是把每一条sql保留

第二是row 他是记录变更事件

第三个是mixed 他是上面两种的混合

binlog 主要用来做什么?

主从复制

主从复制的流程

  1. 主库把sql写到我们的binlog里

  2. 从库 创建出一个IO线程去请求更新的binlog

  3. 主库创建一个binlog dump线程发送 从库去接受

  4. 从库把接受的数据写到relay log

  5. 从库的Sql线程把relaylog执行一遍

Redo log

redo log 是物理日志,记录了某个数据页做了什么修改,比如对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新,每当执行一个事务就会产生这样的一条或者多条物理日志。

redo log 和 undo log 区别在哪?

  • redo log 记录了此次事务「完成后」的数据状态,记录的是更新之后的值;

  • undo log 记录了此次事务「开始前」的数据状态,记录的是更新之前的值;

目的:Redo log的目的是为了保证事务的持久性,主要用于崩溃恢复,而Undo log的目的是为了保证事务的原子性和一致性,主要用于事务回滚。
●记录内容:Redo Log 记录了事务的所有数据更改(这些日志不仅仅记录了数据更改的最终结果,而且还记录了实现这些更改的具体操作)。而Undo log记录的是事务执行前的内容

redo log 和 binlog 有什么区别?

1、适用对象不同:

  • binlog 是 MySQL 的 Server 层实现的日志,所有存储引擎都可以使用;

  • redo log 是 Innodb 存储引擎实现的日志

3、写入方式不同:

  • binlog 是追加写,写满一个文件,就创建一个新的文件继续写,不会覆盖以前的日志,保存的是全量的日志。

  • redo log 是循环写,日志空间大小是固定,全部写满就从头开始,保存未被刷入磁盘的脏页日志

4、用途不同:

  • binlog 用于备份恢复、主从复制;

  • redo log 用于掉电等故障恢复。

redolog 怎么保证持久性的?

Redo log是MySQL中用于保证持久性的重要机制之一。它通过以下方式来保证持久性:

  1. Write-ahead logging(WAL):在事务提交之前,将事务所做的修改操作记录到redo log中,然后再将数据写入磁盘。这样即使在数据写入磁盘之前发生了宕机,系统可以通过redo log中的记录来恢复数据。

  2. Redo log的顺序写入:redo log采用追加写入的方式,将redo日志记录追加到文件末尾,而不是随机写入。这样可以减少磁盘的随机I/O操作,提高写入性能。

  3. Checkpoint机制:MySQL会定期将内存中的数据刷新到磁盘,同时将最新的LSN(Log Sequence Number)记录到磁盘中,这个LSN可以确保redo log中的操作是按顺序执行的。在恢复数据时,系统会根据LSN来确定从哪个位置开始应用redo log。

如果不小心整个数据库的数据被删除了,能使用 redo log 文件恢复数据吗?

不可以使用 redo log 文件恢复,只能使用 binlog 文件恢复。

因为 redo log 文件是循环写,是会边写边擦除日志的,只记录未被刷入磁盘的数据的物理日志,已经刷入磁盘的数据都会从 redo log 文件里擦除。

binlog 文件保存的是全量的日志,也就是保存了所有数据变更的情况,理论上只要记录在 binlog 上的数据,都可以恢复,所以如果不小心整个数据库的数据被删除了,得用 binlog 文件恢复数据。

总结

  • undo log(回滚日志):是 Innodb 存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和 MVCC

  • redo log(重做日志):是 Innodb 存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复

  • binlog (归档日志):是 Server 层生成的日志,主要用于数据备份和主从复制

索引部分:

什么是索引

面试官:了解过索引吗?(什么是索引)

候选人:嗯,索引在项目中还是比较常见的,它是帮助MySQL高效获取数据的数据结构,主要是用来提高数据检索的效率,降低数据库的IO成本,同时通过索引列对数据进行排序,降低数据排序的成本,也能降低了CPU的消耗

常见的索引结构有: B 树, B+树 和 Hash、红黑树。

索引的底层数据结构了解过吗?

Mysql的默认存储引擎InnoDB采用的是B+树 因为他路径短,然后呢 是一个双向链表 便于查询

什么是聚簇索引什么是非聚簇索引 ?

好的~,聚簇索引主要是指数据与索引放到一块,B+树的叶子节点保存了整行数据,有且只有一个,一般情况下主键在作为聚簇索引的

非聚簇索引值的是数据与索引分开存储,B+树的叶子节点保存对应的主键,可以有多个,一般我们自己定义的索引都是非聚簇索引

索引类型

  • 我们可以按照四个角度来分类索引。

  1. 按「数据结构」分类:B+tree索引、Hash索引、Full-text索引。

  2. 按「物理存储」分类:聚簇索引(主键索引)、二级索引(辅助索引)。

  3. 按「字段特性」分类:主键索引、唯一索引、普通索引、前缀索引。

  4. 按「字段个数」分类:单列索引、联合索引。



正确使用索引的建议

  • 不为 NULL 的字段:索引字段的数据应该尽量不为 NULL,因为对于数据为 NULL 的字段,数据库较难优化。如果字段频繁被查询,但又避免不了为 NULL,建议使用 0,1,true,false 这样语义较为清晰的短值或短字符作为替代。

  • 被频繁查询的字段:我们创建索引的字段应该是查询操作非常频繁的字段。

  • 被作为条件查询的字段:被作为 WHERE 条件查询的字段,应该被考虑建立索引。

  • 频繁需要排序的字段:索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。

  • 被经常频繁用于连接的字段:经常用于连接的字段可能是一些外键列,对于外键列并不一定要建立外键,只是说该列涉及到表与表的关系。对于频繁被连接查询的字段,可以考虑建立索引,提高多表连接查询的效率。

  • 考虑区分度:尽量不要选择区分度不高的字段作为索引,比如性别。但是也并不绝对,对于一些数据倾斜比较严重的字段,虽然区分度不高,但是如果有索引,查询占比少的数据时效率也会提升。

被频繁更新的字段应该慎重建立索引

虽然索引能带来查询上的效率,但是维护索引的成本也是不小的。 如果一个字段不被经常查询,反而被经常修改,那么就更不应该在这种字段上建立索引了

限制每张表上的索引数量

索引并不是越多越好,建议单张表索引不超过 5 个!索引可以提高效率同样可以降低效率。

索引可以增加查询效率,但同样也会降低插入和更新的效率,甚至有些情况下会降低查询效率。

因为 MySQL 优化器在选择如何优化查询时,会根据统一信息,对每一个可以用到的索引来进行评估,以生成出一个最好的执行计划,如果同时有很多个索引都可以用于查询,就会增加 MySQL 优化器生成执行计划的时间,同样会降低查询性能。

尽可能的考虑建立联合索引而不是单列索引

因为索引是需要占用磁盘空间的,可以简单理解为每个索引都对应着一颗 B+树。如果一个表的字段过多,索引过多,那么当这个表的数据达到一个体量后,索引占用的空间也是很多的,且修改索引时,耗费的时间也是较多的。如果是联合索引,多个字段在一个索引上,那么将会节约很大磁盘空间,且修改数据的操作效率也会提升。

注意避免冗余索引

冗余索引指的是索引的功能相同,能够命中索引(a, b)就肯定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city )和(name )这两个索引就是冗余索引,能够命中前者的查询肯定是能够命中后者的 在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。

字符串类型的字段使用前缀索引代替普通索引

前缀索引仅限于字符串类型,较普通索引会占用更小的空间,所以可以考虑使用前缀索引带替普通索引。

知道什么是回表查询嘛 ?

候选人:嗯,其实跟刚才介绍的聚簇索引和非聚簇索引是有关系的,回表的意思就是通过二级索引找到对应的主键值,然后再通过主键值找到聚集索引中所对应的整行数据,这个过程就是回表

知道什么是覆盖索引吗

比如在select中 我们根据索引查询出来的列和我们需要的列都能查出来 比如我们根据id查询 他就会走一个聚集索引 这个他会返回一整行数据 效率更快 不需要回表查询

如果按照二级索引查询数据的时候,返回的列中没有创建索引,有可能会触发回表查询,

索引创建原则

  1. 量大 且频繁查询的表 需要进行创建索引

  2. where group by order by这个操作的字段需要创建索引

  3. 区分度要高

  4. 字符串长的字段 可以用前缀索引

  5. 尽量使用联合索引 减少单列索引 避免回表

  6. 控制索引的数量

  7. 常用的字段放在前面 有一个最左匹配原则

索引失效场景

  1. 违反最左匹配原则;

  2. 模糊查询 : "%"号在前面也会导致索引失效

  3. 在字段上进行运算或者类型转换也会造成索引失效

  4. 查询条件中使用 OR,且 OR 的前后条件中有一个列没有索引,涉及的索引都不会被使用到;

  5. IN 的取值范围较大时会导致索引失效,走全表扫描(NOT IN 和 IN 的失效场景相同);

知道如何分析语句是否走索引查询

EXPLAIN

Extra(重要)

这列包含了 MySQL 解析查询的额外信息,通过这些信息,可以更准确的理解 MySQL 到底是如何执行查询的。常见的值如下:

  • Using filesort:在排序时使用了外部的索引排序,没有用到表内索引进行排序。

  • Using temporary:MySQL 需要创建临时表来存储查询的结果,常见于 ORDER BY 和 GROUP BY。

  • Using index:表明查询使用了覆盖索引,不用回表,查询效率非常高。

  • Using index condition:表示查询优化器选择使用了索引条件下推这个特性。

  • Using where:表明查询使用了 WHERE 子句进行条件过滤。一般在没有使用到索引的时候会出现。

  • Using join buffer (Block Nested Loop):连表查询的方式,表示当被驱动表的没有使用索引的时候,MySQL 会先将驱动表读出来放到 join buffer 中,再遍历被驱动表与驱动表进行查询。

优化索引方式

  • 前缀索引优化;

  • 覆盖索引优化;

  • 主键索引最好是自增的;

  • 防止索引失效;

事务部分

事务的特性

ACID

  • A(原子性): 事务是一组操作的集合,它是不可分割的 要么全部成功 要么全部失败

  • C(一致性): 事务完成之后 所有的数据要保持一致状态

  • I(隔离性): 在进行事务的时候 不会被其他并发操作影响

  • D(持久性): 一旦提交或者回滚,会数据库的改变是永久的

举个例子

A -> B 转500元钱

A扣除500 B加500 这件事要么都成功 要么都失败

在事务进行的时候 A必须-500 B+500

隔离性就是A->B 不会收其他事务的影响

持久性就是 完事之后 对数据库的改变是永久的

  • 持久性是通过 redo log (重做日志)来保证的;

  • 原子性是通过 undo log(回滚日志) 来保证的;

  • 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;

  • 一致性则是通过持久性+原子性+隔离性来保证;

并发事务问题

脏读

一个事务读到另一个事务还没有提交的数据

不可重复读

一个事务先后读取同一条记录,但是两次读取的数据不一样

幻读

一个事务按照条件去查询 发现没有对应数据行,但是在插入的时候 又发现该数据好像已经存在了!

事务隔离级别

但是 InnoDBlide RR可以解决幻读

Mysql的隔离级别是基于锁实现的吗

串行化是基于锁实现的

RR 和RC是基于MVCC实现的

但是RR在当前读的情况下用了间隙锁和行级锁

MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象(并不是完全解决了,详见这篇文章(opens new window),解决的方案有两种:

  • 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。

  • 针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

并发事务的控制方式

  • 对于「读未提交」隔离级别的事务来说,因为可以读到未提交事务修改的数据,所以直接读取最新的数据就好了;

  • 对于「串行化」隔离级别的事务来说,通过加读写锁的方式来避免并行访问;

  • 对于「读提交」和「可重复读」隔离级别的事务来说,它们是通过 Read View 来实现的,它们的区别在于创建 Read View 的时机不同,大家可以把 Read View 理解成一个数据快照,就像相机拍照那样,定格某一时刻的风景。「读提交」隔离级别是在「每个语句执行前」都会重新生成一个 Read View,而「可重复读」隔离级别是「启动事务时」生成一个 Read View,然后整个事务期间都在用这个 Read View

Innodb 引擎为了解决「可重复读」隔离级别使用「当前读」而造成的幻读问题,就引出了间隙锁

MVCC 是多版本并发控制方法,即对一份数据会存储多个版本,通过事务的可见性来保证事务能看到自己应该看到的版本。通常会有一个全局的版本分配器来为每一行数据设置版本号,版本号是唯一的。

MVCC 在 MySQL 中实现所依赖的手段主要是: 隐藏字段、read view、undo log

  • undo log : undo log 用于记录某行数据的多个版本的数据。

  • read view 和 隐藏字段 : 用来判断当前版本数据的可见性。

「读提交」和「可重复读」区别

  • 「读提交」隔离级别是在每个 select 都会生成一个新的 Read View,也意味着,事务期间的多次读取同一条数据,前后两次读的数据可能会出现不一致,因为可能这期间另外一个事务修改了该记录,并提交了事务。

  • 「可重复读」隔离级别是启动事务时生成一个 Read View,然后整个事务期间都在用这个 Read View,这样就保证了在事务期间读到的数据都是事务启动前的记录。

Innodb的RR到底有没有解决幻读?

nnoDB中的REPEATABLE READ这种隔离级别通过间隙锁+MVCC解决了大部分的幻读问题,但是并不是所有的幻读都能解读,想要彻底解决幻读,需要使用Serializable的隔离级别。

RR中,通过间隙锁解决了部分当前读的幻读问题,通过增加间隙锁将记录之间的间隙锁住,避免新的数据插入。

RR中,通过MVCC机制的,解决了快照读的幻读问题,RR中的快照读只有第一次会进行数据查询,后面都是直接读取快照,所以不会发生幻读。

但是,如果两个事务,事务1先进行快照读,然后事务2插入了一条记录并提交,再在事务1中进行update新插入的这条记录是可以更新出成功的,这就是发生了幻读。

还有一种场景,如果两个事务,事务1先进行快照读,然后事务2插入了一条记录并提交,在事务1中进行了当前读之后,再进行快照读也会发生幻读。

undo log和redo log的区别

redo log日志记录的是数据页的物理变化,服务宕机可用来同步数据,而undo log 不同,它主要记录的是逻辑日志,当事务回滚时,通过逆操作恢复原来的数据,比如我们删除一条数据的时候,就会在undo log日志文件中新增一条delete语句,如果发生回滚就执行逆操作;

redo log保证了事务的持久性,undo log保证了事务的原子性和一致性

事务中的隔离性是如何保证的呢?(你解释一下MVCC)

1、读操作(SELECT):

当一个事务执行读操作时,它会使用快照读取。快照读取是基于事务开始时数据库中的状态创建的,因此事务不会读取其他事务尚未提交的修改。具体工作情况如下:

  • 对于读取操作,事务会查找符合条件的数据行,并选择符合其事务开始时间的数据版本进行读取。

  • 如果某个数据行有多个版本,事务会选择不晚于其开始时间的最新版本,确保事务只读取在它开始之前已经存在的数据。

  • 事务读取的是快照数据,因此其他并发事务对数据行的修改不会影响当前事务的读取操作。

2、写操作(INSERT、UPDATE、DELETE):

当一个事务执行写操作时,它会生成一个新的数据版本,并将修改后的数据写入数据库。具体工作情况如下:

  • 对于写操作,事务会为要修改的数据行创建一个新的版本,并将修改后的数据写入新版本。

  • 新版本的数据会带有当前事务的版本号,以便其他事务能够正确读取相应版本的数据。

  • 原始版本的数据仍然存在,供其他事务使用快照读取,这保证了其他事务不受当前事务的写操作影响。

MVCC 通过创建数据的多个版本和使用快照读取来实现并发控制。读操作使用旧版本数据的快照,写操作创建新版本,并确保原始版本仍然可用。这样,不同的事务可以在一定程度上并发执行,而不会相互干扰,从而提高了数据库的并发性能和数据一致性。

隐藏字段

undo log

  • 另一个作用是 MVCC ,当读取记录时,若该记录被其他事务占用或当前版本对该事务不可见,则可以通过 undo log 读取之前的版本数据,以此实现非锁定读

Mysql锁

表级锁和行级锁了解吗 有什么区别?

表级锁是并发对低的锁 冲突概率大 然后不容易发生死锁 然后是针对于非索引字段的 然后行级锁是针对于索引字段的 并发度最高 然后容易死锁

行级锁的使用有什么注意事项?

当我们使用 update delete 如何where条件没有命中唯一索引 或者索引失效 他就会对这个表的所有行进行加锁

InnoDB 有哪几类行锁?

InnoDB 行锁是通过对索引数据页上的记录加锁实现的,MySQL InnoDB 支持三种行锁定方式:

  • 记录锁(Record Lock):也被称为记录锁,属于单个行记录上的锁。

  • 间隙锁(Gap Lock):锁定一个范围,不包括记录本身。

  • 临键锁(Next-Key Lock):Record Lock+Gap Lock,锁定一个范围,包含记录本身,主要目的是为了解决幻读问题(MySQL 事务部分提到过)。记录锁只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁。

在 InnoDB 默认的隔离级别 REPEATABLE-READ 下,行锁默认使用的是 Next-Key Lock。但是,如果操作的索引是唯一索引或主键,InnoDB 会对 Next-Key Lock 进行优化,将其降级为 Record Lock,即仅锁住索引本身,而不是范围。

当前读和快照读有什么区别?

当前度就是读取我们的一个快照就是历史记录

在RC 和RR 模式下就采取快照度

RC是读取事务开始后最新的那一条快照

RR是读取事务开始时的快照

当前读就是给记录加X 和S锁

为什么默认RR,大厂要改成RC?

提高并发:首先,RC 在加锁的过程中,是不需要添加Gap Lock和 Next-Key Lock 的,只对要修改的记录添加行级锁就行了。

这就使得并发度要比 RR 高很多。

另外,因为 RC 还支持"半一致读",可以大大的减少了更新语句时行锁的冲突;对于不满足更新条件的记录,可以提前释放锁,提升并发度。

减少死锁:比如读取到别的事务修改的值其实问题不太大的,只要修改的时候的不基于错误数据就可以了,所以我们都是在核心表中增加乐观锁标记,更新的时候都要带上锁标记进行乐观锁更新。

还有就是使用 RC 的时候,不能使用statement格式的 binlog,这种影响其实可以忽略不计了,因为MySQL是在5.1.5版本开始支持row的、在5.1.8版本中开始支持mixed,后面这两种可以代替 statement格式。

如何避免死锁

解决(避免)死锁的方法有:
1、减少锁的数量:比如使用RC来代替RR来避免因为gap锁和next-key锁而带来的死锁情况。
2、减少锁的时长:加快事务的执行速度,降低执行时间,也能减少死锁发生的概率。
3、固定顺序访问数据:事务在访问同一张表时,应该以相同的顺序获取锁,这样可以避免死锁的发生。
4、减少操作的数据量:尽量减少事务操作的数据量,尽量减少事务的持有时间,这样可以降低死锁的发生几率。

性能规范

命名规范

  • 所有数据库对象名称必须使用小写字母并用下划线分割

  • 所有存储相同数据的列名和列类型必须一致(一般作为关联列,如果查询时关联列类型不一致会自动进行数据类型隐式转换,会造成列上的索引失效,导致查询效率降低)

超大分页怎么处理

如果我们用limit 他会一行一行从上往下去查 这样效率会非常的慢 所以我们直接用覆盖索引+子查询

SQL优化的经验

  • 表的设计的时候需要考虑更好的字段啊

  • 避免使用select * 有可能回表查询

  • 避免索引失效

  • 尽量使用innerjoin 把小表作为驱动

  • 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

  • .select count(*) from table;这样不带任何条件的count会引起全表扫描,并且没有任何业务意义,是一定要杜绝的。

  • .尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连 接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

  • 尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

  • 尽量避免大事务操作,提高系统并发能力。

综合问题

MySQL自增主键用完了会怎么样?


显示自定义的自增ID,用完以后下次插入会报主键冲突。
未定义自增ID主键,会用row_id,用完以后下一次插入会覆盖历史数据。

归档旧数据(推荐


分布式ID(推荐)

数据库–幂等–方案

全局唯一ID的方案

  1. UUID

  2. Redis INCR命令

  3. 雪花算法

读写分离

读写分离主要是为了将对数据库的读写操作分散到不同的数据库节点上

主从同步流程

  • 主库将数据库中数据的变化写入到 binlog

  • 从库连接主库

  • 从库会创建一个 I/O 线程向主库请求更新的 binlog

  • 主库会创建一个 binlog dump 线程来发送 binlog ,从库中的 I/O 线程负责接收

  • 从库的 I/O 线程将接收的 binlog 写入到 relay log 中。

  • 从库的 SQL 线程读取 relay log 同步数据本地(也就是再执行一遍 SQL )。

如何避免主从延迟

强制将读请求路由到主库处理

二次读取


除了上面我们说的强制读主库的方案,还有一个常见做法叫做二次读取。

啥意思呢,就是我的读取操作,默认读从库,但是如果我从库读取的时候没读到,那我为了避免因为数据延迟导致的,那么就再进行一次从主库读取。

这个实现方式的话也是需要我们定制的开发代码。但是这个方案我不太建议,因为这种一旦出现延迟,也会导致你的主库会有大量的请求过去,造成很大的压力的

什么情况下出现主从延迟?如何尽量减少主从延迟?

第一点就是我们的从库IO线程接受的速度比不上主线程的binlog速度

第二点就是我们从库的relay log的执行速度 比不上从库接受的binlog速度

  1. 从库机器性能比主库差

  2. 从库处理的读请求过多

  3. 大事务

  4. 从库太多

  5. 网络延迟

分库分表

什么情况下需要分库分表

应用并发量太大 数据超过1000w

常见的分片算法有哪些?

  • 哈希分片:求指定 key(比如 id) 的哈希,然后根据哈希值确定数据应被放置在哪个表中。哈希分片比较适合随机读写的场景,不太适合经常需要范围查询的场景。

  • 范围分片:按照特性的范围区间(比如时间区间、ID 区间)来分配数据,比如 将 id 为 1~299999 的记录分到第一个库, 300000~599999 的分到第二个库。范围分片适合需要经常进行范围查找的场景,不太适合随机读写的场景(数据未被分散,容易出现热点数据的问题)。

  • 地理位置分片:很多 NewSQL 数据库都支持地理位置分片算法,也就是根据地理位置(如城市、地域)来分配数据。

  • 融合算法:灵活组合多种分片算法,比如将哈希分片和范围分片组合。

总结部分

0

评论区