1. 常规
MyISAM与InnoDB的区别是什么?
(1)存储结构
MyISAM:每个MyISAM在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。
InnoDB:所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。
(2)存储空间
MyISAM:可被压缩,存储空间较小。支持三种不同的存储格式:静态表(默认,但是注意数据末尾不能有空格,会被去掉)、动态表、压缩表。
InnoDB:需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。
(3)可移植性、备份及恢复
MyISAM:数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。
InnoDB:免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对痛苦了。
(4)事务支持
MyISAM:强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。
InnoDB:提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。
(5)表锁差异
MyISAM:只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。
InnoDB:支持事务和行级锁,是innodb的最大特色。行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。
(6)全文索引
MyISAM:支持 FULLTEXT类型的全文索引
InnoDB:5.6版本开始支持全文索引。
(7)表主键
MyISAM:允许没有任何索引和主键的表存在,索引都是保存行的地址。
InnoDB:如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见),数据是主索引的一部分,附加索引保存的是主索引的值。
(8)表的具体行数
MyISAM:保存有表的总行数,如果select count() from table;会直接取出出该值。
InnoDB:没有保存表的总行数,如果使用select count() from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,myisam和innodb处理的方式都一样。
(9)CURD操作
MyISAM:如果执行大量的SELECT,MyISAM是更好的选择。
InnoDB:如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。DELETE 从性能上InnoDB更优,但DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除,在innodb上如果要清空保存有大量数据的表,最好使用truncate table这个命令。
(10)外键
MyISAM:不支持
InnoDB:支持
MyISAM索引与InnoDB索引的区别
- InnoDB是聚集索引,数据文件是和(主键)索引绑在一起的,通过主键索引到整个记录,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,因为辅助索引是以建索引的字段为关键字索引到主键,所以需要两次,先查询到主键,然后再通过主键查询到数据。
- MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
也就是说:InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;而MyISAM的B+树主键索引和辅助索引的叶子节点都是数据文件的地址指针。
2.mysql锁
2.1 锁的分类
- 按照粒度分类:
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。- 按照功能分类:
共享锁(读锁):其他事务可以并发读取数据,阻止一切修改操作。
排它锁(写锁):某个事务对某行数据加了排它锁,只有该事务能对其进行读和写操作,其他事务不能对其加任和锁。其他进程不能读取,也不能进行写操作。排它锁是悲观锁的一种实现方式。排它锁或阻塞其他的排它锁和共享锁。
全局锁:使用场景比如做全库逻辑备份,该命令可以使整个库处于只读状态,阻止一切修改操作。- 按照逻辑分类:
乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。
2.2 乐观锁和悲观锁的实现
- 乐观锁
版本号控制:一般是在数据表中加上一个数据版本号 version 字段,表示数据被修改的次数。当数据被修改时,version 值会 +1。当线程 A 要更新数据时,在读取数据的同时也会读取 version 值,在提交更新时,若刚才读取到的 version 值与当前数据库中的 version 值相等时才更新,否则重试更新操作,直到更新成功。
悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。
注:
- 悲观锁
1、实现悲观锁利用select ... for update加锁, 操作完成后使用commit来释放锁;
2、innodb引擎时, 默认行级锁, 当有明确字段时会锁一行, 如无查询条件或条件字段不明确时, 会锁整个表,条件为范围时会锁整个表;
3、查不到数据时, 则不会锁表。
SELECT * FROM user WHERE id=3 FOR UPDATE;
验证:
进程 1 | 进程 2 |
---|---|
begin; |
- |
SELECT * FROM user WHERE id = 1 FOR UPDATE; |
- |
- | UPDATE user SET name = ‘test’ WHERE id = 2; 成功 |
- | UPDATE user SET name = ‘test’ WHERE id = 1; 等待 |
commit; | - |
- | 执行等待的任务,成功 |
2.3 死锁和死锁检测
在并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁
事务A在等待事务B释放id=2的行锁,而事务B在等待事务A释放id=1的行锁。事务A和事务B在互相等待对方的资源释放,就是进入了死锁状态。当出现死锁以后,有两种策略:
一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数
innodb_lock_wait_timeout
来设置
另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数
innodb_deadlock_detect
设置为on,表示开启这个逻辑
2.4 隔离级别与锁的关系?
- 在读未提交级别下,读取数据不需要加共享锁,这样就不会跟被修改的数据上的排他锁冲突。
- 在读已提交级别下,读操作需要加共享锁,但是在语句执行完以后释放共享锁。释放完成后,如果其他事务对他修改提交后,再次读取的值和前面读取的值不一样,这就是不可重复读。
- 在可重复读级别下,读操作需要加共享锁,但是在事务提交之前并不释放共享锁,也就是必须等待事务执行完毕以后才释放共享锁。对于范围查询只会锁住当前数据库已经存在符合条件的行,如果新增一个符合条件的行,再次范围查询的结果就和上次范围查询的结果不同,这就是幻读。
- 序列化是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。
3.事务
3.1事务特性(ACID)
- A:原子性(atomicity)一个事务必须被视为一个不可分割的工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚。对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。
- C:一致性(consistency)数据库总是从一个一致性状态转换到下一个一致性状态。
- I:隔离性(isolation)通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的,这就是隔离性带来的结果。
- D:持久性(durability)一旦提交,事务所做的修改就会被永久保存到数据库中。此时即使系统崩溃,数据也不会丢失。
3.2ACID各自的实现原理是什么?
- 原子性的实现依赖undo log回滚日志。每一条数据变更(insert/update/delete)操作都伴随一条undo log的生成,并且回滚日志必须先于数据持久化到磁盘上。所谓的回滚就是根据回滚日志做逆向操作,比如delete的逆向操作为insert,insert的逆向操作为delete,update的逆向为update等。
- 数据库的一致性依赖于其他三种特性:原子性,隔离性,持久性。所谓一致性,指的是数据处于一种有意义的状态,例如从帐户A转一笔钱到帐户B上,A账户上减少的钱数等于B账户上增加的钱数才是一种有意义的状态。
- 隔离性通过锁机制来实现。使用锁机制,保证每个事务能够看到的数据总是一致的,就好像其他事务不存在一样,多个事务并发执行后的状态和它们串行执行后的状态是等价的。原则上一般是两种类型的锁:乐观锁和悲观锁。
- 持久性通过redo log来保证。Mysql是先把磁盘上的数据加载到内存中,在内存中对数据进行修改,再刷回磁盘上。如果此时突然宕机,内存中的数据就会丢失。但是如果事务提交前直接把数据写入磁盘太浪费IO资源,因此使用redo log来解决持久性和读写IO消耗严重之间的平衡问题,当做数据修改的时候,不仅在内存中操作,还会在redo log中记录这次操作。当事务提交的时候,会将redo log日志进行刷盘(redo log一部分在内存一部分在磁盘)。当数据库宕机重启会将redolog中的内容恢复到数据库再根据undo log和binlog内容决定回滚数据还是提交数据。
3.3 事务的隔离级别
-
READ UNCOMMITTED(未提交读)
在READ UNCOMMITTED级别,在事务中可以查看其他事务中还没有提交的修改。读取未提交的数据,也称为脏读(dirty read)。 -
READ COMMITTED(提交读)
大多数数据库系统的默认隔离级别是READ COMMITTED(但MySQL不是)。READ - COMMITTED
满足前面提到的隔离性的简单定义:一个事务可以看到其他事务在它开始之后提交的修改,但在该事务提交之前,其所做的任何修改对其他事务都是不可见的。这个级别仍然允许不可重复读(nonrepeatable read),这意味着同一事务中两次执行相同语句,可能会看到不同的数据结果 -
REPEATABLE READ(可重复读)
解决了不可重复读问题,保证了在同一个事务中多次读取相同行数据的结果是一样的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(phantom read)的问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(phantom row)。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。REPEATABLE READ是MySQL默认的事务隔离级别。 -
SERIALIZABLE(可串行化)
SERIALIZABLE是最高的隔离级别。该级别通过强制事务按序执行,使不同事务之间不可能产生冲突,从而解决了前面说的幻读问题。简单来说,SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。实际应用中很少用到这个隔离级别,除非需要严格确保数据安全且可以接受并发性能下降的结果。
3.4 事务的实现原理
事务是通过redo日志和innodb的存储引擎日志缓冲(Innodb log buffer)来实现的。 当开始一个事务的时候,会记录该事务的lsn(log sequence number)号; 当事务执行时,会往InnoDB存储引擎的日志的日志缓存里面插入事务日志; 当事务提交时,必须将存储引擎的日志缓冲写入磁盘(通过innodb_flush_log_at_trx_commit来控制)。 也就是写数据前,需要先写日志。这种方式称为“预写日志方式”(waf)。
4.最左原则
顾名思义 从最左边进行匹配查询 ,一直向右边匹配,只遇到范围内查询进行停止 (< > + %);
5 b+树层高、好处、为啥不用二叉树
B+树层一般高为三层(可以存2千w数据),叶子节点保存索引和数据,分叶子节点保存索引,减少内存的使用,可以节约资源,而且相互之间有指针,可以提高查找效率。数据结构比较稳定。
二叉树是链表结构,相当于全表扫描。查询效率比b+树慢
6. 读写分离
- 工作原理
让主数据库处理事务性增、删、改操作(INSERT、DELETE、UPDATE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。 - 为什么要读写分离
- 面对越来越大的访问压力,单台的服务器性能成为瓶颈,需要分担负载。
- 因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。
- 但是数据库的“读”(读10000条数据可能只要5秒钟)。
- 所以读写分离,解决的是,数据库的写入影响了查询的效率。
- 什么时候要读写分离
数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用。利用数据库主从同步,再通过读写分离可以分担数据库压力,提高性能。 - mysql支持的复制类型
-
STATEMENT
:基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高。 -
ROW
:基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍。 -
MIXED
:混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
(6)MySQL 读写分离方式 - 基于程序代码内部实现
在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。
优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。 - 基于中间代理层实现
代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序。
- MySQL-Proxy:MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行SQL 判断。
- Atlas:是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。
- Amoeba:由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。
7 MySQL的复制原理
- 步骤一:主库db的更新事件(update、insert、delete)被写到binlog
- 步骤二:从库发起连接,连接到主库
- 步骤三:此时主库创建一个binlog输出线程,把binlog的内容发送到从库
- 步骤四:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log.
- 步骤五:还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db
8 索引
索引的分类
1)B-tree索引(包含b+tree索引)
- 主键索引:
- Innodb主键索引:primary key :加速查找+约束(不为空且唯一)
- MyIsam主键索引和平台索引结构上差不多,但是约束上加了唯一性。
2)辅助索引:
- 普通索引index :加速查找
- 唯一索引unique:加速查找+约束 (唯一)
- 联合索引
- primary key(id,name):联合主键索引
- unique(id,name):联合唯一索引
- index(id,name):联合普通索引
3)哈希索引
哈希索引是基于哈希表实现的,只有精确匹配索引所有列的查询才有效。对于每一行数据存储引擎都会对所有的所有列计算一个哈希码。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。
在MySQL中,自有Memory引擎显式支持哈希索引。哈希索引只存储对于的哈希值,所以索引的结构十分紧凑,这也让哈希索引的查找速度非常快。
哈希索引的缺点:
- 哈希索引不包含行数据,查找过程先找到数据行指针,再去磁盘中读取查找数据。
- 哈希索引不是按照所有值顺序排序存储的,所以无法用于排序。
- 哈希索引只能全值匹配,不支持部分索引列匹配查找。
- 哈希索引只支持等值比较查询,如:=、IN()、<=>
- 哈希冲突很多的话,一些索引维护操作的代价也会很高。
InnoDB引擎有一种特殊的公共:自适应哈希索引,对永无无感知。
4)全文索引
全文索引fulltext :用于搜索很长一篇文章的时候,效果最好。全文搜索的索引。只能用于InnoDB或MyISAM表,只能为CHAR、VARCHAR、TEXT列创建。
5)空间数据索引
空间索引spatial :MyISAM表支持空间索引,用作地理数据存储。空间索引会冲所有维度来索引数据,查询时,可以有效的使用任意比较索引中的值。
B-Tree、B+Tree以及MySQL的B+Tree的区别
- B树的特点:
- 每个节点(不区分内节点和叶子节点)都存储key和data。
- 任何关键出现且只出现在一个节点中。
- 搜索有可能在非叶子节点结束
-
在关键字全集内做一次查找,性能逼近二分查找算法
- B+Tree的特点:
- 非叶子节点只存储键值信息,不存放数据。
- 数据记录都存放在叶子节点中。
-
所有叶子节点之间都有一个链指针(普通B+Tree增加的 是单向指针,MySQL增加的是双向指针)
为什么mysql的索引使用B+树而不是B树
- B+树更适合外部存储(一般指磁盘存储),由于内节点(非叶子节点)不存储data,所以一个节点可以存储更多的内节点,每个节点能索引的范围更大更精确。也就是说使用B+树单次磁盘IO的信息量相比较B树更大,IO效率更高。
- mysql是关系型数据库,经常会按照区间来访问某个索引列,B+树的叶子节点间按顺序建立了链指针,加强了区间访问性,所以B+树对索引列上的区间范围查询很友好。而B树每个节点的key和data在一起,无法进行区间查找。
索引的设计原则
- 索引列的区分度越高,索引的效果越好。比如使用性别这种区分度很低的列作为索引,效果就会很差。
- 尽量使用短索引,对于较长的字符串进行索引时应该指定一个较短的前缀长度,因为较小的索引涉及到的磁盘I/O较少,查询速度更快。
- 索引不是越多越好,每个索引都需要额外的物理空间,维护也需要花费时间。
- 利用最左前缀原则。
MySQL优化有哪些方向?
- SQL语句优化:
a、尽量不要使用select(*)
b、where语句的通配符尽量不要放在前面,且最好不要给字段加运算。
c、尽量不要使用limit,因为limit的操作是在内存中执行的,实际上IO以及查询出来所有复合条件的数据。
d、尽量少用多表连接,将复杂的sql拆分多次执行。 - 索引优化:
a、对WHERE子句中频繁使用的建立索引;
b、尽可能使用唯一索引,重复值越少,索引效果越强;
c、尽量使用短索引,如果char(255)太大,应该给它指定一个前缀长度,大部分情况下前10位或20位值基本是唯一的,那么就不要对整个列进行索引;
d、充分利用左前缀,对WHERE语句如果有AND并列,只能识别一个索引(获取记录最少的那个),这时可以将AND的字段加复合索引;
e、不要过度索引。索引越多,占用空间越大,反而性能变慢;
f、应尽量使用到索引覆盖,避免回表。 - 数据库表结构优化:
a、尽可能选择小的数据类型:比如ip用int而不是varchar,金额使用decimal或者int,char代替varchar。
b、尽可能使用not null:非空比空处理效率快,空会额外增加一个字节的空间。
c、单表尽量少于30个字段。
d、innodb擅长更新和删除,同时也支持事务,外键等高级功能。
e、myisam擅长查询及插入。 - 库表水平或者垂直拆分。
- 建立中间表。
- 系统配置优化。
- 开启缓存:query_cache_type设置为O
慢查询的原因有哪些
- SQL 没加索引
-
SQL 索引不生效
- Limit 深分页问题
- 单表数据量太大
- Join 或者子查询过多
- in 元素过多
- order by使用了文件排序
- 锁等待时间长
mysql底层
mysql底层
- Server层:主要包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
- Store层: 存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。也就是说如果我们在create table时不指定 表的存储引擎类型,默认会给你设置存储引擎为InnoDB。
- 连接器
系统(客户端)访问 MySQL 服务器前,做的第一件事就是建立 TCP 连接。
经过三次握手建立连接成功后, MySQL 服务器对 TCP 传输过来的账号密码做身份认证、权限获取。- 用户名或密码不对,会收到一个Access denied for user错误,客户端程序结束执行
- 用户名密码认证通过,会从权限表查出账号拥有的权限与连接关联,之后的权限判断逻辑,都将依赖于此时读到的权限
TCP 连接收到请求后,必须要分配给一个线程专门与这个客户端的交互。所以还会有个线程池,去走后面的流程。每一个连接从线程池中获取线程,省去了创建和销毁线程的开销。
- 查询缓存
- MySQL内部维持着一些Cache和Buffer,比如Query Cache用来缓存一条SELECT语句的执行结果,如果能够在其中找到对应的查询结果,那么就不必再进行查询解析、优化和执行的整个过程了,直接将结果反馈给客户端。
- 这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key缓存,权限缓存等 。
- 这个查询缓存可以在不同客户端之间共享 。
- 从MySQL 5.7.20开始,不推荐使用查询缓存,并在 MySQL 8.0中删除,因为这个比较鸡肋
因为查询缓存往往弊大于利。查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。 因此很可能你费劲地把结果存起来,还没使用呢,就被一个更新全清空了。对于更新压力大的数据库来说,查询缓存的命中率 会非常低
一般建议大家在静态表里使用查询缓存,什么叫静态表呢?就是一般我们极少更新的表。比如,一个系统配置表、字典表,那这张表上的查询才适合使用查询缓存。好在 MySQL 也提供了这种“按需使用”的方式。你可以将my.cnf参数 query_cache_type 设置成 DEMAND。
- 解析器
- 在解析器中对 SQL 语句进行语法分析、语义分析。将SQL语句分解成数据结构,并将这个结构传递到后续步骤,以后SQL语句的传递和处理就是基于这个结构的。如果在分解构成中遇到错误,那么就说明这个SQL语句是不合理的。
- 在SQL命令传递到解析器的时候会被解析器验证和解析,并为其创建 语法树 ,并根据数据字典丰富查询语法树,会 验证该客户端是否具有执行该查询的权限 。创建好语法树后,MySQL还会对SQl查询进行语法上的优化,进行查询重写。
- 查询优化器
- SQL语句在语法解析之后、查询之前会使用查询优化器确定 SQL 语句的执行路径,生成一个执行计划
- 这个执行计划表明应该 使用哪些索引 进行查询(全表检索还是使用索引检索),表之间的连接顺序如何, 最后会按照执行计划中的步骤调用存储引擎提供的方法来真正的执行查询,并将查询结果返回给用户。
- 它使用“ 选取-投影-连接 ”策略进行查询。例如
SELECT id,name FROM student WHERE gender = '女';
这个SELECT查询先根据WHERE语句进行 选取 ,而不是将表全部查询出来以后再进行gender过滤。 这个SELECT查询先根据id和name进行属性 投影 ,而不是将属性全部取出以后再进行过滤,将这两个查询条件 连接 起来生成最终查询结果。
- 执行器
要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误 - 引擎层
存储引擎层( Storage Engines),真正的负责了MySQL中数据的存储和提取,对物理服务器级别维护的底层数据执行操作,服务器通过API与存储引擎进行通信。不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需要进行选取。 - 存储层
所有的数据,数据库、表的定义,表的每一行的内容,索引,都是存在文件系统上,以文件的方式存在的,并完成与存储引擎的交互。当然有些存储引擎比如InnoDB,也支持不使用文件系统直接管理裸设备,但现代文件系统的实现使得这样做没有必要了。在文件系统之下,可以使用本地磁盘,可以使用DAS、NAS、SAN等各种存储系统。
update执行逻辑
- 从BufferPool(内存中).中查看是否有这条数据.没有就从磁盘中加载到缓冲池.然后对这行记录加独占锁
- 把更新行记录的旧值写入 undo log (以便回滚)
- 更新 Buffer Pool (缓冲池)中的数据(成脏数据);
- 执行器把对数据的修改情况写入redo log中(内存中);
- 准备提交事务时(prepare阶段),按策略把 redo log 刷到 redo log 文件(磁盘中)
- 执行器生成这次更新的 binlog,再按策略刷到 binlog 文件(磁盘中);
- 执行器调用引擎的提交事务接口,完成最终的事务提交。(此时会把本次更新对应的 binlog 文件名称和这次- - 更新的 binlog 文件里的位置,写入到redo log文件中,同时在redo log文件里写入一个 commit标记)
- 如果触发刷新脏页的操作,则将内存更新后的脏数据刷回磁盘。