数据库笔面试知识点整理(MySQL)

存储引擎

MyISAM是MySQL5.5版之前的默认数据库引擎。虽然性能极佳,而且提供了大量的特性,包括全文索引、压缩、空间函数等,但MyISAM不支持事务和行级锁,而且最大的缺陷就是崩溃后无法安全恢复。不过,5.5版本之后,MySQL引入了InnoDB(事务性数据库引擎),MySQL 5.5版本后默认的存储引擎为InnoDB。

MyISAM和InnoDB对比

MyISAMInnoDB
只支持表锁支持行锁和表锁(默认为行锁)
不提供事务支持支持事务、回滚和崩溃修复能力
不支持外键支持外键
不支持MVCC支持MVCC

事务

事务是逻辑上的一组操作要么都执行,要么都不执行。

ACID

事务的特性:

  1. 原子性(Atomicity): 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
  2. 一致性(Consistency): 事务的一致性定义基本可以理解为是事务对数据完整性约束的遵循。无论事务是如何并发的,事务执行前后都要是合法的数据状态,不违背数据的完整性;例如银行的转账不能只加钱不减钱。
  3. 隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的
  4. 持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

并发问题

  • 脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据(脏数据),然后使用了这个数据(这是不正确的)。即一个事务读取到另外一个事务未提交的数据
  • 丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。
  • 不可重复读(Unrepeatable read): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样,即一个事务内部可以看到其他事务所做的修改。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
  • 幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。即一个事务内读取到了别的事务插入的数据,导致前后读取不一致。

不可重复读和幻读区别:

不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。

脏读是不可容忍的,不可重复读和虚读在一定的情况下是可以容忍的。

隔离级别

SQL 标准定义了四个隔离级别:

  • READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
  • READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
  • REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
  • SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读

MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重复读)

虽然 InnoDB 存储引擎的默认支持的隔离级别是可重复读,但是可以通过应用加锁读(例如from table for update 语句)来保证不会产生幻读,而这个加锁度使用到的机制就是 Next-Key Lock 锁算法。从而达到了 SQL 标准的 SERIALIZABLE(可串行化) 隔离级别。

Serializable可以防止丢失修改问题的发生,其他的三个隔离级别都有可能发生丢失修改问题。

索引

索引是一种用于快速查询和检索数据的数据结构。常见的索引结构有: B树, B+树和Hash。

索引的优点:

  • 可以大大加快数据的检索速度(大大减少的检索的数据量)

索引的缺点:

  • 创建索引和维护索引需要耗费许多时间:当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低SQL执行效率。
  • 占用物理存储空间 :索引需要使用物理文件存储,也会耗费一定空间。

Hash索引

Hash索引定位快

  • Hash索引指的就是Hash表,最大的优点就是能够在很短的时间内,根据Hash函数定位到数据所在的位置,这是B+树所不能比的。

Hash冲突问题、不支持范围查询

  • **Hash索引不支持顺序和范围查询(Hash索引不支持顺序和范围查询是它最大的缺点)。**B+树在叶子节点上能够通过双向链表顺序遍历,进行范围查询。

InnoDB是自适应哈希索引的(Hash索引的创建由InnoDB存储引擎引擎自动优化创建,我们干预不了)

B+树索引

为什么不用二叉树?为什么不用红黑树?

  • MySQL根据磁盘I/O次数,也就是搜索的次数,来衡量查询效率
  • 红黑树和二叉树一样,都只有两个分支,因而在相同数据量的情况下,深度比B树、B+树更深,搜索次数也就越多
  • 红黑树一个节点只能存出一个值,B树一个节点可以存储多个值,红黑树的深度会更大

B树与B+树索引的区别:

  • B树的所有节点既存放键(key)也存放数据(data);而B+树只有叶子节点存放 key 和 data,其他内节点只存放key
  • B树的叶子节点都是独立的;B+树的叶子节点有一条引用链指向与它相邻的叶子节点(双向链表),即能够提高范围查找的效率
  • B树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而B+树的检索效率就很稳定了,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显。

B+树中一个节点为一页或页的倍数最为合适

  • 各个数据页可以组成一个双向链表
  • 每个数据页中的记录又可以组成一个单向链表
  • 每个数据页都会为存储在它里边儿的记录生成一个页目录,在通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录
  • 其他列(非主键)作为搜索条件:只能从最小记录开始依次遍历单链表中的每条记录

B+树拥有良好的顺序查询效率,相比较其他的索引结构,这极大地提高了效率,按顺序访问范围数据是很快的,这有两个原因:

  1. 顺序I/O不需要多次磁盘寻道,所以比随机I/O要快很多(特别是对机械硬盘)
  2. 如果服务器能够按需要顺序读取数据,那么就不再需要额外的排序操作,并且GROUPBY查询也无须再做排序和将行按组进行聚合计算了。

索引类型

主键索引(Primary Key):

数据表的主键列使用的就是主键索引。一张数据表有只能有一个主键,并且主键不能为null,不能重复。在MySQL的InnoDB的表中,当没有显示的指定表的主键时,InnoDB会自动先检查表中是否有唯一索引的字段,如果有,则选择该字段为默认的主键,否则InnoDB将会自动创建一个6Byte的自增主键。

二级索引(辅助索引):

二级索引又称为辅助索引,是因为二级索引的叶子节点存储的数据是主键。也就是说,通过二级索引,可以定位主键的位置(回表)。

  1. 唯一索引(Unique Key) :唯一索引也是一种约束。**唯一索引的属性列不能出现重复的数据,但是允许数据为NULL,一张表允许创建多个唯一索引。**建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
  2. 普通索引(Index)普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和NULL。
  3. 前缀索引(Prefix) :前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小, 因为只取前几个字符。
  4. 全文索引(Full Text) :全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。Mysql5.6之前只有MYISAM引擎支持全文索引,5.6之后InnoDB也支持了全文索引。

聚簇索引

一个MySQL 无论如何都会建立起来,并且存储有完整行数据的索引,就叫聚簇索引;一般来说就是主键索引(由主键或是唯一键构成)。

聚簇索引的叶子节点上存储着表中的所有数据;而非聚簇索引的叶子节点上只存储了索引列主键,如果需要查询的列不在索引列中,则需要依据主键再重新回到聚簇索引中进行查找,即回表查询,需要查询两次索引树。

覆盖索引:

  • 覆盖索引就是把要使得需要查询的列和索引列是对应的,只查找一次索引树就能得到想要的所有列,从而避免了回表操作。

聚集索引的缺点

  1. 依赖于有序的数据 :因为B+树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或UUID这种又长又难比较的数据,插入或查找的速度肯定比较慢。
  2. 更新代价大 : 如果对索引列的数据被修改时,那么对应的索引也将会被修改, 而且况聚集索引的叶子节点还存放着数据,修改代价肯定是较大的, 所以对于主键索引来说,主键一般都是不可被修改的

最左匹配原则

  • 索引可以简单如一个列 (a),也可以复杂如多个列 (a,b,c,d),即联合索引
  • 如果是联合索引,那么key也由多个列组成,同时,索引只能用于查找key是否存在(相等),遇到范围查询 (>、<、between、like左匹配)等就不能进一步匹配了,后续退化为线性查找。
  • 因此,列的排列顺序决定了可命中索引的列数

由于最左前缀原则,在创建联合索引时,索引字段的顺序需要考虑字段值去重之后的个数,较多的放前面。ORDER BY子句也遵循此规则。

不需要考虑=、in等的顺序,MySQL会自动优化这些条件的顺序,以匹配尽可能多的索引列:

  • 如有索引 (a,b,c,d),查询条件 c>3 and b=2 and a=1 and d<4a=1 and c>3 and b=2 and d<4

  • MySQL会自动优化为 a=1 and b=2 and c>3 and d<4,依次命中a、b、c;不需要在意顺序,MySQL会自动进行优化

注意事项、优化

  • 尽量选择区分度高的列作为索引,区分度的公式是COUNT(DISTINCT col) / COUNT(*)。表示字段不重复的比率,比率越大我们扫描的记录数就越少。
  • 频繁更新的字段应该慎重建立索引,不被经常查询的字段没有必要建立索引
  • 尽可能的考虑建立联合索引,而不是单列索引;同时设计覆盖索引
  • 尽可能的扩展索引,不要新建立索引。比如表中已经有了a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
  • 考虑在字符串类型的字段上使用前缀索引代替普通索引
  • 索引列不能参与计算,尽量保持列“干净”。比如,FROM_UNIXTIME(create_time)='2016-06-06'就不能使用索引,原因很简单,B+树中存储的都是数据表中的字段值,但是进行检索时,需要把所有元素都应用函数才能比较,显然这样的代价太大。所以语句要写成 :create_time=UNIX_TIMESTAMP('2016-06-06')。
explain

通过explain命令我们可以知道以下信息:表的读取顺序,数据读取操作的类型,哪些索引可以使用,哪些索引实际使用了,表之间的引用,每张表有多少行被优化器查询等信息。

explain命令输出的结果有10列:id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra

  • table:显示了对应行所在的表
  • type:关联类型或者访问类型,即表明了MySQL如何去表中查找对应的行,是判断查询是否高效的重要依据;对应取值:
    • ALL:全表扫描,性能较差
    • index:全索引扫描,扫描了全部的索引,避免了排序,但是开销仍然较大;如果在 Extra 列看到 Using index,说明正在使用覆盖索引
    • range:范围扫描,一个有限制的索引扫描,它开始于索引里的某一点,返回匹配这个值域的行;通常在范围查找中出现
    • ref:索引查找,返回所有匹配某个单个值的行。此类型通常出现在多表的 join 查询,针对于非唯一或非主键索引,或者是使用了最左前缀规则索引的查询。
    • eq_ref:使用这种索引查找,最多只返回一条符合条件的记录。在使用唯一性索引或主键查找时会出现该值,非常高效。
    • const、system:该表至多有一个匹配行,在查询开始时读取,或者该表是系统表,只有一行匹配。其中 const 用于在和 primary key 或 unique 索引中有固定值比较的情形。
    • NULL:在执行阶段不需要访问表。
  • possible_keys:这一列显示查询可能使用哪些索引来查找
  • key:这一列显示MySQL实际决定使用的索引。如果没有选择索引,键是NULL。
  • key_len:这一列显示了在索引里使用的字节数,当key列的值为 NULL 时,则该列也是 NULL
  • ref:这一列显示了哪些字段或者常量被用来和key配合从表中查询记录出来。
  • rows:这一列显示了估计要找到所需的行而要读取的行数,这个值是个估计值,原则上值越小越好。
  • extra:其他的信息:
    • Using index:使用覆盖索引,表示查询索引就可查到所需数据,不用扫描表数据文件,往往说明性能不错。
    • Using Where:在存储引擎检索行后再进行过滤,使用了where从句来限制哪些行将与下一张表匹配或者是返回给用户。
    • Using temporary:在查询结果排序时会使用一个临时表,一般出现于排序、分组和多表 join 的情况,查询效率不高,建议优化。
    • Using filesort:对结果使用一个外部索引排序,而不是按索引次序从表里读取行,一般有出现该值,都建议优化去掉,因为这样的查询 CPU 资源消耗大。

MySQL对于一些操作会进行默认的加锁:

  • 对于 UPDATE、DELETE、INSERT语句,InnoDB会自动给涉及数据集加排他锁(X锁)
  • MyISAM在执行查询语句 SELECT前,会自动给涉及的所有读锁,在执行更新操作( UPDATE、DELETE、INSERT等)前,会自动给涉及的写锁,这个过程并不需要用户干预

表锁和行锁

  • 表锁:开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低,是粒度最大的一种锁
  • 行锁:开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高,是粒度最小的一种锁

InnoDB只有通过索引条件检索数据才使用行级锁,否则,InnoDB将使用表锁;即行锁是基于索引的。

表锁

表锁又分为表读锁和表写锁,其中读读不阻塞,读写阻塞,写写阻塞,即读锁和写锁是互斥的,读写操作是串行

请求锁模式 / 是否兼容当前锁None读锁写锁
读锁
写锁
  • 如果某个进程想要获取读锁,同时另外一个进程想要获取写锁。在MySQL里边,写锁是优先于读锁的
  • 写锁和读锁优先级的问题是可以通过参数调节的: max_write_lock_countlow-priority-updates

MyISAM可以支持查询和插入操作的并发进行。可以通过系统变量 concurrent_insert来指定哪种模式,在MyISAM中它默认是:如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。但是InnoDB存储引擎是不支持的

行锁

共享锁(S锁、读锁)

  • 允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。也叫做读锁:读锁是共享的,多个客户可以同时读取同一个资源,但不允许其他客户修改

排它锁(X锁、写锁)

  • 允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。也叫做写锁:写锁是排他的,写锁会阻塞其他的写锁和读锁

另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁

  • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
  • 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
  • 意向锁是数据库隐式实现的,不需要人为设置

乐观锁和悲观锁

乐观锁和悲观锁是并发控制主要采用的技术手段。

  • 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作

    • 在查询完数据的时候就把事务锁起来,直到提交事务
    • 实现方式:使用数据库中的锁机制
  • 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。

    • 在修改数据的时候把事务锁起来,通过version的方式来进行锁定
    • 实现方式:使用version版本或者时间戳

MVCC(多版本并发控制)

锁的应用最终导致不同事务的隔离级别,事务的隔离级别就是通过锁的机制来实现,只不过隐藏了加锁细节

MVCC就是行级锁的一个变种(升级版)。在表锁中我们读写是阻塞的,基于提升并发性能的考虑,MVCC一般读写是不阻塞的(所以说MVCC很多情况下避免了加锁的操作)。MVCC实现的读写不阻塞正如其名(多版本并发控制):

  • 通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本

快照有两个级别

  • 语句级:针对于 Readcommitted隔离级别
  • 事务级别:针对于 Repeatableread隔离级别

InnoDB中的MVCC的具体实现:

  • InnoDB中每一行记录后都有两个隐藏的列,一个保存了行的创建时间,另一个保存了行的过期时间(或删除时间),以系统版本号而非时间值的形式存储
  • 每开始一个新的事务时,系统版本号都会递增;而此时的系统版本号也会作为事务的版本号,用于和查询到的记录中的版本号进行对比
  • InnoDB只查找(SELECT)小于当前事务版本号的数据(行内的系统版本号小于等于事务的版本号),从而事务查询到的记录要么是此前就已经创建的,要么是在当前事务中创建的
  • 行的删除版本号要么未定义,要么大于当前事务版本号,以确保事务读取到的行在事务开始之前没有被删除

间隙锁GAP

当我们用范围条件检索数据而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合范围条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做间隙(GAP)。InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁。

间隙锁只会在 Repeatableread隔离级别下使用。

InnoDB使用间隙锁的目的有两个:

  • 为了防止幻读( Repeatableread隔离级别下再通过GAP锁即可避免了幻读)

  • 满足恢复和复制的需要

    • MySQL的恢复机制要求:在一个事务未提交前,其他并发事务不能插入满足其锁定条件的任何记录,也就是不允许出现幻读

死锁

避免死锁的办法:

  • 1)以固定的顺序访问表和行。比如对两个job批量更新的情形,简单方法是对id列表先排序,后执行,这样就避免了交叉等待锁的情形;将两个事务的sql顺序调整为一致,也能避免死锁。
  • 2)大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。
  • 3)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。
  • 4)降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。
  • 5)为表添加合理的索引。可以看到如果不走索引将会为表的每一行记录添加上锁,死锁的概率大大增大。

日志Log

bin log

binlog记录了数据库表结构和表数据变更,比如update/delete/insert/truncate/create;它不会记录select(因为这没有对表没有进行变更)。从数据库中检索数据是通过搜索引擎的,而每当数据库中的数据被修改时,搜索引擎中的数据也需要进行变更。此时我们就需要对binlog进行监听,如果发现binlog被修改了,则需要对搜索引擎中的数据也进行相应的修改。

bin log中存储了每条进行变更的SQL语句,以及XID:事务的ID等信息。

bin log的作用:

  • MySQL在公司使用的时候往往都是一主多从结构的,从服务器需要与主服务器的数据保持一致,这就是通过binlog来实现的(主从复制)。
  • 数据库的数据被干掉了,我们可以通过binlog来对数据进行恢复

undo log

InnoDB事务日志包括redo log和undo log。redo log是重做日志,提供前滚操作,undo log是回滚日志,提供回滚操作。

undo log主要有两个作用:回滚多版本控制(MVCC)

在数据修改的时候,不仅记录了redo log,还记录undo log,如果因为某些原因导致事务失败回滚了,可以用undo log进行回滚。undo log主要存储的也是(反向的)逻辑日志,比如我们要**insert一条数据了,那undo log会记录的一条对应(相反)的delete日志。我们要update一条记录时,它会记录一条对应相反update**记录。

因为undo log存储着修改之前的数据(执行undo log中的逻辑之后,数据能回到之前的状态),相当于一个前版本,MVCC实现的是读写不阻塞,读的时候只要返回前一个版本的数据就行了。

redo log

对数据库中的一条数据进行修改时,需要先将这条记录读取至内存,在内存中进行修改,之后再写回去。如果在内存中修改完之后,还没有写入磁盘之前,数据库就发生了故障,此时这条修改就会丢失。它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。

MySQL的基本存储结构是(记录都存在页里边),所以MySQL是先把这条记录所在的找到,然后把该页加载到内存中,将对应记录进行修改。redo log记载着这次在某个页上做了什么修改。在对内存中的数据进行修改之后,数据库会写一份redo log,这份redo log记载着这次在某个页上做了什么修改

其实写redo log的时候,也会有buffer,是先写buffer,再真正落到磁盘中的。至于从buffer什么时候落磁盘,会有配置供我们配置。写redo log也是需要写磁盘的,但它的好处就是顺序IO(顺序IO比随机IO快非常多)。

当我们修改的时候,写完内存了,但数据还没真正写到磁盘的时候。此时我们的数据库挂了,我们可以根据redo log来对数据进行恢复。因为redo log是顺序IO,所以写入的速度很快,并且**redo log记载的是物理变化**(xxx页做了xxx修改),文件的体积很小,恢复速度很快

bin log 和 redo log 的区别

binlog记载的是update/delete/insert这样的SQL语句,而redo log记载的是物理修改的内容(xxx页修改了xxx)。所以在搜索资料的时候会有这样的说法:redo log 记录的是数据的物理变化binlog 记录的是数据的逻辑变化

redo log的作用是为持久化而生的。写完内存,如果数据库挂了,那我们可以通过redo log来恢复内存还没来得及刷到磁盘的数据,将redo log加载到内存里边,那内存就能恢复到挂掉之前的数据了。binlog的作用是复制和恢复而生的。

如果内存的数据已经刷到了磁盘了,那redo log的数据就无效了。所以redo log不会存储着历史所有数据的变更,文件的内容会被覆盖的

redo log事务开始的时候,就开始记录每次的变更信息,而binlog是在事务提交的时候才记录。MySQL需要保证redo logbinlog数据是一致

如果在写其中一个log时数据库发生了故障(先写redo log,再写binlog):

  • 如果写redo log失败了,那我们就认为这次事务有问题,回滚,不再写binlog
  • 如果写redo log成功了,写binlog,写binlog写一半了,但失败了怎么办?我们还是会对这次的事务回滚(使用redo log回滚),将无效的binlog给删除(因为binlog会影响从库的数据,所以需要做删除操作)
  • 如果写redo logbinlog都成功了,那这次算是事务才会真正成功

MySQL通过两阶段提交来保证redo logbinlog的数据是一致的:

  • 如果redo log写失败了,而binlog写成功了。那假设内存的数据还没来得及落磁盘,机器就挂掉了。那主从服务器的数据就不一致了。(从服务器通过binlog得到最新的数据,而主服务器由于redo log没有记载,没法恢复数据)
  • 如果redo log写成功了,而binlog写失败了。那从服务器就拿不到最新的数据了

主从复制

主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从数据库上,然后在从数据库上对这些日志进行重新执行,从而使从数据库和主数据库的数据保持一致

MySQL通过三个线程来完成主从库间的数据复制,其中Binlog Dump线程跑在主库上,I/O线程和SQL线程跑着从库上:

  • 在从库上启动复制时,先创建一个I/O线程连接主库
  • 主库创建Binlog Dump线程读取Binlog中的数据库事件并发送给I/O线程,I/O线程将其更新到从库的Relay Log中去
  • 从库创建SQL线程读取中继日志Relay Log中的数据库事件并应用

存储过程

存储过程就像我们编程语言中的函数一样,封装了我们的代码(PLSQL、T-SQL)

存储过程的优点:

  • 能够将代码封装起来
  • 保存在数据库之中
  • 让编程语言进行调用
  • 存储过程是一个预编译的代码块,执行效率比较高
  • 一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率

存储过程的缺点:

  • 每个数据库的存储过程语法几乎都不一样,十分难以维护(不通用)
  • 业务逻辑放在数据库上,难以迭代

视图

视图是一种基于数据表的一种虚表

  • (1)视图是一种虚表
  • (2)视图建立在已有表的基础上, 视图赖以建立的这些表称为基表
  • (3)向视图提供数据内容的语句为 SELECT 语句,可以将视图理解为存储起来的 SELECT 语句
  • (4)视图向用户提供基表数据的另一种表现形式
  • (5)视图没有存储真正的数据,真正的数据还是存储在基表中
  • (6)程序员虽然操作的是视图,但最终视图还会转成操作基表
  • (7)一个基表可以有0个或多个视图

使用视图可以让我们专注与逻辑,但不提高查询效率

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值