精华内容
下载资源
问答
  • 数据库的事务隔离 ...数据库的隔离级别都有什么? 数据库的MVVC视图是怎么实现的? 数据库的隔离级别是为了解决什么问题的? 看完上面三个问题,自己能回答上来几个呢?不急。我们继续往下看 数据库的事务 数据库

    数据库的事务隔离

    前段时间,公司内部遇到了一个问题,就是我们创建的同一批任务,别分配给了不同的实例去执行,导致线上的结果出现问题。
    另一个组的leader说没有开启事务,设置下事务就可以。
    数据库一出现一致性问题,就说开启事务,我就有点疑惑,数据库的事务到底是怎么保证一致性的。

    在看下面的内容,我们可以先思考几个问题。

    数据库的隔离级别都有什么?
    数据库的MVVC视图是怎么实现的?
    数据库的隔离级别是为了解决什么问题的?
    看完上面三个问题,自己能回答上来几个呢?不急。我们继续往下看

    数据库的事务

    数据库的事务我们简单来说就是用来保证数据的正确性,它只有两个操作:事务要么成功,要么失败并进行回滚。

    为什么这么做呢?这是因为一般我们进行事务操作,都会进行一组操作。比如你常见的金融转账。

    在这个转账事务里面包含2个操作:

    • 扣自己银行账户的钱
    • 给对应的账户添加收到的钱。

    现在思考下,如果我们没有添加事务,那么会出现什么样的情况呢?

    1. 如果先扣钱成功,执行给别人加钱失败。而钱已经扣了,对方没收到钱,你说怎么办?
    2. 如果先给对方加钱,而扣你钱的时候没扣成功。这钱银行给的补助吗?嘿嘿,那银行肯定不开心。

    所以了我们只能在这种操作中使用事务,来保证执行的成功与失败,失败了要进行回滚,保证扣钱的操作也不执行。

    事务的ACID

    事务具有四个特性,这四个特性简称为ACID

    • 原子性Atomicity:同一组操作,要么做,要么不做,一组中的一两个执行成功不代表成功,所有成功才可以。这就是原子性,做或者不做(失败进行回滚)。
    • 一致性Consistency:数据的一致性,就像上面的举例说的,你扣钱了,对方没加钱,那肯定不行。
    • 隔离性Isolation:多个数据库操作同一条数据时,不能互相影响。不能你这边变动,那边数据空间就变换了。
    • 持续性Durability: 事务结果提交后,变动就是永久性的,接下来的操作或者系统故障不能让这个记录丢失。

    今天主要说的事务就是隔离。看看事务是怎么保证数据之间的隔离

    事务的隔离级别

    不同的事务隔离级别对应的不同的数据执行效率,隔离的越严格,那么执行的效率就约低下,下面的四个隔离级别是原来越严格。

    • 读未提交(read uncommitted):指数据在事务执行时,还没有提交,其他事务就可以看到结果
    • 读提交(read committed):指数据在其事务提交后,其他事务才能看到结果。视图是在执行sql语句的时候进行创建,具体视图看下面的数据隔离是怎么实现的
    • 可重复读(repeatable read):一个事务在执行过程中,看到的结果与其启动的时候看到的内容是一致的。启动的时候会创建一个视图快照,该事务状态下,会看的一致是这个视图快照内容,其他事务变更是看不到的。注意是读取的过程,如果是更新,那么会采用当前读,就是其他事务的更新操作会拿到结果,用来保证数据一致性
    • 串行化(serializable):顾名思义,就是将多个事务进行串行化(读写过程中加锁,读写冲突,读读冲突),一个事务结束后,另外一个事务才能执行,带来的效果就是并行化不好,效率低下。

    Mysql中默认的事务隔离级别是可重复读,使用下面这个命令进行查看当前的事务级别,

    show variables like 'transaction_isolation';
    
    # 下面的语句进行修改事务的级别。
    SET session TRANSACTION ISOLATION LEVEL Serializable;(参数可以为:Read uncommittedRead committedRepeatableSerializable

    事务级别

    事务的启动方式

    在程序中,我们很多时候都是默认的自动提交,也就是一个sql操作就是一条事务,但有时候需要的是多个SQL进行组合,我们就要显式的开启事务。

    显示开启的语句是用 begin或者 start transaction.同样在事务结束的时候使用commit进行提交,失败使用rollbakc进行回滚。

    当然如果不想让SQL进行自动提交,我们就将自动提交进行关闭set autocommit=0,这样事务就不会自动提交,需要我们手动的执行commit.

    如何避免长事务

    关闭自动提交事务后,就需要我们来自己提交事务,这时候每个语句执行都是这样的。

    
    begin
    sql语句
    commit
    

    如果我们在程序编写中,本来一个sql解决的操作,结果忘记进行事务的提交,到下下下一个SQL才进行commit,这样就会出现长事务。

    而长事务往往会造成大量的堵塞与锁超时的现象,事务中如果有读写(读读不冲突,读写冲突,写写冲突)操作,那么会将数据进行锁住,其他事务也要进行等待。

    所以在程序中,我们应该尽量避免使用大事务,同样也避免我们写程序的时候出现偶然的大事务(失误😁)。

    解决办法是我们将自动提交打开,当需要使用事务的时候才会显示的开启事务

    程序中出现大量的事务等待怎么办

    在MySQL中想定位一个长事务问题还是很方便的。

    首先我们先找到正在执行的长事务是什么。

    select t.*,to_seconds(now())-to_seconds(t.trx_started) idle_time from INFORMATION_SCHEMA.INNODB_TRX t \G
    

    该语句会展示出事务的执行的开始时间,我们可以很简单的算出,当前事务执行了多久,其中上面的idle_time就是执行的事务时间

    假设我们现在设定的超过30s执行的事务都是长事务,可以使用下面语句进行过滤30s以上的长事务。

    select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>30
    

    通过information_schema.innodb_trx 我们就能定位到长事务。

    从而决定长事务是否要被杀死,还是继续等待。如果出现死锁的情况,处理方式也是类似,查找到死锁的语句,然后进行杀死某个语句的执行(有点暴力)。

    数据隔离是怎么实现的

    注意:本次数据隔离是建立在可重复读的场景下

    在可重复读的场景下,我们了解每次启动事务的时候,会在当前启动一个视图,而这个视图是整个数据库的视图快照。

    嘿嘿,是不是想数据库那么大,为啥我们没有感觉到创建快照时间的消耗呢?

    这是因为数据库创建的视图快照利用了所有数据都有多个版本的特性,来实现快速创建视图快照的能力

    那数据多个版本是怎么回事呢?

    准备下数据

    先别急,我们准备下数据。

    现在创建一个表,并且插入三条数据。

    create table scores
    (
        id    int   not null
            primary key,
        score float null
    );
    INSERT INTO scores (id, score) VALUES (1, 3.5);
    INSERT INTO scores (id, score) VALUES (2, 3.65);
    INSERT INTO scores (id, Score) VALUES (3, 4);
    

    在开始使用前我们要了解两个小知识点。begin/start transaction 与 start transaction with consistent snapshot。

    • begin/start transaction 视图的创建是建立在begin/ start transaction 之后SQL语句才会创建视图, 比如 下面案例

      begin
      select source from scores;  //视图是在这里开始创建 而不是在begin那里创建
      commit
      
    • start transaction with consistent snapshot:则是该语句执行后,就创建视图。

    了解上面两个创建事务的区别后,我们来看下视图是怎么创建出来多个数据版本的. 以下SQL在两个窗口打开。

    事务A 事务B 结果
    start transaction with consistent snapshot 开启事务,并创建视图
    start transaction with consistent snapshot 开启事务,并创建视图
    select score from scors where id =2 事务A中的值为3.65
    update scores set scores = 10 where id =2 事务B修改为10
    select score from scores where id =2 事务B显示为10
    select score from scores where id =2 事务A显示为3.65
    select score from scores where id =2 for update 会被锁住,等待事务B释放锁(间隙锁)
    commit 提交事务B
    select score from scores where id =2 for update 这个语句可以看到变成了10(利用了当前读)
    select score from scores where id =2 不加 for update 那么结果还是3.65
    commit

    上述流程就是两个不同的请求过来,对数据库同一个表的不同操作。

    当事务A执行start transaction with consistent snapshot之后,A的视图就开始被创建了,这时候是看不到事务B对其中的修改,就算事务Bcommit之后,只要事务A不结束,它看到的结果就是它启动时刻的值。

    这就与不重复提交,执行过程中看到的结果与启动的时候看到的结果是一致的这句话对应上了

    快照多版本

    前面说了,快照是事务的启动的时候是基于整个数据库的,而整个数据库是很大,那MYSQL是怎么让我们无感并快速创建一个快照呢。

    快照多版本你可以认为是由以下两部分构成。

    • 事务id(transaction id):这个是由事务启动的时候向InnoDB启动时申请的。并且一定注意哦它是递增的。
    • row trx_id:这个id其实就是事务ID,每次事务更新数据的时候回将事务ID赋值给这个数据版本的事务ID上,将这个数据版本的事务ID称为 row trx_id.

    当一行记录存在多个数据版本的时候,那么就有多个row trx_id 。举个例子

    版本 事务ID 对应的语句操作
    v1 score =3 89
    v2 score =5 90 update scores set score = 5 where id =3; select score from scores where id =3;
    v3 score = 6 91 update scores set score = 6 where id =3;

    v1->v2->v3 这里面涉及了三个版本的迭代。中间是通过undo log 日志来保存更新的记录的。

    注意启动快照之后,可重复读隔离情况下,获取到v1的值,不是说MYSQL直接存储的该值,而是利用现在这条记录的最新版本与undo log日志计算出来的,比如通过v3 ->v2—>v1 计算出v1中score值。

    版本图

    版本计算

    上面简单说了下版本的计算规则,但是在MYSQL中,版本并不是那么简单的计算的,我们现在来看下到底怎么计算的,

    这个两点我们在注意一下:

    • 事务在启动的时候会向InnoDB的事务系统申请事务ID,这个事务ID是严格递增的。
    • 每行数据是多个版本,这个版本的id就是row trx_id,而事务更新数据(更新数据的时候才会生成一个新的版本)的时候会生成一个新的数据版本,并把事务ID赋值给这个数据的事务ID==row trx_id,
    1. 事务启动的时候,能看到所有已经提交事务的结果,但是他启动之后,其他事务的变更是看不到的。

    2. 当事务启动的瞬间,除了已经提交的事务,创建的瞬间还会存在正在运行的事务,MYSQL是把这些正在运行的事务ID放入到一个数组中。数组中最小的事务ID记为低水位,当前系统中创建过的事务ID最大值+1记为高水位。

      举个简单的例子。
      a. 注意一点:获取事务ID与创建数组不是一个原子操作,所以存在事务id为8,然后又存在当前MYSQL中存在活跃事务ID为9 10的事务。

      b. 事务ID低于低水位那么对于当前事务肯定是可见的,事务ID高于高水位的事务ID值,则对当前事务不可见.
      c. 事务ID 位于低水位与高水位之间分为两种情况。

      • 如果事务id是在活跃的数组中表示这个版本是正在执行,但是结果还没有提交,所以这些事务的变更是不会让当然事务看到的。
      • 事务id如果没有在活跃数组中,代表这个事务是已经提交了,所以可见。比如现在创建了90,91,92三个事务,91执行的比较快,提交完毕,90和92还没有提交.这时候创建了一个新的事务id为93,那么在活跃的数组中的事务就是90,92,93,你看91是已经提交了,它的事务还在这个低水位与高水位之间,但结果对于93是可见。

    总的上面来说就是你在我创建的时候事务结果已经提交,那么是可见的,之后提交那么就是不可见的。

    读取流程

    上面简单说了下老版本视图中的数据是通过最新的版本与undo log 计算出来的,那到底怎么就算的呢?

    事务A 事务B 结果
    start transaction with consistent snapshot 事务 id 89 开启事务,并创建视图
    start transaction with consistent snapshot 事务id 92 开启事务,并创建视图
    select score from scors where id =2 事务A中的值为3.65
    update scores set scores = 10 where id =2 事务B修改为10
    select score from scores where id =2 事务B显示为10
    select score from scores where id =2 事务A显示为3.65
    commit

    还是看这个事务操作。
    下面是数据变动的流程。

    • 假设开始之前有两个活跃的事务ID为 78,88.
    • 事务A启动的时候会将78 88,包含它自己放入到活跃数组中。
    • 事务A 操作的语句select score from scors where id =2将其看到的结果认为是v1版本数据比如其现在row trx_id(**注意:**row trx_id是数据行被更新后事务id才会赋值给row trx id上)是86,并且保存好。
    • 事务B启动时,会发现在活跃数组是78,88,89,自己的92.
    • 事务B 执行更新语句语句后,会生成一个新的版本V2,数据变换就是V1–>V2。记录中间变化的是undo log日志。这样ID 89存储的数据就变成了历史数据。数据版本row trx_id则是92
    • 事务A 查询score数据,就会通过先查到现在的V2版本视图,找到对应的row trx_id = 92,发现row trx_id 位于高水位上,则抛弃这个值,通过V2找到V1,row trx_id为86,而86大于低水位,而低于高水位89+1.但是由于86没有在活跃数组中,而且属于已经提交的事务,则当前事务是能看到该结果的,所以事务A能拿到读取的值。

    你看经过简单的几步,我们就拿到了想要读取的事务数据,所以不论事务A什么时候查询,它拿到的结果都是跟它读取的数据是一致的。

    你看有了MVCC(多版本并发控制)计算别的事务更改了值也不会影响到当前事务读取结果的过程。

    我们经常说不要写一个长事务,通过上面的读取流程可以看到,长事务存在时间长的话,数据版本就会有很多,那么undo log日志就需要保存好久,这些回滚日志会占用大量的内存存储空间。

    当没有事务需要读取该日志与版本数据的时候,这个日志才可以删除,从而释放内存空间。

    更新流程

    事务A 事务B 结果
    start transaction with consistent snapshot 事务 id 89 开启事务,并创建视图
    start transaction with consistent snapshot 事务id 92 开启事务,并创建视图
    select score from scors where id =2 事务A中的值为3.65
    update scores set scores = 10 where id =2 事务B修改为10
    select score from scores where id =2 事务B显示为10
    select score from scores where id =2 事务A显示为3.65
    select score from scores where id =2 for update 会被锁住,等待事务B释放锁(间隙锁)
    commit 提交事务B
    select score from scores where id =2 for update 这个语句可以看到变成了10(利用了当前读)
    select score from scores where id =2 不加 for update 那么结果还是3.65
    commit

    上面说了读取的过程,其实在事务中,我们还有更新流程,更新流程比较简单,更新过程我们需要保证数据的一致性,不能说别人修改了,我们还看不到,那样就会造成数据的不一致。

    为了保证看到最新的数据,会对更新行的操作加锁(行锁),加锁之后,其他事务对行进行更新操作,必须等待其他事务commit之后才能获取到最新的值,这个过程被称为当前读

    想要读取过程中获得最新的值可以使用 上面的语句select score from scores where id =2 for update ,就可以看到当前最新值。

    总结

    本小节主要梳理了事务的隔离级别,事务的MVCC多版本并发控制实现原理。

    事务在面试中是比较多的一个点,这样的题目可以多种变换,我们刚开始题目提到的三个问题已经可以解答了。

    你来尝试回答下?

    下期会说下数据库中的幻读,幻读也是面试中经常遇到的问题哦。

    展开全文
  • 1.2 索引都有哪些数据结构?1.3 Hash索引与B+Tree索引的区别?1.4 聚簇索引和覆盖索引区别?1.5 索引设计原则有哪些?1.6 *MySQL索引的使用有哪些注意事项?1.7 *如何知道是否使用了索引?2 视图2.1 什么视图?2.2 ...

    0 参考链接

    1. 100道MySQL常见面试题总结
    2. 【黑马程序员】2020最新MySQL高级教程

    如有错误欢迎批评指正!

    1 索引相关

    1.1 什么是索引?

    索引是一种数据结构,可以使数据库快速查询数据。

    1.2 索引都有哪些数据结构?

    索引的实现与具体数据库有关,在MySQL中常用的有B树索引、B+Tree索引与Hash索引。InnoDB中的默认索引是B+树索引。

    1.3 B树与B+树的区别,InnoDB为什么用B+树做索引

    区别:

    1. B树中可以将索引和行放在内部节点中;B树可以在索引结构内部存放键和值,把频繁访问的数据放在靠近根节点的地方可以提高查询效率。
    2. B+树的非叶子结点只包含导航信息,不包含实际的值,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历。
      • B+树查询效率高,内部节点仅保存键
      • 查询效率稳定:每次都需要从根节点访问到叶子节点
      • B+更有利于全表扫描,B+树只需要访问叶子节点。就可以解决全部信息扫描。

    1.4 Hash索引与B+Tree索引的区别?

    Hash索引的底层就是Hash表,进行查找时,调用一次Hash函数就可以得到相应的键值。

    1. hash索引进行等值查询更快(一般情况下)但是却无法进行范围查询.因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询.

    2. hash索引不支持模糊查询以及多列索引的最左前缀匹配,因为hash函数的不可预测,eg:AAAA和AAAAB的索引没有相关性.

    3. hash索引任何时候都避免不了回表查询数据.

    4. hash索引虽然在等值上查询叫快,但是不稳定,性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时查询效率可能极差.

    5. hash索引不支持使用索引进行排序,因为hash函数的不可预测.

    B+Tree的底层实现是多路平衡查找树。对于每一次查询都是从根结点出发到叶子节点才能找到所查键值。

    1. B+树的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似)自然支持范围查询.

    2. 在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询.不需要回表查询.

    3. 查询效率比较稳定,对于查询都是从根节点到叶子节点,且树的高度较低.

    结论:大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度,而不需要使用Hash索引。

    1.4 聚簇索引、非聚簇索引、二级索引、索引覆盖、回表相关?

    链接1链接2

    1.4.1 聚簇索引

    1. 聚簇索引不单是索引结构,其还是数据存储的方式,数据存储在B+树的叶子索引上(如下图)。
      在这里插入图片描述
    2. 在InnoDB中,默认主键是聚簇索引,如果没有则会选择唯一的列,否则隐式创建主键列。

    优点

    1. 可以把相关数据保存在一起。
    2. 数据访问更快。数据和索引保存在同一个 B+Tree 。
    3. 使用覆盖索引扫描的查询可以直接使用页节点的主键值。

    缺点

    1. 提高了I/O密集型应用的性能,但是数据都在内存中优势就没有那么明显了
    2. 插入速度严重依赖于主键顺序,如果不是按照自增顺序插入,速度将很慢
    3. 更新聚簇的代缴很高,因为InnoDB会将行的所有记录移到新的位置

    1.4.2 二级索引与覆盖查询

    叶子节点中存储主键值,每次查找数据时,根据索引找到叶子节点中的主键值,根据主键值再到聚簇索引中得到完整的一行记录。如下图所示:
    在这里插入图片描述

    对于非聚簇索引:

    • 如果查询语句中包含索引以外的列,则需要回表查询,即进行二次I/O。
    • 如果不包含,则不需要回表查询。

    1.5 索引设计原则有哪些?

    • 在查询频次高、数据量大的表上建立索引
    • 选择where子句中用于比较的字段
    • 选取唯一索引增强区分度
    • 选取短索引提高IO与CPU比较效率
    • 适当索引,所以能够提升查询效率,但是会影响更新的效率,因为在更新时需要同步更新索引结构

    1.6 *MySQL索引的使用有哪些注意事项?

    或者说如何避免索引失效。

    1. 遵循最左前缀法则(针对复合索引)
      • 从最左列索引开始,不能有跳跃,否则索引从跳跃处失效
      • 不从最左索引列开始,索引将全部失效
    2. 不能再索引列上进行运算,否则失效
    3. 字符串不加单引号,索引失效
    4. 尽量使用覆盖索引,即索引包含查询的内容
    5. OR分割条件,如果OR存在没有索引的列,则索引失效
    6. 以%开头的模糊查询,索引失效。
    7. 如果使用索引比全表扫描还蛮,则不使用
    8. 尽量使用复合索引

    1.7 *如何知道是否使用了索引?

    可以在查询语句前添加explain来分析执行计划,其中可以通过三个字段可以判断索引是否命中:

    • possible_key:可能用到的索引
    • key:实际用到的索引
    • key_len:索引长度

    2 视图

    2.1 什么是视图?

    视图是一种预定义的虚拟的表,它不保存查询数据,仅保存查询逻辑,查询的数据在使用时动态生成。

    2.2 视图的作用有哪些?

    • 简化用户查询:使用户不必关心表结构、关联条件与过滤条件,只关心查询结果;
    • 安全性:使用视图的用户只能看到虚拟的表,看不到具体的逻辑;
    • 数据独立:数据库结构变动时,仅需要修改相应的视图逻辑,不会对用户造成影响。

    3 事务相关

    3.1 什么是事务?

    事务就是逻辑上的一个执行流程,该流程要么全部执行,要么都不执行。

    3.2 事务的ACID分别代表什么,详细解释?

    • A=Atomicity:原子性,就是上面说的,要么全部成功,要么全部失败.不可能只执行一部分操作.

    • C=Consistency:一致性,系统(数据库)总是从一个一致性的状态转移到另一个一致性的状态,不会存在中间状态.

    • I=Isolation:隔离性, 通常来说一个事务在完全提交之前,对其他事务是不可见的。注意前面的通常来说加了红色,意味着有例外情况。

    • D=Durability:持久性,一旦事务提交,那么就永远是这样子了,哪怕系统崩溃也不会影响到这个事务的结果。

    3.3 事务并发会带来哪些问题?

    1. 脏读:事务A读取了另外事务B还未提交的内容,而事务B进行了回滚;
    2. 不可重复读:事务A的两次读取结果不一致,事务B在事务A两次读取之间进行了更新操作
    3. 幻读:事务A读取了一个范围的内容,同时事务B在此期间插入/删除了一条数据,造成了“幻觉”。

    3.4 上述问题如何解决,MySQL的事务隔离级别了解吗?

    • 读未提交(READ UNCOMMITTED):其他事务能够看到未提交的修改部分,容易造成上述三种问题。
    • 读已提交(READ COMMITTED):其他事务只能读到已经提交的部分。但是无法预防不可重复读的问题。因为都的过程中,其他事务仍有机会更新记录。
    • 可重复读(REPEATABLE READ):在都的过程中不允许其他事务进行修改。但是无法解决幻影读的问题,因为其他语句仍能插入删除。InnoDB的默认级别时可重复读。
    • 可串行化(SERIALIZABLE):最高的隔离级别,事务被强制串行处理,安全程度最高,但是并发度也最低。

    3.5 MySQL有哪些锁?各自的特点?

    按类型分

    • 读锁:又称共享锁,读锁允许其他事务并行读,但是不允许修改
    • 写锁:又称排他锁,写锁既不允许其他事务修改,也不允许其他事务读

    按粒度分

    • 行级锁:锁粒度最小,开销大,加锁慢,会出现死锁,但并发程度最高。
    • 页级锁:锁粒度与开销介于行级与页级之间,会出现死锁,并发程度一般
    • 表级锁:锁粒度最大,开销最小,加锁最快,但并发程度最低

    4 表结构设计

    4.1 为什么要尽量设定一个主键?

    • 提供唯一性保障
    • 加速查询

    4.2 使用主键自增还是UUID(随机生成)?

    推荐使用主键自增:

    • 在InnoDB中,主键还是作为聚簇索引存在的(主要使用B+树),按需添加会减少B+树结构调整的数据开销。

    4.3 字段为什么要求定义not null

    MySQL官网介绍

    For MyISAM tables, NULL columns require additional space in the row to record whether their values are NULL. Each NULL column takes one bit extra, rounded up to the nearest byte.

    不管字段是否为null,都会设置为占用空间,且会多一个字节,最后向上取到最接近的byte数。

    4.4 如果要存储用户的密码散列,应该使用什么字段进行存储?

    对于固定长度的字符串,应使用固定长度的char而非varchar,这样可以节省空间并且提高检测效率。

    5 *查询优化

    5.1 插入优化大批量插入数据

    推荐按照主键顺序插入,因为InnoDB默认主键使用B+树作为索引,有序插入会降低B+树结构调整的成本。

    5.2 order by优化

    尽量使用索引排序,所有不经过索引的排序都会进行FileSort,比较耗时。

    5.2.1 FIleSort优化

    两次扫描

    先加载排序字段和行指针,根据排序结果到表中提取查询的字段。

    一次扫描

    一次就把所有的结果都读取到内存中,内存开销大,但是查询效率高。

    5.3 group by优化

    因为group by也会进行排序操作,如果没有排序要求,可以使用order by null来禁止排序。

    5.4 使用join优化嵌套查询优化

    连接(Join)查询之所以更有效率一些 ,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作。

    5.5 超大分页优化

    • 尽量在索引上进行分页,避免排序

      select * from table where age > 20 limit 1000000,10;
      -- 改成
      select * from table where id in (select id from table where age > 20 limit 1000000,10;
      

    6 使用EXPLAIN分析SQL语句

    使用方法:在SQL语句前添加explain
    在这里插入图片描述

    • id:表示table加载的优先级,优先级越越先被加载,相同说明处在同一级
    • select_type:表示SELECT的类型
      • SIMPLE:简单的查询,不包括子查询或者UNION
      • PRIMARY:包含子查询,最外层的显示该标识
      • SUBQUARY:子查询的标志
      • DERIVED:from中包含的zichaxun
      • UNION:第二个SELECT出现在UNION后显示的标记
      • UNION RESULT:从UNION表获取结果的SELECT
    • table:分析记录所属的表是哪个
    • type:访问的类型
      • NULL:MySQL不访问任何表,索引,直接返回结果
      • system: 表只有一行记录(等于系统表),这是const类型的特例,一般不会出现
      • const:表示通过索引一次就找到了,const 用于比较primary key 或者 unique 索引。因为只匹配一行数据,所以很快。
      • eq_ref:类似ref,区别在于使用的是唯一索引,使用主键的关联查询,关联查询出的记录只有一条。常见于主键或唯一索引扫描
      • ref:非唯一性索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,返回所有匹配某个单独值的所有行(多个)
      • range:只检索给定返回的行,使用一个索引来选择行。 where 之后出现 between , < , > , in 等操作。
      • index: 与 ALL的区别为 index 类型只是遍历了索引树, 通常比ALL 快, ALL 是遍历数据文件。
      • all:全表扫描
    • key:
      • possible_keys : 显示可能应用在这张表的索引, 一个或多个。
      • key : 实际使用的索引, 如果为NULL, 则没有使用索引。
      • key_len : 表示索引中使用的字节数, 该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下, 长度越短越好 。
    • rows:扫描行的数量
    • extra:
      • using filesort:使用了文件排序,效率低
      • using temporary:使用了临时表保存的结果
      • using index:使用索引覆盖

    7 存储引擎

    7.1 MySQL都支持哪些存储引擎?

    MySQL支持多种数据引擎,并且可以为每张表指定不同的引擎,主要包括:InnoDB、MyISAM、MEMORY、NDB。

    7.2 InnoDB与MyISAM的区别有哪些?

    • InnoDB支持事务
    • InnoDB支持行级锁
    • InnoDB支持外键
    • InnoDB支持MVVC(Multi-Version Concurrency Control,多版本并发控制):乐观锁的思想实现无锁并发
    • MyISAM支持全文索引,MYSQL5.6之后InnoDB也支持全文索引:用于大量文本数据的索引

    8 其他MySQL相关

    8.1 什么是存储过程、函数?有哪些不同?

    存储过程:存储过程是预先编译好的,存储在数据库中的一段SQL语句集合,有如下优点

    • 减少数据传输
    • 预编译,执行效率高
    • 减轻开发人员压力

    函数:一个有返回的过程

    不同

    • 使用方法不同,函数可以像聚合函数COUNT那样在SQL语句中调用,而存储过程使用CALL关键字
    • 存储过程可以有多个返回,函数有且只有一个返回

    9 数据库原理相关

    9.1 数据库的范式有哪些?

    • 第一范式:每个列不可以再分
    • 第二范式:非主键列完全依赖于主键,不能存在只依赖部分主键的列
    • 第三范式:非主键列值不依赖于其他非主属性列(消除非主属性传递依赖)
    • BCNF
      • 非主属性完全依赖于每一个主码
      • 所有主属性都完全依赖于不包含他的码
      • 没有任何属性完全函数依赖于非码的任何一组属性
    展开全文
  • 比如后面要讲的一个单体产品服务应用,提供数据和视图都在一个springboot里。 单体架构系统其好处,如便于开发,测试,部署也很方便,直接打成一个 jar 或者 war, 就什么都好了。 不过单体架构也其弊端,最主要...

    步骤 1 : 先讲单体架构系统

    在讲解Springcloud 之前,我们先讲一讲单体架构系统。 所谓的单体架构就是所有功能,都放在一个应用里。
    比如后面要讲的一个单体产品服务应用,提供数据和视图都在一个springboot里。

    单体架构系统有其好处,如便于开发,测试,部署也很方便,直接打成一个 jar 或者 war, 就什么都好了。

    不过单体架构也有其弊端,最主要体现在高访问,高并发的上限是固定的。 比如一个单体架构,能够承受 1000次访问/秒。 但是访问量达到 2000次/秒的时候,就会非常卡顿,严重影响业务,并且仅仅依靠单体架构本身,很难突破这个瓶颈了。

    步骤 2 : 分布式和集群

    既然单体架构会有性能上的瓶颈,那么总要解决呀。 解决办法通常就是采用分布式和集群来做。
    可是分布式和集群分别是什么意思呢? 

    这个就不是一两句话能够说的清楚的啦。。。。 站长又不愿意直接丢一大堆概念给同学们,让没有接触过的同学们更加云里雾里,所以站长会先讲解单体架构,然后对这个单体架构进行逐步改造,最后让其变成一个分布式和集群系统,通过参与这个过程,大家才能够感性地接触和认识到底什么是分布式和集群。

    步骤 3 : SpringCloud

    SpringCloud 就是一套工具,帮助大家很容易地搭建出这么一个 集群和分布式的架子出来。

    接下来的课程,站长就会从一个简单的单站系统开始,然后一步一步地把它改造成分布式+集群的系统。 在改造的过程中,就会逐步引入服务注册中心 Eureka, 客户端Ribbon,Feigh, 断路保护 Hystrix, 配置服务,消息总线等等概念和用法。 
    按部就班地跟着站长走一遍,差不多SpringCloud 的初步运用就能掌握啦。


    更多内容,点击了解: http://how2j.cn/k/springcloud/springcloud-intro/2035.html?p=71911

    展开全文
  • Springcloud

    2019-11-13 15:17:59
    比如后面要讲的一个单体产品服务应用,提供数据和视图都在一个springboot里。 单体架构系统其好处,如便于开发,测试,部署也很方便,直接打成一个 jar 或者 war, 就什么都好了。 不过单体架构也其弊端,最主要...

    在讲解Springcloud 之前,我们先讲一讲单体架构系统。 所谓的单体架构就是所有功能,都放在一个应用里。
    比如后面要讲的一个单体产品服务应用,提供数据和视图都在一个springboot里。

    单体架构系统有其好处,如便于开发,测试,部署也很方便,直接打成一个 jar 或者 war, 就什么都好了。

    不过单体架构也有其弊端,最主要体现在高访问,高并发的上限是固定的。 比如一个单体架构,能够承受 1000次访问/秒。 但是访问量达到 2000次/秒的时候,就会非常卡顿,严重影响业务,并且仅仅依靠单体架构本身,很难突破这个瓶颈了。Springcloud学习资料以及相关项目

    展开全文
  • 比如后面要讲的一个单体产品服务应用,提供数据和视图都在一个springboot里。 单体架构系统其好处,如便于开发,测试,部署也很方便,直接打成一个 jar 或者 war, 就什么都好了。 不过单体架构也其弊端,最主要...
  • 比如后面要讲的一个单体产品服务应用,提供数据和视图都在一个springboot里。 单体架构系统其好处,如便于开发,测试,部署也很方便,直接打成一个 jar 或者 war, 就什么都好了。 不过单体架构也其弊端,最主要...
  • 从Java基础、JavaWeb基础到常用的框架再到面试题都有完整的教程,几乎涵盖了Java后端必备的知识点。该开源仓库的文章都是我个人原创,公众号发过的技术文章(干货)也会有相关的目录整理,很多知识点我还在不停的...
  • 关于三层数据传输问题的谈讨

    千次阅读 2010-11-04 19:34:00
    开始使用TOP,或Rownum来控制语句分页,但还是不怎么明效,后来又使用存储过程来进行分页,效果明显好转些,但遇上并发还是有些卡,大家对这个有什么好的解决方法没有。   为些我特自己写了一个分页控件...
  • 阿里巴巴B2B Java实习生面试题

    千次阅读 2010-06-25 19:46:00
    挑战性B2B比较注重java底层、J2EE、数据库、并发、业务、学习能力1、自我介绍(还好我昨天准备了下)2、某个项目中遇到的最大问题3、团队成员间如何更好的协作4、项目的总体框架,模块的测试5、项目中用到的设计...
  • 4.1.5 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。 4.1.6 JAVA8的ConcurrentHashMap为什么放弃了分段锁,有...
  •  处理多个并发用户时,如何在5个隔离级别和2个并发模型中做出选择 作译者  Kalen Delanev自1993年起就是微软SQL Server的MVP,她为全世界的客户提供高级SQL Server培训、她是《SQL Server Magazine》的特约编辑...
  • CruiseYoung提供的带详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 该资料是《深入解析SQL Server 2008》的随书源代码 对应的书籍资料见: 深入解析SQL Server 2008(微软SQL ...
  • 7.1 什么并发控制 219 7.2 事务隔离级别 220 7.2.1 READ UNCOMMITTED 221 7.2.2 READ COMMITTED 223 7.2.3 REPEATABLE READ 224 7.2.4 SERIALIZABLE 226 7.2.5 READ ONLY 228 7.3 多版本控制读一致性的...
  • 每种方法都有可取之处,但我相信,真正的学习应该是“参考+实践”。盲目实践会频繁遇到本来可以避免的陷阱和失败,耽于参考又会成为纸上谈兵,无法得到真才实学。 学习Oracle时,很多书和资料都很有参考价值,特别...
  •  本书的一个特点是,凡是作者提到的观点,尽可能地使用一些例子来证明它,这样看起来更说服力一些。  为什么会出现数据库的性能问题  性能问题是最近几年来DBA们越来越关注的一个数据库技术领域,归根结底...
  • 因此,我个人更强调对基础的掌握,而不要迷信有什么技巧或捷径。请相信只要能在一个领域持续上数年,你就在这个领域里能成为专家。  采用这种方式还有一个原因,RAC覆盖知识面广、资料难觅也是众所周知的。时至...
  • 其一、就业面广:全球前100强企业99家在使用ORACLE相关技术,中国政府机构,大中型企事业单位ORACLE技术的工程师岗位。 其二、技术层次深:如果期望进入IT服务或者产品公司(类似毕博、DELL、IBM等),...
  • 10.1 什么并发 426 10.2 查询优化的基础知识 427 10.3 操作系统与硬件因素 428 10.4 事务 429 10.4.1 事务语法 430 10.4.2 已编译的SQL Server代码 437 10.5 SQL Server并发控制 444 10.5.1 锁 445 ...
  • 38.abstract class和interface有什么区别? 答: 声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能...
  • Firebird数据库中文版

    热门讨论 2011-11-29 08:48:43
    Firebird可以工作最常见的硬件环境中,甚至非常差的硬件中,也能很好的工作,当然,硬件的要求依赖于你想做什么,例如 ,你多少个并发用户等等。 有效的平台支持: Firebrid在常见的平台上可运行,如Linux和...
  •  t-sql一直以来是 sql server编程的基础。和传统的 t-sql书籍不同,本书以独特的 “技巧 ”形式来介绍知识点,涵盖了数据处理(增删改、视图、索引、存储过程、触发器等)、数据应用(web服务、 clr集成、分布式...
  • 6.2.4 选择地禁用视图状态 6.2.5 视图状态安全 6.3 在页面间传送信息 6.3.1 查询字符串 6.3.2 跨页回发 6.4 cookie 6.5 会话状态 6.5.1 会话架构 6.5.2 使用会话状态 6.5.3 配置会话状态 ...
  • 用户只需指出“做什么”,而不需指出“怎么做”,对数 据存取路径的选择以及 语句功能的实现均由系统自动完成,与用户编制的应用程序与 具体的机器及关系 的实现细节无关,从而方便了用户,提高了应用程序的开发效率,...
  • 5.6 数据一致性和数据并发性 155 5.6.1 数据库写入器和写前协议 155 5.6.2 SCN 156 5.6.3 撤销管理 156 5.7 备份与恢复体系结构 157 5.7.1 用户管理的备份与恢复 157 5.7.2 RMAN 157 5.7.3 Oracle ...
  • 33、游标怎么使用:游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字,用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理。 必须使用游标的SQL语句...
  • /创建一个关于项目的目标、限定条件和解决方案的概要视图 界面层的异常处理的处理方法//重试/将问题提交给用户/停止界面流程 52、 常见的Caching技术://ASP.NET Cache //数据库缓存 //通过静态变量缓存//...
  • CruiseYoung提供的带详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 数据库系统基础:高级篇(第5版)(讲述数据库系统原理的经典教材) 基本信息 原书名: Fundamentals of Database ...
  • 第1章至第4章是基础篇,包括数据库建模、oracle体系结构、网络结构、备份恢复和使用oem,这些对于刚刚从事dba或者试图转做dba的朋友是必备知识。第5章至第9章是中级篇,专门讨论性能调整,包括性能优化原理、...
  • 但是遇到产品需求,比如过节做个活动,发个购物券之类的需求,由于购物车和商品详情页都有活动,因此会造成组件经常会发生联动。 如何做到各个组件化模块能获取到全局上下文? 组件在lib和app之间进行切换,如何处理...
  • 结构化方法和JSP方法不适合于大型软件的开发。(√) 5. 原型化开发方法包括生成原型和实现原型两个步骤。(×) 6. 面向对象的开发方法包括面向对象的分析、面向对象的设计和面向对象的程序设计。( √) 7. 软件...

空空如也

空空如也

1 2 3 4
收藏数 66
精华内容 26
关键字:

并发视图都有什么