随笔录--并发与并行

一条 SQL 语句在 MySQL 中的执行过程是怎样的?

在 MySQL 中,一条 SQL 语句的执行过程通常可以分为以下几个步骤:

词法分析和语法分析:MySQL 的 SQL 解析器会对输入的 SQL 语句进行词法分析和语法分析,以确定语句的结构和语法是否正确

查询优化:MySQL 会对 SQL 语句进行优化,以确定最优的执行计划。在这个过程中,MySQL 会考虑许多因素,例如索引、表连接、统计信息等,以找到执行查询的最有效方式。

查询执行:在查询优化后,MySQL 开始执行查询,读取和处理数据。在执行过程中,MySQL 会根据查询中所涉及的表和列等信息,从磁盘中读取相应的数据,并进行计算和过滤操作。

结果返回:最后,MySQL 会将查询结果返回给客户端,完成整个查询过程。

需要注意的是,实际的执行过程可能会因为多种因素而不同,例如数据量、硬件配置等。

另外,在并发环境下,多个查询可能会同时进行,需要使用锁和事务等机制来保证数据的一致性和正确性。

第一步:连接器

过程

  1. 建立连接:与客户端进行 TCP 三次握手建立连接;

  2. 校验密码:校验客户端的用户名和密码,如果用户名或密码不对,则会报错;

  3. 权限判断:如果用户名和密码都对了,会读取该用户的权限,然后后面的权限逻辑判断都基于此时读取到的权限;

其他相关问题

如何查看 MySQL 服务被多少个客户端连接了?

  mysql> show processlist;

空闲连接会一直占用着吗?

  • 空闲连接的最大空闲时长,由 wait_timeout 参数控制的

  • 查询命令

mysql> show variables like 'wait_timeout';
  • 手动断开

mysql> kill connection +6;

MySQL 的连接数有限制吗?

MySQL 服务支持的最大连接数由 max_connections 参数控制。

MySQL 的连接也跟 HTTP 一样,有短连接和长连接的概念。

怎么解决长连接占用内存的问题?

  • 定期断开长连接

  • 客户端主动重置连接

第二步:查询缓存

过程

解析出 SQL 语句的第一个字段,看看是什么类型的语句。

如果 SQL 是查询语句(select 语句),MySQL 就会先去查询缓存( Query Cache )里查找缓存数据。

如果查询的语句命中查询缓存,那么就会直接返回 value 给客户端。

如果查询的语句没有命中查询缓存中,那么就要往下继续执行,等执行完后,查询的结果就会被存入查询缓存中。

缺点

  • 更新比较频繁的表,查询缓存的命中率很低

版本变动

  • MySQL 8.0 版本直接将查询缓存删掉了,也就是说 MySQL 8.0 开始,执行一条 SQL 查询语句,不会再走到查询缓存这个阶段了。对于 MySQL 8.0 之前的版本,如果想关闭查询缓存,我们可以通过将参数 query_cache_type 设置成 DEMAND。

这里说的查询缓存是 server 层的,也就是 MySQL 8.0 版本移除的是 server 层的查询缓存,并不是 Innodb 存储引擎中的 buffer pool。

第三步:解析 SQL

过程

  1. 词法分析

  2. 语法分析

  3. 语法不对,解析器就会给报错

注意:表不存在或者字段不存在,并不是在解析器里做的,解析器只负责构建语法树和检查语法,但是不会去查表或者字段存不存在。

第四步:执行 SQL

过程

  1. prepare 阶段,也就是预处理阶段;

  2. optimize 阶段,也就是优化阶段;

  3. execute 阶段,也就是执行阶段;

1 预处理器

检查 SQL 查询语句中的表或者字段是否存在;

将 select * 中的 * 符号,扩展为表上的所有列;

2 优化器

优化器主要负责将 SQL 查询语句的执行方案确定下来

比如在表里面有多个索引的时候,优化器会基于查询成本的考虑,来决定选择使用哪个索引。

要想知道优化器选择了哪个索引,我们可以在查询语句最前面加个 explain 命令

3 执行器

执行器就会和存储引擎交互了,交互是以记录为单位的。

三种方式执行过程

  • 主键索引查询

  • 全表扫描

  • 索引下推(MySQL 5.6 推出的查询优化策略)

特点

  • 执行器查询的过程是一个 while 循环

  • Server 层每从存储引擎读到一条记录就会发送给客户端,之所以客户端显示的时候是直接显示所有记录的,是因为客户端是等查询语句查询完成后,才会显示出所有的记录

总结

执行一条 SQL 查询语句,期间发生了什么?

  • 连接器:建立连接,管理连接、校验用户身份;

  • 查询缓存:查询语句如果命中查询缓存则直接返回,否则继续往下执行。MySQL 8.0 已删除该模块;

  • 解析 SQL,通过解析器对 SQL 查询语句进行词法分析、语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;

  • 执行 SQL:执行 SQL 共有三个阶段:

    • 预处理阶段:检查表或字段是否存在;将 select * 中的 * 符号扩展为表上的所有列。

    • 优化阶段:基于查询成本的考虑,选择查询成本最小的执行计划;

    • 执行阶段:根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端;

随笔录--并发与并行_第1张图片

连接器:客户端首先进行身份验证,如果没通过直接返回。

查询缓存:如果身份验证不通过则查询缓存。缓存这个原理很容易理解,就是把常用的数据放到更高效的地方便于查询。查询缓存也有缺点,就是每当数据更改的时候就要重新设置缓存,在 MySQL8.0 已经将查询缓存去掉。

分析器:分析器先会做“词法分析”。把你输入的内容进行识别,知道字符分别代表什么,有什么含义 然后进行语法分析,如果你的 SQL 语句不符合 MySQL 语法就会收到错误提醒。

优化器:优化器作用就是决定使用哪个索引,决定 join 表的连接顺序。优化器会选择它自己认为最高效的方案,(也代表它不一定能选择出最优的方案)。

执行器:执行器还是先会判断有没有执行的权限,如果有权限的话才会执行下一步。遍历满足条件的行,并把组成的记录集作为结果集返回给客户端。

题目二

什么是 IOC,简单讲一下 Spring IOC 的实现机制?

IOC (Inversion of Control),中文翻译为控制反转,是一种编程思想,它将程序中对象的创建、组装、管理等控制权从代码中转移到框架中,实现了松耦合可重用性的设计。

Spring IOC 是 Spring 框架的一个核心特性,它的实现机制主要包括以下几个步骤:

  • 定义 Bean:在 Spring IOC 中,所有的对象都被看作是 Bean,需要在配置文件或者使用注解的方式中进行定义和配置。

  • 创建 Bean 工厂:在 Spring 中,Bean 工厂负责管理 Bean 的创建、组装和销毁等任务。Spring IOC 容器就是 Bean 工厂的一种实现。

  • 读取配置文件:Spring IOC 容器会读取配置文件或者使用注解的方式来获取 Bean 的定义和配置信息。

  • 创建 Bean 实例:Spring IOC 容器根据配置文件中的信息,使用反射技术来创建 Bean 实例,并将其保存在容器中。

  • 组装 Bean:Spring IOC 容器根据配置文件中的信息,将不同的 Bean 实例组装起来,形成一个完整的应用程序。

  • 注入依赖:Spring IOC 容器根据配置文件中的信息,自动为 Bean 注入依赖的对象或者值。

  • 提供 Bean 实例:应用程序通过 Spring IOC 容器获取需要的 Bean 实例,从而使用其中的方法和属性等。

需要注意的是,Spring IOC 还提供了多种作用域,例如单例、原型、会话、请求等作用域,可以根据具体的需求来选择。

同时,Spring IOC 容器也支持 AOP、事务管理等功能,可以为应用程序提供更完整的服务。

什么是IOC容器,以及IOC的创建过程

基本概念

  • IOC(Inverse Of Controll,控制反转):就是原来代码里面需要自己手动创建的对象,依赖,反转给 Spring 来帮忙实现。我们需要创建一个容器,同时需要一种描述来让容器知道要创建的对象与对象之间的关系。

  • 在 Spring 中 BeanFactory 就是 IOC 容器,在 Spring 初始化的时候,创建容器,并将需要创建对象和对象的关系(xml,注解)通过 BeanDefinitionReader 加载到 BeanDefinition 中并保存在 BeanDefinitionMap 中,然后再由 IOC 容器创建 bean 对象.

两种 bean 的注册方式

  • 方法1:通过 @Bean + @Configuration 的方式直接定义要创建的对象与对象的关系

  • 方式2:通过 @Component 定义类,这种方式必须使用 @ComponetScan 定位 Bean 扫描路径

IOC的创建

  • 在 Spring 中 BeanFactory 就是 IOC 容器,在 Spring 初始化的时候,创建容器,并将需要创建对象和对象的关系(xml,注解)通过 BeanDefinitionReader 加载到 BeanDefinition 中并保存在 BeanDefinitionMap 中,在这个过程中会让 BeanDefinitionProcesser(Bean 的定义信息的后置处理器)进行增强,然后再由 IOC 容器创建 bean 对象.

Bean的生命周期(面试官顺着问题往下问的拓展)

  • bean 的实例化:spring 启动后,会查找和加载需要被 spring 管理的 Bean,并且实例化

  • bean 的属性注入(bean 的初始化):bean 被实例化后将 Bean 的引用和值注入到 bean 的属性中

    • 查看是否调用一些 aware 接口,比如 BeanFactoryAware,BeanFactoryAware,ApplicationContextAware 接口,分别会将 Bean 的名字,BeanFactory 容器实例,以及 Bean 所在的上下文引用传入给 Bean

    • 在初始化之前,会查看是否调用了 BeanPostProcessor 的预初始化方法,可以对 bean 进行扩展

    • 调用 InitializingBean 的 afterPropertiesSet()方法:如果 Bean 实现了 InitializingBean 接口,spring 将调用他们的afterPropertiesSet()方法,类似的,如果 Bean 使用 init-method 生命了初始化方法的话,这个方法也会被调用。

    • 初始化成功之后,会查看是否调用 BeanPostProcessor 的初始化后的方法:如果 Bean 实现了 BeanPostProcessor 接口,spring 就将调用他们的 postprocessAfterInitialization()方法。可以对 bean 进行扩展

  • bean的正常使用:可以被应用程序正常使用了,他们将驻留在上下文中,直到应用的上下文被销毁

  • bean的销毁:调用 DisposableBean 的destory()方法:如果 Bean 实现 DisposableBean 接口,spring 将用他的 destory()方法,相同的,如果 Bean 使用了 destory-method 生命销毁方法,该方法也会被调用。(但由于 bean 也分为单例和多例,单例 bean 会随着 IOC 容器的销毁而销毁,多例的 bean 不会随着 IOC 容器的销毁而销毁,他是通过 JVM 里面的垃圾回收器负责回收)

题目三

并发和并行有什么区别?同步和异步有什么区别?

并发并行是两个计算机领域中经常被提到的概念,它们的含义有所不同。

  • 并发(Concurrency):指的是系统中同时存在多个正在执行的任务,并且这些任务之间可能会相互影响。并发通常用来处理多个任务共享资源的情况。在单核 CPU 上,多个任务会轮流使用 CPU 时间片,表现为看似同时执行的情况,但实际上只有一个任务正在执行。

  • 并行(Parallelism):指的是系统中同时存在多个并且相互独立的任务,并且这些任务可以在多个处理器上同时执行,真正意义上的同时处理多个任务。

  • 同步(Synchronous):指的是程序按照代码的顺序执行,一行一行地执行,直到当前行执行完成后才能继续执行下一行。同步通常会阻塞调用者,直到任务完成才能返回。

  • 异步(Asynchronous):指的是程序在执行某个任务时,不会一直等待任务完成,而是继续执行下一行代码,当任务完成后再进行相应的处理。异步通常不会阻塞调用者,可以提高系统的并发性能

总的来说,"并发"和"并行"是针对多个任务的执行方式,"同步"和"异步"是针对任务执行的阻塞方式和返回方式。在实际应用中,可以根据不同的需求来选择合适的并发和同步方式,以提高系统的性能和可靠性。

随笔录--并发与并行_第2张图片

先介绍并发和并行的区别:

并发:指多个任务同时在执行,但是它们并不是在同一时刻执行,而是通过快速切换上下文来模拟同时执行,优秀的并发可以无限逼近并行,但无法完全做到并行。

例如,在一个 Web 服务器上,多个用户访问同一个网站,服务器会并发地处理这些请求,同时响应每个请求,但是在某一时刻只有一个请求被处理;

并行:指多个任务同时在执行,并且它们真正地同时执行,通常需要多个 CPU 或者多台计算机协同工作。

例如,在一个分布式计算系统中,不同的计算节点可以同时执行不同的任务,并在完成任务后将结果汇总,以加速计算的过程。

接下来是同步和异步:

同步:指调用某个函数或方法时,程序必须等待函数或方法执行完毕才能继续往下执行。

最熟知的便是使用同步机制来控制多个线程之间的访问,如在 Java 中的 synchronized  关键字可以确保同一时间只有一个线程可以访问某个对象的临界区,避免了多个线程同时修改同一个对象导致的数据不一致问题;

异步:指调用某个函数或方法时,程序可以继续往下执行,不必等待函数或方法执行完毕。当函数或方法执行完毕后,程序会得到一个通知或回调来处理结果。在 Java 中可以使用 CompletableFuture 类来异步执行某个任务,从而提高程序的性能。

虽然并发和并行、同步和异步都是计算机领域中常用的概念,但是它们的区别还是很明显的。并发和并行关注的是任务的执行方式,同步和异步则关注的是数据的处理方式

前端

题目一

用 CSS 和 JS 来实现动画分别有哪些优缺点?

用 CSS 和 JS 来实现动画各有其优缺点,具体如下:

使用 CSS 实现动画的优缺点:

优点:

  • 硬件加速:CSS 动画会使用浏览器的 GPU 来进行硬件加速,能够更加流畅和高效地运行。

  • 简单易用:CSS 动画通常只需要几行代码就能实现基本的动画效果,不需要使用 JavaScript 来控制动画。

  • 低资源占用:CSS 动画通常比 JavaScript 动画使用更少的 CPU 和内存资源,因此更适合用于简单的动画效果。

缺点:

  • 限制较大:CSS 动画在实现复杂的动画效果时,受到限制较大,不能像 JavaScript 动画那样自由控制动画的速度、方向等。

  • 兼容性问题:由于不同浏览器对 CSS 动画支持程度不同,因此在实现时需要考虑浏览器兼容性问题。

  • 可维护性差:当动画效果较为复杂时,使用 CSS 实现的代码会变得冗长和难以维护,因此需要进行代码优化和结构设计。

使用 JavaScript 实现动画的优缺点:

优点:

  • 自由控制:JavaScript 动画能够更加自由地控制动画的速度、方向等,可以实现更加复杂的动画效果。

  • 兼容性好:由于 JavaScript 是浏览器通用的语言,因此在实现动画效果时,能够更好地兼容不同的浏览器。

  • 可维护性强:使用 JavaScript 实现动画时,代码结构更加灵活,能够更好地维护和扩展。

缺点:

  • 资源占用高:JavaScript 动画通常需要更多的 CPU 和内存资源,因此在实现动画效果时需要考虑系统资源的消耗问题。

  • 性能问题:JavaScript 动画性能受 JavaScript 引擎的影响,而不是浏览器引擎,因此需要对代码进行优化以提高动画性能。

  • 复杂度高:JavaScript 动画的实现复杂度通常比 CSS 动画高,因此需要对动画效果进行设计和规划。

题目二

JS 中怎么阻止事件冒泡和事件默认行为?

在 JavaScript 中,可以通过以下方式阻止事件的冒泡和默认行为:

阻止事件冒泡:事件冒泡是指当一个子元素触发了某个事件后,事件会一直冒泡到它的父元素,直到到达文档根节点。为了阻止事件冒泡,可以使用事件对象的 stopPropagation() 方法。例如:

document.getElementById("child").addEventListener("click", function(event) {
  // 阻止事件冒泡
  event.stopPropagation();
});

上面的代码中,当子元素被点击时,事件不会继续冒泡到父元素。

阻止事件默认行为:

事件的默认行为是指事件发生时,浏览器会默认执行的一些操作,例如提交表单、打开链接等。为了阻止事件的默认行为,可以使用事件对象的 preventDefault() 方法。例如:

document.getElementById("link").addEventListener("click", function(event) {
  // 阻止链接的默认跳转行为
  event.preventDefault();
});

上面的代码中,当链接被点击时,链接不会跳转到指定的地址。

需要注意的是,阻止事件的冒泡和默认行为可能会影响用户体验,因此需要谨慎使用。在一些场景下,可以使用阻止事件传播的方式来实现事件委托、事件代理等功能。

阻止事件冒泡:事件冒泡是指当一个子元素触发了某个事件后,事件会一直冒泡到它的父元素,直到到达文档根节点。为了阻止事件冒泡,可以使用事件对象的 stopPropagation() 方法。

document.getElementById("child").addEventListener("click", function(event) {
  // 阻止事件冒泡
  event.stopPropagation();
  //IE浏览器(IE11以下)
  event.cancelBubble = true;
});

阻止事件默认行为

事件的默认行为是指事件发生时,浏览器会默认执行的一些操作,例如提交表单、打开链接等。为了阻止事件的默认行为,可以使用事件对象的 preventDefault() 方法。

document.getElementById("link").addEventListener("click", function(event) {
  // 阻止链接的默认跳转行为
  event.preventDefault();
  //IE8及以下
  window.event.returnValue = false;
  //无兼容问题(但不能用于节点直接onclick绑定函数)
  return false;
});

但是请注意:



  阻止默认事件

return false不能适用于直接用onclick绑定的事件,所以当我们使用这种绑定事件方式时,我们还是需要采用e.preventDefault()这个函数。

注:在jQuery中使用return false时,相当于同时使用event.preventDefault和event.stopPropagation,它会阻止冒泡也会阻止默认行为。但是使用原生js写时,return false只会阻止默认行为。

题目三

什么是 webpack?它有什么作用?

Webpack 是一个开源的前端打包工具,它主要用于将多个 JavaScript 文件打包成一个或多个文件,以便在浏览器中加载。Webpack 的核心功能是对模块进行打包,并支持多种资源的加载和打包,如 JavaScript、CSS、图片、字体等。

Webpack 的主要作用包括:

  1. 模块化:Webpack 支持各种模块化规范,包括 ES6、CommonJS、AMD 等,可以将应用程序拆分为多个模块,方便管理和维护。

  2. 资源加载:Webpack 可以处理各种类型的文件,包括 JavaScript、CSS、图片、字体等,可以将这些文件作为模块进行加载和打包。

  3. 代码压缩:Webpack 可以对代码进行压缩和混淆,减小文件体积,提高页面加载速度。

  4. 代码分割:Webpack 可以将应用程序拆分成多个 chunk,从而实现按需加载,减小首屏加载时间。

  5. 模块热替换:Webpack 支持模块热替换,可以在开发过程中快速预览应用程序的变化,提高开发效率。

  6. 优化打包速度:Webpack 可以使用多线程打包、缓存等技术,优化打包速度。

需要注意的是,Webpack 本身只是一个打包工具,对于项目的构建和管理,通常需要结合其他工具和插件一起使用,如 Babel、ESLint、PostCSS、Vue Loader 等。同时,Webpack 的配置也比较复杂,需要一定的学习成本。但是一旦熟练掌握,Webpack 可以大大提高项目的可维护性和开发效率。

Webpack 是一个开源的静态模块打包工具,它可以将多个模块组合成一个文件,同时可以将 Less、Scss、TypeScript、ES6 等代码转换为浏览器可以识别的 JavaScript 代码。

Webpack 最重要的特性之一就是模块化。它允许使用模块化的方式来管理前端代码,可以将应用程序分成多个模块,每个模块包含自己的 JavaScript、CSS、图片等资源。Webpack 会自动解析模块之间的依赖关系,并将它们打包成一个或多个文件,这样可以减少 HTTP 请求的次数,提高页面加载速度。Webpack 还有以下几个重要的作用:

  1. 支持代码拆分和懒加载,可以将代码拆分成多个块,按需加载,提高页面加载速度和性能。

  2. 支持插件和 Loader,可以通过插件和 Loader 实现各种各样的自动化任务,如压缩代码、生成 HTML 文件、图片压缩、样式预处理等。

  3. 支持开发和生产环境的不同配置,可以通过不同的配置文件来满足不同环境下的需求,如开发环境下需要支持热更新,生产环境下需要压缩代码等。

  4. 提供了开发服务器,可以在开发过程中快速构建和预览应用程序,提高开发效率。

Webpack 的工作原理可以概括为以下几个步骤:

  1. 读取入口文件:Webpack 会读取入口文件,根据入口文件和配置信息,构建出一个或多个代码块(Chunk)。

  2. 解析模块依赖:Webpack 会递归解析入口文件和其它模块之间的依赖关系,直到所有依赖关系都被解析出来。

  3. 加载和转换模块:Webpack 会根据不同的 Loader,将模块中的不同类型的文件转换为 JavaScript 模块,如将 Less、Scss、TypeScript、ES6 等代码转换为浏览器可以识别的 JavaScript 代码。

  4. 合并模块:Webpack 会将所有模块合并到一个或多个 Chunk 中,每个 Chunk 中包含了所有相关的模块和代码。

  5. 输出打包结果:Webpack 会根据配置信息,将打包后的代码生成一个或多个文件,如输出到 dist 目录中,生成多个 JavaScript 和 CSS 文件。在实际开发的时候,Webpack 的配置非常灵活,可以根据项目的需求来进行配置,包括入口文件、输出文件、Loader、插件、代码拆分、懒加载、开发服务器等。因此,熟练掌握Webpack可以更好地进行项目开发和维护。

你可能感兴趣的:(随笔录,adb,android,python,开发语言,笔记)