索引

1. innodb B+树主键索引的叶子节点存的是什么?

  • 页(B+树的叶子节点是page (页),一个页里面可以存多个行)

    2. 索引哪些情况会失效

  • 查询条件包含or,可能导致索引失效

  • 如何字段类型是字符串,where时一定用引号括起来,否则索引失效
  • like通配符可能导致索引失效(前缀模糊匹配)。
  • 联合索引,查询时的条件列不是联合索引中的第一个列,索引失效。
  • 在索引列上使用mysql的内置函数,索引失效。
  • 对索引列运算(如,+、-、*、/),索引失效。
  • 索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效。
  • 索引字段上使用is null, is not null,可能导致索引失效。
  • mysql估计使用全表扫描要比使用索引快,则不使用索引。

    3. 为什么索引使用b+数

  • 因为B树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出),指针少的情况下要保存大量数据,只能增加树的高度,导致IO操作变多,查询性能变低;

  • B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。
  • B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。innodb中页的默认大小是16KB,如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。
  • B+ 树索引并不能找到一个给定键对应的具体值,它只能找到数据行对应的页,数据库把整个页读入到内存中,并在内存中查找具体的数据行。
  • 叶子之间,增加了链表,获取所有节点,所以只遍历叶子节点就可以遍历整颗树,不再需要中序遍历;B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。
  • 如果是hash的话哈希函数的目的就是让数据尽可能被分散到不同的桶中进行存储,所以在遇到可能存在相同键 或者排序以及范围查询时,由哈希作为底层数据结构的表可能就会面对数据库全表扫描。
  • b树只适合随机检索,b+树同时支持随机检索和顺序检索

    4. 为什么不是一般二叉树?

  • 如果二叉树特殊化为一个链表,相当于全表扫描。平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快。

    5. 为什么不是平衡二叉树呢?

  • 在内存比在磁盘的数据,查询效率快得多。如果树这种数据结构作为索引,那我们每查找一次数据就需要从磁盘中读取一个节点,也就是我们说的一个磁盘块,但是平衡二叉树可是每个节点只存储一个键值和数据的,如果是B树,可以存储更多的节点数据,树的高度也会降低,因此读取磁盘的次数就降下来啦,查询效率就快。

    6. 索引有哪些优缺点?

  • 优点:
    • 唯一索引可以保证数据库表中每一行的数据的唯一性
    • 索引可以加快数据查询速度,减少查询时间
  • 缺点:

    • 创建索引和维护索引要耗费时间
    • 索引需要占物理空间,除了数据表占用数据空间之外,每一个索引还要占用一定的物理空间
    • 以表中的数据进行增、删、改的时候,索引也要动态的维护。

      7. 索引有哪几种类型?

    • 主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键。

    • 唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。
    • 普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值。
    • 全文索引:是目前搜索引擎使用的一种关键技术,对文本的内容进行分词、搜索。
    • 覆盖索引:查询列要被所建的索引覆盖,不必读取数据行
    • 组合索引:多列值组成一个索引,用于组合搜索,效率大于索引合并

      8. 创建索引有什么原则呢?

    • 最左前缀匹配原则

    • 频繁作为查询条件的字段才去创建索引
    • 频繁更新的字段不适合创建索引
    • 索引列不能参与计算,不能有函数操作
    • 优先考虑扩展索引,而不是新建索引,避免不必要的索引
    • 在order by或者group by子句中,创建索引需要注意顺序
    • 区分度低的数据列不适合做索引列(如性别)
    • 定义有外键的数据列一定要建立索引。
    • 对于定义为text、image数据类型的列不要建立索引。
    • 删除不再使用或者很少使用的索引

      9. MySQL中InnoDB引擎的行锁是怎么实现的?

  • 基于索引来完成行锁的。

  • select from t where id = 666 *for update;
  • for update 可以根据条件来完成行锁锁定,并且 id 是有索引键的列,如果 id 不是索引键那么InnoDB将实行表锁。

    10. 执行 select * from T where k between 3 and 5,需要执行几次树的搜索操作,会扫描多少行?(k为非主键索引)

    image.png

  • 在 k 索引树上找到 k=3 的记录,取得 ID = 300;

  • 再到 ID 索引树查到 ID=300 对应的 R3;
  • 在 k 索引树取下一个值 k=5,取得 ID=500;
  • 再回到 ID 索引树查到 ID=500 对应的 R4;
  • 在 k 索引树取下一个值 k=6,不满足条件,循环结束。

在这个过程中,回到主键索引树搜索的过程,我们称为回表。

11 B+树的叶子节点是双向链表

12 索引使用or查询是:


索引失效指的是:假如or连接的
俩个查询条件字段中有一个没有索引的话,引擎会放弃索引而产生全表扫描。我们从or的基本含义出发应该能理解并认可这种说法,没啥问题。
此刻需要注意
type**类型为index_merge

index_merge作用:
1、索引合并是把几个索引的范围扫描合并成一个索引。
2、索引合并的时候,会对索引进行并集,交集或者先交集再并集操作,以便合并成一个索引。
3、这些需要合并的索引只能是一个表的。不能对多表进行索引合并。

引擎

1. InnoDB与MyISAM的区别

  • InnoDB支持事务,MyISAM不支持事务
  • InnoDB支持外键,MyISAM不支持外键
  • InnoDB 支持 MVCC(多版本并发控制),MyISAM 不支持
  • select count(*) from table时,MyISAM更快,因为它有一个变量保存了整个表的总行数,可以直接读取,InnoDB就需要全表扫描。
  • Innodb不支持全文索引,而MyISAM支持全文索引(5.7以后的InnoDB也支持全文索引)
  • InnoDB支持表、行级锁,而MyISAM支持表级锁。
  • InnoDB表必须有主键,而MyISAM可以没有主键
  • Innodb表需要更多的内存和存储,而MyISAM可被压缩,存储空间较小,。
  • Innodb按主键大小有序插入,MyISAM记录插入顺序是,按记录插入顺序保存。
  • InnoDB 存储引擎提供了具有提交、回滚、崩溃恢复能力的事务安全,与 MyISAM 比 InnoDB 写的效率差一些,并且会占用更多的磁盘空间以保留数据和索引

1. update t set t.name=’abc’ where t.name=’cde’; name 如何锁的,如果加limit 1 会怎么锁

  • 如果update的列没建索引,即使只update一条记录也会锁定整张表
  • 如果列上没有索引,更新就是走主键索引树,逐行扫描满足条件的行,等于将主键索引所有的行上了锁,假如加上limit 1,扫描主键索引树,直到找到第一条满足条件的行,扫描过的行都会被加上行锁。
  • 版本5.7.13 ,加没加limit,update其他行数据都会失败,但是,加了limit,自增insert成功,但是,在行锁数据的前面加一条数据会被阻塞。没加limit,insert会阻塞,等待其他事务提交
  • 如果update的列没建索引,即使只update一条记录也会锁定整张表
  • update 没有走索引,innodb内部是全表根据主键索引逐行扫描 逐行加锁,事务提交的时候统一释放

limit

1. limit 1000000 加载很慢的话,你是怎么解决的呢?

  • 如果id是连续的,可以这样,返回上次查询的最大记录(偏移量),再往下limit
    • select id,name from employee where id>1000000 limit 10.
  • 在业务允许的情况下限制页数:
    • 建议跟业务讨论,有没有必要查这么后的分页啦。因为绝大多数用户都不会往后翻太多页。
  • order by + 索引(id为索引)
    • select id,name from employee order by id limit 1000000,10
  • 利用延迟关联或者子查询优化超多分页场景。(先快速定位需要获取的id段,然后再关联)
    • SELECT a.* FROM employee a, (select id from employee where 条件 LIMIT 1000000,10 ) b where a.id=b.id

其他

1. 数据库的三大范式

  • 第一范式:数据表中的每一列(每个字段)都不可以再拆分。
  • 第二范式:在第一范式的基础上,分主键列完全依赖于主键,而不能是依赖于主键的一部分。
  • 第三范式:在满足第二范式的基础上,表中的非主键只依赖于主键,而不依赖于其他非主键。

2. SQL 约束有哪几种呢?

  • NOT NULL: 约束字段的内容一定不能为NULL。
  • UNIQUE: 约束字段唯一性,一个表允许有多个 Unique 约束。
  • PRIMARY KEY: 约束字段唯一,不可重复,一个表只允许存在一个。
  • FOREIGN KEY: 用于预防破坏表之间连接的动作,也能防止非法数据插入外键。
  • CHECK: 用于控制字段的值范围。

3. MySQL数据库cpu飙升的话,要怎么处理呢?

  • 排查过程:
    • 使用top 命令观察,确定是mysqld导致还是其他原因。
    • 如果是mysqld导致的,show processlist,查看session情况,确定是不是有消耗资源的sql在运行。
    • 找出消耗高的 sql,看看执行计划是否准确, 索引是否缺失,数据量是否太大。
  • 处理:
    • kill 掉这些线程(同时观察 cpu 使用率是否下降),
    • 进行相应的调整(比如说加索引、改 sql、改内存参数)
    • 重新跑这些 SQL。
  • 其他情况:

    • 也有可能是每个 sql 消耗资源并不多,但是突然之间,有大量的 session 连进来导致 cpu 飙升,这种情况就需要跟应用一起来分析为何连接数会激增,再做出相应的调整,比如说限制连接数等

      4. Innodb的事务与日志的实现方式

  • 日志的存放形式

    • redo:在页修改的时候,先写到 redo log buffer 里面, 然后写到 redo log 的文件系统缓存里面(fwrite),然后再同步到磁盘文件( fsync)。
    • Undo:在 MySQL5.5 之前, undo 只能存放在 ibdata文件里面, 5.6 之后,可以通过设置 innodb_undo_tablespaces 参数把 undo log 存放在 ibdata之外。
  • 事务是如何通过日志来实现的
    • 因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。
    • 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的 状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。
    • 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。

5. 优化limit分页

  • 返回上次查询的最大记录(偏移量)
    • select id,name from employee where id>10000 limit 10.
  • order by + 索引
    • select id,name from employee order by id limit 10000,10

6. 使用联合索引时,注意索引列的顺序,一般遵循最左匹配原则。

  • 当我们创建一个联合索引的时候,如(k1,k2,k3),相当于创建了(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则。
  • 联合索引不满足最左原则,索引一般会失效,但是这个还跟Mysql优化器有关的。

7. 使用长连接后。可能导致于内存太大,被系统强行kill掉,如何解决

  • 定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。
  • 如果用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。

    8. 数据库的主键应该如何选择

  • 最好需要具有单调性、比如利用id排序

  • 提升数据的写入性能。MySQL InnoDB 存储引擎使用 B+ 树存储索引数据,而主键也是一种索引。索引数据在 B+ 树中是有序排列的。不然会频繁移动数据页里面的数据的位置

事务

1. 事务的特性

  • 原子性、一致性、隔离性、持久性

6. 事务启动方式

  • 显式启动事务语句,begin或者start transaction,提交commit,回滚rollback;
  • set autocommit=0,该命令会把这个线程的自动提交关掉。这样只要执行一个select语句,事务就启动,并不会自动提交,直到主动执行commit或rollback或断开连接。

    3. 事务的两阶段提交

  • 指的就是在事务提交的时候,分成 prepare 和 commit 两个阶段。redo log 先 prepare 完成,再写 binlog,最后才进入 redo log commit 阶段。

    4 MVCC

    • MVCC的实现,是通过保存数据在某个时间点的快照来实现的。因此不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。

      5 MVCC是如何工作的

    • InnoDB的MVCC是通过在每行记录后保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或者是删除时间)。当然存储的不是实际的时间值,而是系统版本号。每当开始一个新的事务,系统版本号都会自动递增,事务开始时刻的系统版本号作为事务的版本号,用来和查询到的每行记录的版本号进行比较。

    • InnoDB 将行记录快照保存在了 Undo Log 里:
    • SELECT:InnoDB之查找版本号小于等于当前事务版本的数据行,这样可以确保事务读取的行要么是在事务开始前已经存在的,要么就是事务自身插入或者修改过的。行的删除版本要么未定义,要么大于当前事务版本号。这样可以确保事务读取到的行,在事务开始前未被删除。
    • INSERT:InnoDB为新插入的每一行保存当前系统版本号作为行版本号。
    • DELETE:InnoDB为删除的每一行保存当前系统版本号作为行删除标识。
    • UPDATE:InnoDB会插入一条新记录,保存当前系统版本号为行版本号,同时保存当前系统版本号到原来的行作为行删除标识。

6 MySQL如何处理幻读的

  • 手动加 X锁 的方法消除幻读
  • mvcc

7 为什么事务的隔离级别是RR

  • 在MySQL的早期版本(大概是5.1)中,binlog的默认格式是语句格式。这时候如果启用了RC的隔离级别,binlog记录的顺序可能与实际不一致。所以系统做了一个判断,如果隔离级别为RC,则binlog格式必须要是Mi或者row。
  • 性能,问题是有可能出现幻读,mysql联合使用next-key locking解决幻读。


1. 死锁的概念是什么? 举例说明出现死锁的情况.

  • 多个进程可以竞争有限数量的资源。当一个进程申请资源时,如果这时没有可用资源,那么这个进程进入等待状态
  1. 互斥:至少有一个资源必须处于非共享模式,即一次只有一个进程可使用。如果另一进程申请该资源,那么申请进程应等到该资源释放为止。
  2. 占有并等待:—个进程应占有至少一个资源,并等待另一个资源,而该资源为其他进程所占有。
  3. 非抢占:资源不能被抢占,即资源只能被进程在完成任务后自愿释放。
  4. 循环等待:

2. 死锁的处理策略有哪两种?

  • 一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wait_timeout (默认50s)来设置。
  • 另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑。

3. 等待超时处理死锁的机制什么?有什么局限?

  • 设置参数innodb_lock_wait_timeout
  • 超时时间、太长太短都不太合适

4. 死锁检测处理死锁的机制是什么? 有什么局限?

  • 需考虑该锁等待队列中的线程,单个线程判断时间复杂度为O(n)
  • 并发更新同一行的n个线程死锁检测的时间复杂度为O(n^2)
  • 耗费大量的cpu资源,高cpu利用率事务执行效率低

MYSQL的主从延迟,你怎么解决?

参考 https://juejin.im/post/5ec15ab9f265da7bc60e1910#heading-37

MYSQL数据库服务器性能分析的方法命令有哪些?

MySQL的复制原理以及流程

1. 如果表 T 中没有字段 k,而你执行了这个语句 select * from T where k=1, 那肯定是会报“不存在这个列”的错误,是在哪个阶段报错的

  • MySql会在分析阶段判断语句是否正确,表是否存在,列是否存在等

    2. redo log 和binlog不同

  • redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。

  • redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的 c 字段加 1 ”
  • redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

    3. 回滚日志什么时候删除?

  • 系统会判断当没有事务需要用到这些回滚日志的时候,回滚日志会被删除。

    5. 为什么尽量不要使用长事务

  • 长事务意味着系统里面会存在很老的事务视图,在这个事务提交之前,回滚记录都要保留,这会导致大量占用存储空间。除此之外,长事务还占用锁资源,可能会拖垮库。

    7. 基于主键索引和普通索引的查询有什么区别?

  • 如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索 ID 这棵 B+ 树;

  • 如果语句是 select * from T where k=5,即普通索引查询方式,则需要先搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表。
  • 基于非主键索引的查询需要多扫描一棵索引树,我们在应用中应该尽量使用主键查询。

    9. 你要删除一个表里面的前 10000 行数据,有以下三种方式可以做到

  • 直接执行delete from T limit 10000;(单个语句占用时间长,锁的时间也比较长;而且大事务还会导致主从延迟。不建议)

  • 在一个连接中循环执行 20 次 delete from T limit 500;(串行化执行,将相对长的事务分成多次相对短的事务,则每次事务占用锁的时间相对较短,其他客户端在等待相应资源的时间也较短。这样的操作,同时也意味着将资源分片使用(每次执行使用不同片段的资源),可以提高并发性。)
  • 在 20 个连接中同时执行 delete from T limit 500;(会人为造成锁冲突。)

    10. 一次一条执行和一次执行多条SQL的区别是什么

  • 合并MySQL的日志,比如binlog和事务日志,降低日志刷盘的数据量和频率,从而提高效率。通过合并SQL语句,同时也能减少SQL语句的解析次数,减少网络的IO,不只是sql,还有Redis操作,能用mget,hmget,pipeline更好,不过也要注意把控

    12. 怎么解决由这种热点行更新导致的性能问题呢

  • 就是如果你能确保这个业务一定不会出现死锁,可以临时把死锁检测关掉。但是这种操作本身带有一定的风险,因为业务设计的时候一般不会把死锁当做一个严重错误,毕竟出现死锁了,就回滚,然后通过业务重试一般就没问题了,这是业务无损的。而关掉死锁检测意味着可能会出现大量的超时,这是业务有损的。

  • 另一个思路是控制并发度。发现如果并发能够控制住,比如同一行同时最多只有 10 个线程在更新,那么死锁检测的成本很低,就不会出现这个问题。一个直接的想法就是,在客户端做并发控制。但是,你会很快发现这个方法不太可行,因为客户端很多。(并发控制要做在数据库服务端)
  • 考虑通过将一行改成逻辑上的多行来减少锁冲突(比如很多行都是对id = 1 的数据进行相加,在程序上相加然后update)

    13. InnoDB读取数据方式

  • InnoDB 的数据是按数据页为单位来读写的。也就是说,当需要读一条记录的时候,并不是将这个记录本身从磁盘读出来,而是以页为单位,将其整体读入内存。在 InnoDB 中,每个数据页的大小默认是 16KB。每个 16KB 大小的页中可以存放 2-200 行的记录。

    14. 回表的过程(回到主键索引树搜索的过程,我们称为回表)

  • 如SQL是 select * from T where k between 3 and 5

  • 在 k 索引树上找到 k=3 的记录,取得 ID = 300;
  • 再到 ID 索引树查到 ID=300 对应的 R3;
  • 再回到 ID 索引树查到 ID=500 对应的 R4;
  • 在 k 索引树取下一个值 k=6,不满足条件,循环结束。

    15. 下面两条语句有什么区别,为什么都提倡使用2:

  • select * from T where k in(1,2,3,4,5)

  • select * from T where k between 1 and 5
  • 第一个要树搜素5次,第二个搜索一次

    16. 如果把一个 InnoDB 表的主键删掉,是不是就没有主键,就没办法回表了?

  • 如果你创建的表没有主键,或者把一个表的主键删掉了,那么 InnoDB 会自己生成一个长度为 6 字节的 rowid 来作为主键。

    • a表有100条记录,b表有10000条记录,两张表做关联查询时,是将a表放前面效率高,还是b表放前面效率高?
  • 两个表谁放前面都一样,优化器会调整顺序选择合适的驱动表;如果是考察优化器怎么实现的,每次在树搜索里面做一次查找都是log(n), 所以对比的是100_log(10000)和 10000_log(100)哪个小,显然是前者,所以结论应该是让小表驱动大表。
    • 只查一行的语句,也执行这么慢?
  • 是否被锁表了 show processlist
    • select * from table_a where b=’1234567890abcd’; 有 100 万行数据,其中有 10 万行数据的 b 的值是’1234567890’ MySQL执行流程
  • 在传给引擎执行的时候,做了字符截断。因为引擎里面这个行只定义了长度是 10,所以只截了前 10 个字节,就是’1234567890’进去做匹配;
  • 这样满足条件的数据有 10 万行;
  • 因为是 select *, 所以要做 10 万次回表;
  • 但是每次回表以后查出整行,到 server 层一判断,b 的值都不是’1234567890abcd’;
  • 返回结果是空。
    • 幻读和不可重复读的区别在于?
  • 幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。
    • 如果你的 MySQL 现在出现了性能瓶颈,而且瓶颈在 IO 上,可以通过哪些方法来提升性能呢?
  • 设置 binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 参数,减少 binlog 的写盘次数。这个方法是基于“额外的故意等待”来实现的,因此可能会增加语句的响应时间,但没有丢失数据的风险。
  • 将 sync_binlog 设置为大于 1 的值(比较常见是 100~1000)。这样做的风险是,主机掉电时会丢 binlog 日志。
  • 将 innodb_flush_log_at_trx_commit 设置为 2。这样做的风险是,主机掉电的时候会丢数据。
    • 为什么 binlog cache 是每个线程自己维护的,而 redo log buffer 是全局共用的?
  • MySQL 这么设计的主要原因是,binlog 是不能“被打断的”。一个事务的 binlog 必须连续写,因此要整个事务完成后,再一起写到文件里。
    • 事务执行期间,还没到提交阶段,如果发生 crash 的话,redo log 肯定丢了,这会不会导致主备不一致呢?
  • 不会。因为这时候 binlog 也还在 binlog cache 里,没发给备库。crash 以后 redo log 和 binlog 都没有了,从业务角度看这个事务也没有提交,所以数据是一致的。

    • 主库挂了怎么办?
      *
    • 写的压力大怎么办?
      *

      21. redo日志刷盘时机

  • 由于redo日志一直都是增长的,且内存空间有限,数据也不能一直待在缓存中, 我们需要将其刷新至硬盘上。log buffer空间不足。上面有指定缓冲区的内存大小,MySQL认为日志量已经占了 总容量的一半左右,就需要将这些日志刷新到磁盘上。事务提交时。我们使用redo日志的目的就是将他未刷新到磁盘的记录保存起来,防止 丢失,如果数据提交了,我们是可以不把数据提交到磁盘的,但为了保证持久性,必须 把修改这些页面的redo日志刷新到磁盘。后台线程不同的刷新 后台有一个线程,大概每秒都会将log buffer里面的redo日志刷新到硬盘上。

    • redo日志是循环写,如何不覆盖?
  • checkpoint:
    • b+数特点
  • 只有叶子节点保存数据
  • 搜索时相当于二分查找
    • 分库分表产生的问题,及注意事项?
  • 联合查询的问题:联合查询基本不可能,因为关联的表有可能不在同一数据库中。
  • 不经常修改的字段放在同一张表中,将经常改变的字段放在另一张表中。
  • 对于需要经常关联查询的字段,建议放在同一张表中。
  • 尽量把同一组数据放到同一DB服务器上,也就是说避免数据库中的数据依赖另一数据库中的数据。
  • 避免跨库事务:避免在一个事务中修改db0中的表的时候同时修改db1中的表,一个是操作起来更复杂,效率也会有一定影响。
    • 在数据库中查询语句速度很慢,如何优化?
  • 建索引
  • 减少表之间的关联
  • 优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面
  • 简化查询字段,没用的字段不要,已经对返回结果的控制,尽量返回少量数据
    • 假如一个表里有10万条数据,需要随机读出10条数据,有啥方案?
  • 如果能随机模拟出已经存在的id,就随机出10个id,去库里查找。如果不能,比如uuid,那就把所有的id。缓存起来,随机取10条数据,然后去数据库里查找10条数据,也可以考虑用数据库的随机函数(不到万不得已)
    • SQL查询中in和exists的区别分析
  • select * from A where id in (select id from B);
  • select * from A where exists (select 1 from B where A.id=B.id);
  • in是相当于在遍历比较,exists需要查询数据库,所以说当b表数据量比较大的时候,exists效率优先in。IN()只执行一次,它查出B表中的所有id字段并缓存起来。之后,检查A表的id是否与B表中的id相等,如果相等则将A表的记录加入结果集中,直到遍历完A表的所有记录。
  • 在插入记录前,需要检查这条记录是否已经存在,只有当记录不存在时才执行插入操作,可以通过使用 EXISTS 条件句防止插入重复记录。
  • EXISTS与IN的使用效率的问题,通常情况下采用exists要比in效率高,因为IN不走索引。但要看实际情况具体使用:
  • IN适合于外表大而内表小的情况;
  • EXISTS适合于外表小而内表大的情况。
    • 备份一般都会在备库上执行,你在用–single-transaction 方法做逻辑备份的过程中,如果主库上的一个小表做了一个 DDL,比如给一个表上加了一列。这时候,从备库上会看到什么现象?
      *

22 不需要回表的过程

  • SQL语句中的查询字段在叶子节点都有的情况下,比如使用了覆盖索引,就不需要回表了

—— TODO

commit work and chain的语法是做什么用的?
怎么查询各个表中的长事务?
如何避免长事务的出现?


有哪些思路可以解决热点更新导致的并发问题?

https://segmentfault.com/a/1190000015210634

乐观锁与悲观锁的区别?

binlog 日志是 master 推的还是 salve 来拉的?

服务发现是怎么实现的

熔断是怎么实现的