Innodb是怎么实现事务的?
redolog、read view、mvcc、行锁
事务的几种隔离级别解决的问题:
保证数据正确的读取和存储; 锁设计的初衷是处理并发问题,减少行锁冲突来提升业务并发度,避免锁等待
mysql中的关键词统计:
- WAL 技术
- buffer pool
- redo log
- buffer join_buffer(join语句的驱动表使用)
- sort_buffer(MySQL 会给每个线程分配一块内存用于排序,称为 sort_buffer)
- change buffer(唯一索引用不上 change buffer 的优化机制)
- binlog和redolog关联的XID;
- write pos和checkpoint;
- read-view
- 覆盖索引、前缀索引、索引下推
- MDL 读锁,
- MDL 写锁 MDL 的作用是,保证读写的正确性,语句执行期间另一个线程不能对这个表结构做变更 单个语句占用时间长,锁的时间也比较长;而且大事务还会导致主从延迟。
- 一致性读、当前读和行锁就串起来了
- net_buffer(放查询结果集的,默认是 16k) 读写事务与一个只读事务(只读事务,InnoDB 并不会分配 trx_id);
- BNL/NGJ算法(join) Using join buffer (Block Nested Loop):基于块的嵌套循环算法,被驱动表不能有效的利用索引加快访问速度,MySQL一般会为其分配一块名叫join buffer的内存块来加快查询速度;
- using index(表示的就是使用了覆盖索引)/using temporary/filesort Using index condition:
- 如果在查询语句的执行过程中将要使用索引条件下推这个特性,在Extra列中将会显示Using index condition
- 幻读,一致性读的情况下用当前读就会出现,加上写锁,给行两边的空隙加上间隙锁,来避免幻读。幻读仅专指“新插入的行”;
explain
- 执行计划中的type列: const,eq_ref,ref,range,index,ALL
btree
B+ 树能够很好地配合磁盘的读写特性,减少单次查询的磁盘访问次数。 InnoDB 是索引组织表 覆盖索引、前缀索引、索引下推 InnoDB 引擎支持事务,我们利用好事务的原子性和隔离性,就可以简化在业务开发时的逻辑。 对于由于索引统计信息不准确导致的问题,你可以用 analyze table 来解决。 而对于其他优化器误判的情况,你可以在应用端用 force index 来强行指定索引 “order by”是怎么工作的:全字段排序和rowid排序(减少字段排序好后会进行一次回表操作),排序字段在联合索引里面就直接是拍好序的;
索引相关
- 什么是索引? 索引是一种数据结构,可以帮助我们快速的进行数据的查找.
- 索引是个什么样的数据结构呢:索引的数据结构和存储引擎有关, 在MySQL中使用较多的索引有Hash索引,B+树索引,而我们经常使用的InnoDB存储引擎的默认索引实现为B+树索引.
- Hash索引和B+树所有有什么区别:等值查询快、范围查询、模糊、前缀查询慢。hash索引任何时候都避免不了回表查询数据;
- 在建立索引的时候,都有哪些需要考虑的因素呢? 字段的使用频率,经常作为条件进行查询的字段比较适合,如果需要建立联合索引,还需要考虑联合索引中的顺序.
- 创建了索引但是在查询的时候并没有使用的情况:数据库中的列参与了数学运算或者函数,like时左边是通配符%,优化器觉得全表扫描比使用索引快的时候;
事务相关
- 什么是事务:事务是一系列的操作,他们要符合ACID特性;
- 同时有多个事务在进行会怎么样呢:会发生 脏读、不可重复读、幻读。MySQL的事务隔离级别就是解决这些问题的;
- 什么是锁:当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些锁的机制来保证访问的次序;
- MySQL都有哪些锁呢:读锁和写锁,写锁和其它的写锁,共享锁都相斥;锁的粒度取决于具体的存储引擎,InnoDB实现了行级锁,页级锁,表级锁,加锁开销从大到小,并发能力也是从大到小.
表结构设计
- 为什么要尽量设定一个主键:主键是确保数据行在整张表"唯一性的保障";
- 主键使用自增ID还是UUID:UUID会造成插入性能的下降,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片;
- 字段为什么要求定义为not null:null值会占用更多的字节,且会在程序中造成很多与预期不符的情况;
- char可以节省空间且提高检索效率;
- varchar(10)和int(10)代表什么含义? varchar的10代表了申请的空间长度,而int的10只是代表了展示的长度;
- sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,binlog
- 三个范式:1:每个列都不可以再拆分、2:非主键列只依赖于主键、3:不要设计在其它表中可以查的字段;为了性能可以不遵守第三个范式.
存储引擎相关
- InnoDB也是Myisam的区别:
- 事务、行锁、索引的数据在磁盘上表现形式;
- myisam使用读多写少的场景,全文索引;
sql优化
- 慢查询的三种情况:查询条件没有命中索引、加载了不需要的数据列、还是有长事务导致的锁等待;
- 对慢查询的三种优化:索引优化、联合查询的优化、加载了不需要的数据列
- 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写.
- 分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引.
- 如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表. 3、分析查询日志和慢查询日志
- mysql优化解决方案: 选择合适的存储引擎; 将非”索引”数据分离,比方将大篇文章分离存储,不影响其它自己主动查询。 建立合适的索引,比如联合索引和前缀索引; 对可能全表扫描的sql用explain工具分析一下; 分析查询日志和慢查询日志
- sql优化一般分为这几步,选择合适的存储引擎、设计表时选择合适的字段类型、索引优化、开启慢日志、看看业务层面是否用了合适的sql
业务相关
- 超大的分页一般从两个方向上来解决:数据库层面,减少load的数据(索引覆盖),从需求的角度减少这种请求
- mysql线程突然增多的原因:长事务不提交就会一直占着MDL锁,这时就可能导致库的线程爆满,锁等待、缓存命令率低等;出现N多客户端同时对一行进行操作,死锁检测CPU 消耗接近100%;
- 把一致性读、当前读和行锁串起来;
- 脑补sql语句的执行流程。explain命令来查看语句的执行计划,将该语句过一遍查询优化器;
- 要使用 InnoDB,因为不论是在事务支持、并发能力还是在数据安全方面,InnoDB 都优于 MyISAM
mysql数据库(重要): acid四个特性,产生的相关技术点: 原子性,事务 一致性,redo log 隔离性,锁、mvcc和快照 持久性,bin log和入磁盘
- acid:3特性+3查询 数据库从运行到存储的过程中产生的6个技术点 锁,有哪些锁,加锁的规则是什么,mvcc,快照,行锁是支持事务最多的 事务四种隔离级别 保证数据不丢的和数据的持久化bin log/redo log 索引(查和加索引) sql优化(内存和联合查询方面) 存储引擎和临时表
- server层、引擎层、分析器、查询优化器 数据库优化的目的是:尽量少地访问资源是数据库设计的重要原则,基于成本的优化,分析查询语句或是结构的性能瓶颈; 锁设计的初衷是在并发访问的时候,合理地控制资源的访问规则。锁是一种重要数据结构。
一个 SQL 语句完整查询流程:
Server 层和存储引擎层,server包括连接器、查询缓存、分析器、优化器、执行器等
一条SQL更新语句是的流程
更新流程还涉及两个重要的日志模块,redo log(重做日志)和 binlog(归档日志),WAL 技术;
事务隔离:
在“可重复读”隔离级别下,视图是在事务启动时创建的 在“读提交”隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的 长事务存在的两个风险:回滚记录很多,对回滚有影响,长事务还占用锁资源; 索引相关:InnoDB 是索引组织表,索引包括这三个,覆盖索引、索引下推、前缀索引、联合索引 可重复读隔离级别更新一行时,如果刚好有另外一个事务拥有这一行的行锁,它会被阻塞,进入锁等待,更新直接就是当前读; 读提交,每一个语句执行前都会重新算出一个新的视图; 视图的作用是,实现 MVCC(基于数据的row trx_id),用于支持 RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)隔离级别的实现; 视图(快照)在 MVCC 里是怎么工作的的理解就是:一致性读(快照)和多版本(mvcc) mvcc“所有数据都有多个版本”的这个特性的作用:实现了“秒级创建快照”的能力。数据表中的一行记录,可能有多个版本;
锁相关:
根据加锁的范围,锁大致可以分成全局锁、表级锁、行锁三类 全局锁就是对整个数据库实例加全局读锁,全库逻辑备份 表锁和元数据锁 行锁是在引擎层由各个引擎自己实现的,行锁是最容易造成锁冲突的; 两阶段锁协议,行锁是在需要的时候才加上的,而要等到事务结束时才释放,看持有哪些锁,以及在什么时候释放 死锁,不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源 死锁有两种应对策略:一种策略是,直接进入等待,直到超时,2、发起死锁检测(耗费CPU资源),3、从业务上优化这个问题
MySQL会选错索引的两种情况:
MySQL得到索引的基数不对导致选错索引(基数是通过采样统计),执行成本判断错误(扫描行数),选择索引是优化器的工作,基于成本的优化 force index和建立合适索引来引导优化器做选择,或删掉误用的索引;
给字符串字段加索引:
直接创建完整索引、hash(有额外的存储和计算消耗)、创建前缀索引、倒序存储(可能会增加扫描行数) MySQL刷脏页的两种时机:脏页会被后台线程自动刷,也会由于数据页淘汰而触发;缓冲池中的内存页有三种状态:还没有使用的、使用了并且是干净页、使用了并且是脏页。 count(字段)<count(主键 id)<count(1)≈count(), count() 有优化,优化器会找到最小的那棵树来遍历; InnoDB 引擎使用的是 WAL 技术,执行事务的时候,写完内存和日志,事务就算完成了;mysql的机制是内存优先; order by是怎么工作的:每个线程分配一块内存用于排序,称为sort_buffer。Extra 这个字段中的“Using filesort”表示的就是需要排序,sort_buffer内存放不下
影响性能的两个语句:
- 对索引字段做函数操作,可能会破坏索引值的有序性,
- 隐式类型转换和隐式字符编码转换 加锁规则里面的两个“原则”1:加锁的基本单位是 next-key lock,前开后闭区间;2:查找过程中访问到的对象才会加锁; 加锁的规则:explain 索引组织表、索引、锁这三个东东可以表示一个一个语句的执行流程。加锁的基本单位是 next-key lock,相隔两行就是一个间隙;
redo log和binlog的两个作用:
归档和记录了数据页的更改 1、保证数据不丢的:每次提交事务都要写redo log 和binlog到磁盘,只要这两个保证持久化到磁盘,数据可以恢复 2、持久化的时候更快:redo log 和 binlog 都是顺序写,磁盘的顺序写比随机写速度要快; 两阶段提交:时序上 redo log 先 prepare, 再写 binlog,最后再把 redo log commit。 一个sql查这么多数据,会不会把数据库内存打爆:innodb的核心是尽量使用内存,buffer pool有三种状态,由一个lru链表来维护young和old区; join语句的优化:小表驱动,两种方式表示小表,被驱动表可以用上索引的情况; 用户创建临时表:一个临时表只能被创建它的 session 访问,对其他线程不可见,临时表可以与普通表同名,增删改查语句先访问的是临时表。 内部临时表:语句执行过程可以一边读数据,一边直接得到结果,是不需要额外内存的,否则就需要额外的内存,来保存中间结果 Memory 引擎,索引是哈希索引,范围查询时,需要走全表扫描;不支持 varchar 和 Text 字段,数据都保存在内存比磁盘快;
我的思考:
innodb的核心是尽量使用内存,buffer pool有三种状态,由一个lru链表来维护young和old区; explain 索引组织表、索引、锁这三个东东可以表示一个一个语句的执行流程; 锁是一种数据结构,维护了高并发下数据的访问规则; 事务的四种隔离级别,可重复读会出现幻读的现象,幻读是用了当前读,读取到了insert的语句;
问题:
InnoDB和MyISAM的区别: 1、InnoDB:nnoDB是聚簇索引,支持事务、行级锁;用法:可靠性要求较高,需要支持事务,数据的增删改查都非常的频繁; 2、MyISAM:非聚簇索引(叶子节点存指针); 用法:查询非常频繁,没有事务的场景,对数据的增删改的频率不高; https://blog.csdn.net/wjtlht928/article/details/46641865 B+ 树能够很好地配合磁盘的读写特性,减少单次查询的磁盘访问次数。 InnoDB 是索引组织表 覆盖索引、前缀索引、索引下推 InnoDB 引擎支持事务,我们利用好事务的原子性和隔离性,就可以简化在业务开发时的逻辑。 对于由于索引统计信息不准确导致的问题,你可以用 analyze table 来解决。 而对于其他优化器误判的情况,你可以在应用端用 force index 来强行指定索引 “order by”是怎么工作的:全字段排序和rowid排序(减少字段排序好后会进行一次回表操作),排序字段在联合索引里面就直接是拍好序的;
sql中的几种语句
dql、dml、ddl、dcl 隐式提交,间接完成的提交为隐式提交:CREATE,DROP,ALTER,RENAME,GRANT,REVOKE 区别