maven生命周期详解

一、构建生命周期基础:

Maven基于构建生命周期的中心概念。

这意味着构建和分发特定工件(项目)的过程被明确定义。

有三个内置的生命周期:

  • 默认(default)
  • 清洁(clean)
  • 站点(site)

在默认(default)的生命周期处理你的项目部署,将清洁(clean)的生命周期处理项目的清理,而网站(site)的生命周期处理你的项目站点文档的创建。

二、构建生命周期是由阶段组成的:

这些构建生命周期中的每一个由构建阶段的不同列表定义,其中构建阶段表示生命周期中的阶段。

例如,默认(default)的生命周期包括以下阶段(注意:这里是简化的阶段,用于生命周期阶段的完整列表,请参阅下方生命周期参考):

验证(validate) - 验证项目是否正确,所有必要的信息可用
编译(compile) - 编译项目的源代码
测试(test) - 使用合适的单元测试框架测试编译的源代码。这些测试不应该要求代码被打包或部署
打包(package) - 采用编译的代码,并以其可分配格式(如JAR)进行打包。
验证(verify) - 对集成测试的结果执行任何检查,以确保满足质量标准
安装(install) - 将软件包安装到本地存储库中,用作本地其他项目的依赖项
部署(deploy) - 在构建环境中完成,将最终的包复制到远程存储库以与其他开发人员和项目共享。

这些生命周期阶段(以及此处未显示的其他生命周期阶段)依次执行,以完成默认生命周期。给定上述生命周期阶段,这意味着当使用默认生命周期时,Maven将首先验证项目,然后尝试编译源代码,运行这些源代码,打包二进制文件(例如jar),运行集成测试软件包,验证集成测试,将验证的软件包安装到本地存储库,然后将安装的软件包部署到远程存储库。

换句话说,在生命周期里面阶段是连续的,在不出错的前提下,比如执行打包(package)时就一定是执行了测试(test)之后再执行。

三、生命周期参考:

以下列出了默认(default),清洁(clean)和站点(site)生命周期的所有构建阶段,它们按照指定的顺序执行的顺序执行。

清洁(clean):生命周期
预清洁(pre-clean): 执行实际项目清理之前所需的流程
清洁(clean): 删除以前构建生成的所有文件
后清洁(post-clean): 执行完成项目清理所需的流程

默认(default)生命周期

验证(validate):验证项目是正确的,所有必要的信息可用。
初始化(initialize): 初始化构建状态,例如设置属性或创建目录。
产生来源(generate-sources): 生成包含在编译中的任何源代码。
流程源(process-sources): 处理源代码,例如过滤任何值。
生成资源(generate-resources):生成包含在包中的资源。
流程资源(process-resources): 将资源复制并处理到目标目录中,准备打包。
编译(compile): 编译项目的源代码。
工艺类(process-classes): 从编译后处理生成的文件,例如对Java类进行字节码增强。
生成测试来源(generate-test-sources): 生成包含在编译中的任何测试源代码。
流程测试来源(process-test-sources): 处理测试源代码,例如过滤任何值。
生成测试资源(generate-test-resources):创建测试资源。
流程测试资源(process-test-resources):将资源复制并处理到测试目标目录中。
测试编译(test-compile):将测试源代码编译到测试目标目录中
流程检验类(process-test-classes):从测试编译中处理生成的文件,例如对Java类进行字节码增强。对于Maven 2.0.5及以上版本。
测试(test): 使用合适的单元测试框架运行测试。这些测试不应该要求代码被打包或部署。
制备包(prepare-package):在实际包装之前,执行必要的准备包装的操作。这通常会导致打包的处理版本的包。(Maven 2.1及以上)
打包(package):采取编译的代码,并以其可分发的格式(如JAR)进行打包。
预集成测试(pre-integration-test):在执行集成测试之前执行所需的操作。这可能涉及诸如设置所需环境等。
集成测试(integration-test):如果需要,可以将该包过程并部署到可以运行集成测试的环境中。
整合后的测试(post-integration-test):执行集成测试后执行所需的操作。这可能包括清理环境。
校验(verify): 运行任何检查以验证包装是否有效并符合质量标准。
安装(install):将软件包安装到本地存储库中,以作为本地其他项目的依赖关系。
部署(deploy):在集成或发布环境中完成,将最终软件包复制到远程存储库,以与其他开发人员和项目共享。

站点(site)生命周期
预网站(pre-site): 在实际的项目现场生成之前执行所需的进程
网站(site):生成项目的站点文档
后网站(post-site):执行完成站点生成所需的进程,并准备站点部署
网站部署(site-deploy): 将生成的站点文档部署到指定的Web服务器

四、生命周期阶段在命令行中的调用

在开发环境中,使用以下调用构建并将工件安装到本地存储库中。

mvn install

此命令在执行安装之前按顺序(验证(validate),编译(compile),打包(package)等)执行每个默认生命周期阶段。在这种情况下,您只需要调用最后一个构建阶段来执行,安装(install)。

在构建环境中,使用以下调用将工件清理地构建并部署到共享存储库中。

mvn clean deploy

相同的命令可以在多模块场景(即具有一个或多个子项目的项目)中使用。Maven遍历每个子项目并执行清洁(clean),然后执行部署(deploy)(包括所有之前的构建阶段步骤)。

注意:在我们开发阶段,有一些生命周期的阶段,比如验证(validate)这些,基本很少用到。只要使用关键的几个基本能满足需求。

五、通常情况在命令行只调用某些特定的阶段

以连字符(pre-,post-或process-*)命名的阶段通常不会从命令行直接调用。这些阶段对构建进行排序,生成在构建之外无用的中间结果。在调用集成测试的情况下,环境可能处于挂起状态。

诸如Jacoco和执行容器插件(如Tomcat,Cargo和Docker)的代码覆盖工具将目标绑定到预集成测试(pre-integration-test)阶段以准备集成测试容器环境。这些插件还将目标绑定到整合后的测试(post-integration-test)阶段,以收集覆盖统计信息或停止集成测试容器。

故障安全和代码覆盖插件将目标绑定到集成测试(integration-test)和验证(verify)阶段。最终结果是在验证(verify)阶段后可以使用测试和覆盖率报告。如果从命令行调用集成测试(integration-test)阶段,则不会生成任何报告。整合测试容器环境处于更糟糕的悬挂状态; Tomcat网络服务器或Docker实例将保持运行,并且Maven本身甚至可能不会终止。

提示:再次明确,在生命周期的阶段上,只有特定的几个阶段对于构建有意义。一些无用的阶段只起到了中间阶段的作用,换句话说只是一个过客。

六、调用由插件目标(Plugin Goals)组成的构建阶段

然而,即使构建阶段负责构建生命周期中的特定步骤,其执行这些职责的方式可能会有所不同。这是通过声明绑定到这些构建阶段的插件目标来完成的。

插件目标代表一个特定的任务(比构建阶段更精细),有助于项目的构建和管理。它可能被限制在零个或多个构建阶段。不限于任何构建阶段的目标可以通过直接调用在构建生命周期之外执行。执行顺序取决于调用目标和构建阶段的顺序。例如,考虑下面的命令。该清洁(clean)和打包(package)是建立阶段,而dependency:copy-dependencies是(一个插件)的目标。

mvn clean dependency:copy-dependencies package

如果要执行此操作,则将首先执行清洁(clean)阶段(意味着它将运行清洁生命周期的所有先前阶段以及清洁(clean)阶段本身),然后执行dependency:copy-dependencies目标,然后才能最终执行打包(package)阶段(以及默认生命周期的所有之前的构建阶段)。

而且,如果一个目标被绑定到一个或者多个构建阶段,那么在所有这些阶段都会调用这个目标。

此外,构建阶段也可以有零个或多个目标。如果构建阶段没有绑定目标,则构建阶段将不会执行。但是,如果它有一个或多个目标,它将执行所有这些目标(注意:在Maven 2.0.5及更高版本中,绑定到阶段的多个目标的执行顺序与POM中声明的顺序相同,但不支持同一插件的多个实例,同一个插件的多个实例被分组一起执行要在Maven 2.0.11及以上)。

提示:其实简单点理解就是说dependency是一个插件,在我们执行生命周期阶段时,可以调用这个插件做特定的事,其中copy-dependencies就是特定的事,那么上面的命令可以这么理解,在执行clean后就会执行dependecy这个插件,最后再执行package;如果dependecy这个插件执行过程异常,package就不会执行到。还有就是一个命令可以有多个插件,也可以一个插件都没有。

提示2:dependency:copy-dependencies这样的形式最标准的官方说法:左边dependency为插件,右边copy-dependencies为插件的目标,通常还有一种说法就是命令行参数。

七、使用构建生命周期来设置项目

构建生命周期足够简单,但是当您为项目配置Maven构建时,您如何将任务分配到每个构建阶段?

打包

第一个也是最常见的方法是通过同样命名的POM元素为您的项目设置打包。一些有效的打包值是jar,war,ear和pom。如果没有指定包装值,它将默认为jar。

每个不同类型的打包都包含要绑定到特定阶段的目标列表。例如,jar包将绑定以下目标来构建默认生命周期的阶段。
流程资源(process-resources): resources:resources
**编译(compile):**compiler:compile
流程测试资源(process-test-resources): resources:testResources
测试编译(test-compile): compiler:testCompile
测试(test): surefire:test
打包(package) : jar:jar
安装(install) : install:install
部署(deploy): deploy:deploy

这几乎是一个标准的绑定 ; 然而,一些包装处理它们不同。例如,纯粹的元数据(包装值是pom)的项目只将目标绑定到安装(install)和部署(deploy)阶段(对于某些包装类型的目标到构建阶段绑定的完整列表,请参阅生命周期参考)。

请注意,对于某些可用的打包类型,您可能还需要在POM的部分中包含一个特定的插件,并为该插件指定true。需要这种插件的一个例子是Plexus插件,它提供plexus-application和plexus-service打包。

提示:这里简单点可以说不同的包对应不同的生命周期阶段,比如jar包和war包的区别可以参考:https://maven.apache.org/ref/3.5.0/maven-core/default-bindings.html

上方列表可以这么理解,左边是简化的命令,右侧是详细的插件加目标(命令行参数)的形式;切记,Maven都是以插件的形式存在的,包括生命周期的阶段同样也是一个个不同的插件组成,比如上面的编译(compile)就是由compiler插件提供,其中compile为这个插件的目标,也可以说是插件的命令行参数。

插件

将目标添加到阶段的第二种方法是在项目中配置插件。插件是为Maven提供目标的工件。此外,插件可以具有一个或多个目标,其中每个目标代表该插件的能力。例如,编译器(compiler)插件有两个目标:compile和testCompile。前者编译主代码的源代码,后者编译测试代码的源代码。

如稍后部分所示,插件可以包含指示将目标绑定到的生命周期阶段的信息。请注意,自己添加插件是不够的,您还必须指定要作为构建的一部分运行的目标。

配置的目标将被添加到已经从选定的打包绑定到生命周期的目标。如果将多个目标绑定到特定阶段,则使用的顺序是首先执行来自打包装的顺序,然后执行在POM中配置。请注意,您可以使用元素来获得对特定目标的顺序更多的控制。

例如,Modello插件默认将目标modello:java绑定到generate-sources阶段(注意:modello:java目标生成Java源代码)。因此,要使用Modello插件,并从模型生成源代码并将其合并到构建中,您可以在的部分中将以下内容添加到POM中:

 <plugin>
   <groupId>org.codehaus.modello</groupId>
   <artifactId>modello-maven-plugin</artifactId>
   <version>1.8.1</version>
   <executions>
     <execution>
       <configuration>
         <models>
           <model>src/main/mdo/maven.mdo</model>
         </models>
         <version>4.0.0</version>
       </configuration>
       <goals>
         <goal>java</goal>
       </goals>
     </execution>
   </executions>
 </plugin>

提示:这里所说的更直白的意思就是Modello插件有默认的生命周期阶段,而无需自己手动配置这些阶段。

你可能会想知道为什么这个元素在那里。这样,如果需要,您可以使用不同的配置多次运行相同的目标。还可以使用单独的执行标识,以便在继承或应用配置文件期间,您可以控制目标配置是合并还是转为额外的执行。

当给出与特定阶段匹配的多个执行时,它们按照POM中指定的顺序执行,继承的执行首先运行。

现在,在modello:java的情况下,它只在generate-sources阶段才有意义。但是一些目标可以在一个以上的阶段中使用,也可能没有合理的默认。对于那些,您可以自己指定阶段。例如,假设您有一个目标display:time当前时间到命令行的时间,并希望它在process-test-resources阶段运行以指示测试何时开始。这将被配置如下:

 <plugin>
   <groupId>com.mycompany.example</groupId>
   <artifactId>display-maven-plugin</artifactId>
   <version>1.0</version>
   <executions>
     <execution>
       <phase>process-test-resources</phase>
       <goals>
         <goal>time</goal>
       </goals>
     </execution>
   </executions>
 </plugin>

提示:这里已经是换了一个插件了,与上面的插件不同的是,可以在中指定生命周期阶段。可以说是两个做了一个明显对比。

八、内置生命周期的绑定

根据 https://maven.apache.org/ref/3.5.0/maven-core/default-bindings.html

提供的不同类型对应不同的生命周期阶段

默认情况下,某些阶段的目标与之相关。对于默认生命周期,这些绑定取决于包装值。以下是一些目标到构建阶段的绑定。

清洁生命周期绑定
清洁(clean): clean:clean

默认生命周期绑定-打包ejb/ejb3/jar/par/rar/war
流程资源(process-resources) : resources:resources
编译(compile): compiler:compile
流程测试资源(process-test-resources): resources:testResources
测试编译(test-compile) : compiler:testCompile
测试(test): surefire:test
打包(package): ejb:ejb or ejb3:ejb3 or jar:jar or par:par or rar:rar or war:war
安装(install) : install:install
部署(deploy) : deploy:deploy

默认生命周期绑定-打包ear
生成资源(generate-resources): ear:generate-application-xml
流程资源(process-resources): resources:resources
打包(package): ear:ear
安装(install) : install:install
部署(deploy) : deploy:deploy

默认生命周期绑定-打包maven-plugin
生成资源(generate-resources): plugin:descriptor
流程资源(process-resources): resources:resources
编译(compile) : compiler:compile
流程测试资源(process-test-resources): resources:testResources
测试编译(test-compile) : compiler:testCompile
测试(test): surefire:test
打包(package): jar:jar and plugin:addPluginArtifactMetadata
安装(install): install:install
部署(deploy): deploy:deploy

默认生命周期绑定-包装pom
打包(package): site:attach-descriptor
安装(install) : install:install
部署(deploy) : deploy:deploy

网站生命周期绑定
网站(site): site:site
网站部署(site-deploy): site:deploy

官方资料:https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

转自:https://blog.csdn.net/hp_yangpeng/article/details/80800041

Spring boot配置属性[server]

server配置

  • server.address
    指定server绑定的地址
  • server.compression.enabled
    是否开启压缩,默认为false.
  • server.compression.excluded-user-agents
    指定不压缩的user-agent,多个以逗号分隔,默认值为:text/html,text/xml,text/plain,text/css
  • server.compression.mime-types
    指定要压缩的MIME type,多个以逗号分隔.
  • server.compression.min-response-size
    执行压缩的阈值,默认为2048
  • server.context-parameters.[param name]
    设置servlet context 参数
  • server.context-path
    设定应用的context-path.
  • server.display-name
    设定应用的展示名称,默认: application
  • server.jsp-servlet.class-name
    设定编译JSP用的servlet,默认: org.apache.jasper

.servlet.JspServlet)

  • server.jsp-servlet.init-parameters.[param name]
    设置JSP servlet 初始化参数.
  • server.jsp-servlet.registered
    设定JSP servlet是否注册到内嵌的servlet容器,默认true
  • server.port
    设定http监听端口
  • server.servlet-path
    设定dispatcher servlet的监听路径,默认为: /

cookie、session配置

  • server.session.cookie.comment
    指定session cookie的comment
  • server.session.cookie.domain
    指定session cookie的domain
  • server.session.cookie.http-only
    是否开启HttpOnly.
  • server.session.cookie.max-age
    设定session cookie的最大age.
  • server.session.cookie.name
    设定Session cookie 的名称.
  • server.session.cookie.path
    设定session cookie的路径.
  • server.session.cookie.secure
    设定session cookie的“Secure” flag.
  • server.session.persistent
    重启时是否持久化session,默认false
  • server.session.timeout
    session的超时时间
  • server.session.tracking-modes
    设定Session的追踪模式(cookie, url, ssl).

ssl配置

  • server.ssl.ciphers
    是否支持SSL ciphers.
  • server.ssl.client-auth
    设定client authentication是wanted 还是 needed.
  • server.ssl.enabled
    是否开启ssl,默认: true
  • server.ssl.key-alias
    设定key store中key的别名.
  • server.ssl.key-password
    访问key store中key的密码.
  • server.ssl.key-store
    设定持有SSL certificate的key store的路径,通常是一个.jks文件.
  • server.ssl.key-store-password
    设定访问key store的密码.
  • server.ssl.key-store-provider
    设定key store的提供者.
  • server.ssl.key-store-type
    设定key store的类型.
  • server.ssl.protocol
    使用的SSL协议,默认: TLS
  • server.ssl.trust-store
    持有SSL certificates的Trust store.
  • server.ssl.trust-store-password
    访问trust store的密码.
  • server.ssl.trust-store-provider
    设定trust store的提供者.
  • server.ssl.trust-store-type
    指定trust store的类型.

tomcat

  • server.tomcat.access-log-enabled
    是否开启access log ,默认: false)
  • server.tomcat.access-log-pattern
    设定access logs的格式,默认: common
  • server.tomcat.accesslog.directory
    设定log的目录,默认: logs
  • server.tomcat.accesslog.enabled
    是否开启access log,默认: false
  • server.tomcat.accesslog.pattern
    设定access logs的格式,默认: common
  • server.tomcat.accesslog.prefix
    设定Log 文件的前缀,默认: access_log
  • server.tomcat.accesslog.suffix
    设定Log 文件的后缀,默认: .log
  • server.tomcat.background-processor-delay
    后台线程方法的Delay大小: 30
  • server.tomcat.basedir
    设定Tomcat的base 目录,如果没有指定则使用临时目录.
  • server.tomcat.internal-proxies
    设定信任的正则表达式,默认:“10\.\d{1,3}\.\d{1,3}\.\d{1,3}| 192\.168\.\d{1,3}\.\d{1,3}| 169\.254\.\d{1,3}\.\d{1,3}| 127\.\d{1,3}\.\d{1,3}\.\d{1,3}| 172\.1[6-9]{1}\.\d{1,3}\.\d{1,3}| 172\.2[0-9]{1}\.\d{1,3}\.\d{1,3}|172\.3[0-1]{1}\.\d{1,3}\.\d{1,3}”
  • server.tomcat.max-http-header-size
    设定http header的最小值,默认: 0
  • server.tomcat.max-threads
    设定tomcat的最大工作线程数,默认为: 0
  • server.tomcat.port-header
    设定http header使用的,用来覆盖原来port的value.
  • server.tomcat.protocol-header
    设定Header包含的协议,通常是 X-Forwarded-Proto,如果remoteIpHeader有值,则将设置为RemoteIpValve.
  • server.tomcat.protocol-header-https-value
    设定使用SSL的header的值,默认https.
  • server.tomcat.remote-ip-header
    设定remote IP的header,如果remoteIpHeader有值,则设置为RemoteIpValve
  • server.tomcat.uri-encoding
    设定URI的解码字符集.

undertow

    • server.undertow.access-log-dir
      设定Undertow access log 的目录,默认: logs
    • server.undertow.access-log-enabled
      是否开启access log,默认: false
    • server.undertow.access-log-pattern
      设定access logs的格式,默认: common
    • server.undertow.accesslog.dir
      设定access log 的目录.
    • server.undertow.buffer-size
      设定buffer的大小.
    • server.undertow.buffers-per-region
      设定每个region的buffer数
    • server.undertow.direct-buffers
      设定堆外内存
    • server.undertow.io-threads
      设定I/O线程数.
    • server.undertow.worker-threads
      设定工作线程数

HTTP状态码(记录)

HTTP状态码总的分为五类:

1开头:信息状态码

2开头:成功状态码

3开头:重定向状态码

4开头:客户端错误状态码

5开头:服务端错误状态码

 1XX:信息状态码

状态码 含义 描述
100 继续 初始的请求已经接受,请客户端继续发送剩余部分
101 切换协议 请求这要求服务器切换协议,服务器已确定切换

 2XX:成功状态码

状态码 含义 描述
200 成功 服务器已成功处理了请求
201 已创建 请求成功并且服务器创建了新的资源
202 已接受 服务器已接受请求,但尚未处理
203 非授权信息 服务器已成功处理请求,但返回的信息可能来自另一个来源
204 无内容 服务器成功处理了请求,但没有返回任何内容
205 重置内容 服务器处理成功,用户终端应重置文档视图
206 部分内容 服务器成功处理了部分GET请求

3XX:重定向状态码

状态码 含义 描述
300 多种选择 针对请求,服务器可执行多种操作
301 永久移动 请求的页面已永久跳转到新的url
302 临时移动 服务器目前从不同位置的网页响应请求,但请求仍继续使用原有位置来进行以后的请求
303 查看其他位置 请求者应当对不同的位置使用单独的GET请求来检索响应时,服务器返回此代码
304 未修改 自从上次请求后,请求的网页未修改过
305 使用代理 请求者只能使用代理访问请求的网页
307 临时重定向 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求

4XX:客户端错误状态码

状态码 含义 描述
400 错误请求 服务器不理解请求的语法
401 未授权 请求要求用户的身份演验证
403 禁止 服务器拒绝请求
404 未找到 服务器找不到请求的页面
405 方法禁用 禁用请求中指定的方法
406 不接受 无法使用请求的内容特性响应请求的页面
407 需要代理授权 请求需要代理的身份认证
408 请求超时 服务器等候请求时发生超时
409 冲突 服务器在完成请求时发生冲突
410 已删除 客户端请求的资源已经不存在
411 需要有效长度 服务器不接受不含有效长度表头字段的请求
412 未满足前提条件 服务器未满足请求者在请求中设置的其中一个前提条件
413 请求实体过大 由于请求实体过大,服务器无法处理,因此拒绝请求
414 请求url过长 请求的url过长,服务器无法处理
415 不支持格式 服务器无法处理请求中附带媒体格式
416 范围无效 客户端请求的范围无效
417 未满足期望 服务器无法满足请求表头字段要求

 

5XX:服务端错误状态码

状态码 含义 描述
500 服务器错误 服务器内部错误,无法完成请求
501 尚未实施 服务器不具备完成请求的功能
502 错误网关 服务器作为网关或代理出现错误
503 服务不可用 服务器目前无法使用
504 网关超时 网关或代理服务器,未及时获取请求
505 不支持版本 服务器不支持请求中使用的HTTP协议版本

MySQL8.0新特性

1. 默认字符集由latin1变为utf8mb4

在8.0版本之前,默认字符集为latin1,utf8指向的是utf8mb3,8.0版本默认字符集为utf8mb4,utf8默认指向的也是utf8mb4。
注:在Percona Server 8.0.15版本上测试,utf8仍然指向的是utf8mb3,与官方文档有出入。

Warning | 3719 | 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous. |

2. MyISAM系统表全部换成InnoDB表

系统表全部换成事务型的innodb表,默认的MySQL实例将不包含任何MyISAM表,除非手动创建MyISAM表。

# MySQL 5.7
mysql> select distinct(ENGINE) from information_schema.tables;
+--------------------+
| ENGINE             |
+--------------------+
| MEMORY             |
| InnoDB             |
| MyISAM             |
| CSV                |
| PERFORMANCE_SCHEMA |
| NULL               |
+--------------------+
6 rows in set (0.00 sec)
 
# MySQL 8.0
mysql> select distinct(ENGINE) from information_schema.tables;
+--------------------+
| ENGINE             |
+--------------------+
| NULL               |
| InnoDB             |
| CSV                |
| PERFORMANCE_SCHEMA |
+--------------------+
4 rows in set (0.00 sec)

3. 自增变量持久化

在8.0之前的版本,自增主键AUTO_INCREMENT的值如果大于max(primary key)+1,在MySQL重启后,会重置AUTO_INCREMENT=max(primary key)+1,这种现象在某些情况下会导致业务主键冲突或者其他难以发现的问题。自增主键重启重置的问题很早就被发现(https://bugs.mysql.com/bug.php?id=199),一直到8.0才被解决,8.0版本将会对AUTO_INCREMENT值进行持久化,MySQL重启后,该值将不会改变。

4. DDL原子化

InnoDB表的DDL支持事务完整性,要么成功要么回滚,将DDL操作回滚日志写入到data dictionary 数据字典表 mysql.innodb_ddl_log 中用于回滚操作,该表是隐藏的表,通过show tables无法看到。通过设置参数,可将ddl操作日志打印输出到mysql错误日志中。

mysql> set global log_error_verbosity=3;
mysql> set global innodb_print_ddl_logs=1;
mysql> create table t1(c int) engine=innodb;
 
# MySQL错误日志:
2018-06-26T11:25:25.817245+08:00 44 [Note] [MY-012473] [InnoDB] InnoDB: DDL log insert : [DDL record: DELETE SPACE, id=41, thread_id=44, space_id=6, old_file_path=./db/t1.ibd]
2018-06-26T11:25:25.817369+08:00 44 [Note] [MY-012478] [InnoDB] InnoDB: DDL log delete : by id 41
2018-06-26T11:25:25.819753+08:00 44 [Note] [MY-012477] [InnoDB] InnoDB: DDL log insert : [DDL record: REMOVE CACHE, id=42, thread_id=44, table_id=1063, new_file_path=db/t1]
2018-06-26T11:25:25.819796+08:00 44 [Note] [MY-012478] [InnoDB] InnoDB: DDL log delete : by id 42
2018-06-26T11:25:25.820556+08:00 44 [Note] [MY-012472] [InnoDB] InnoDB: DDL log insert : [DDL record: FREE, id=43, thread_id=44, space_id=6, index_id=140, page_no=4]
2018-06-26T11:25:25.820594+08:00 44 [Note] [MY-012478] [InnoDB] InnoDB: DDL log delete : by id 43
2018-06-26T11:25:25.825743+08:00 44 [Note] [MY-012485] [InnoDB] InnoDB: DDL log post ddl : begin for thread id : 44
2018-06-26T11:25:25.825784+08:00 44 [Note] [MY-012486] [InnoDB] InnoDB: DDL log post ddl : end for thread id : 44

来看另外一个例子,库里只有一个t1表,drop table t1,t2; 试图删除t1,t2两张表,在5.7中,执行报错,但是t1表被删除,在8.0中执行报错,但是t1表没有被删除,证明了8.0 DDL操作的原子性,要么全部成功,要么回滚。

# MySQL 5.7
mysql> show tables;
+---------------+
| Tables_in_db |
+---------------+
| t1            |
+---------------+
1 row in set (0.00 sec)
mysql> drop table t1, t2;
ERROR 1051 (42S02): Unknown table 'db.t2'
mysql> show tables;
Empty set (0.00 sec)
 
# MySQL 8.0
mysql> show tables;
+---------------+
| Tables_in_db |
+---------------+
| t1            |
+---------------+
1 row in set (0.00 sec)
mysql> drop table t1, t2;
ERROR 1051 (42S02): Unknown table 'db.t2'
mysql> show tables;
+---------------+
| Tables_in_db |
+---------------+
| t1            |
+---------------+
1 row in set (0.00 sec)

5. 参数修改持久化

MySQL 8.0版本支持在线修改全局参数并持久化,通过加上PERSIST关键字,可以将修改的参数持久化到新的配置文件(mysqld-auto.cnf)中,重启MySQL时,可以从该配置文件获取到最新的配置参数。
例如执行:
set PERSIST expire_logs_days=10 ;
系统会在数据目录下生成一个包含json格式的 mysqld-auto.cnf 的文件,格式化后如下所示,当 my.cnf 和 mysqld-auto.cnf 同时存在时,后者具有更高优先级。

{
    "Version": 1,
    "mysql_server": {
        "expire_logs_days": {
            "Value": "10",
            "Metadata": {
                "Timestamp": 1529657078851627,
                "User": "root",
                "Host": "localhost"
            }
        }
    }
}

6. 新增降序索引

MySQL在语法上很早就已经支持降序索引,但实际上创建的仍然是升序索引,如下MySQL 5.7 所示,c2字段降序,但是从show create table看c2仍然是升序。8.0可以看到,c2字段降序。

# MySQL 5.7
mysql> create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));
Query OK, 0 rows affected (0.03 sec)
mysql> show create table t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  KEY `idx_c1_c2` (`c1`,`c2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
 
# MySQL 8.0
mysql> create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));
Query OK, 0 rows affected (0.06 sec)
mysql> show create table t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  KEY `idx_c1_c2` (`c1`,`c2` DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC
1 row in set (0.00 sec)

再来看看降序索引在执行计划中的表现,在t1表插入10万条随机数据,查看select * from t1 order by c1 , c2 desc;的执行计划。从执行计划上可以看出,5.7的扫描数100113远远大于8.0的5行,并且使用了filesort。

DELIMITER ;;
CREATE PROCEDURE test_insert ()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i<100000
DO
insert into t1 select rand()*100000, rand()*100000;
SET i=i+1;
END WHILE ;
commit;
END;;
DELIMITER ;
CALL test_insert();
 
# MySQL 5.7
mysql> explain select * from t1 order by c1 , c2 desc limit 5;
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows   | filtered | Extra                       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | idx_c1_c2 | 10      | NULL | 100113 |   100.00 | Using index; Using filesort |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)
 
# MySQL 8.0
mysql> explain select * from t1 order by c1 , c2 desc limit 5;
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | idx_c1_c2 | 10      | NULL |    5 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

降序索引只是对查询中特定的排序顺序有效,如果使用不当,反而查询效率更低,比如上述查询排序条件改为 order by c1 desc, c2 desc,这种情况下,5.7的执行计划要明显好于8.0的,如下:

# MySQL 5.7
mysql> explain select * from t1  order by c1 desc , c2 desc limit 5;
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | idx_c1_c2 | 10      | NULL |    5 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)
 
# MySQL 8.0
mysql> explain select * from t1 order by c1 desc , c2 desc limit 5;
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows   | filtered | Extra                       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | idx_c1_c2 | 10      | NULL | 100429 |   100.00 | Using index; Using filesort |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+--------+----------+-----------------------------+
1 row in set, 1 warning (0.01 sec)

7. group by 不再隐式排序

mysql 8.0 对于group by 字段不再隐式排序,如需要排序,必须显式加上order by 子句。

# 表结构
mysql> show create table tb1\G
*************************** 1. row ***************************
       Table: tb1
Create Table: CREATE TABLE `tb1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `group_own` int(11) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC
1 row in set (0.00 sec)
 
# 表数据
mysql> select * from tb1;
+----+------+-----------+
| id | name | group_own |
+----+------+-----------+
|  1 | 1    |         0 |
|  2 | 2    |         0 |
|  3 | 3    |         0 |
|  4 | 4    |         0 |
|  5 | 5    |         5 |
|  8 | 8    |         1 |
| 10 | 10   |         5 |
+----+------+-----------+
7 rows in set (0.00 sec)
 
# MySQL 5.7
mysql> select count(id), group_own from tb1 group by group_own;
+-----------+-----------+
| count(id) | group_own |
+-----------+-----------+
|         4 |         0 |
|         1 |         1 |
|         2 |         5 |
+-----------+-----------+
3 rows in set (0.00 sec)
 
# MySQL 8.0.11
mysql> select count(id), group_own from tb1 group by group_own;
+-----------+-----------+
| count(id) | group_own |
+-----------+-----------+
|         4 |         0 |
|         2 |         5 |
|         1 |         1 |
+-----------+-----------+
3 rows in set (0.00 sec)
 
# MySQL 8.0.11显式地加上order by进行排序
mysql> select count(id), group_own from tb1 group by group_own order by group_own;
+-----------+-----------+
| count(id) | group_own |
+-----------+-----------+
|         4 |         0 |
|         1 |         1 |
|         2 |         5 |
+-----------+-----------+
3 rows in set (0.00 sec)

8. JSON特性增强

MySQL 8 大幅改进了对 JSON 的支持,添加了基于路径查询参数从 JSON 字段中抽取数据的 JSON_EXTRACT() 函数,以及用于将数据分别组合到 JSON 数组和对象中的 JSON_ARRAYAGG() 和 JSON_OBJECTAGG() 聚合函数。

在主从复制中,新增参数 binlog_row_value_options,控制JSON数据的传输方式,允许对于Json类型部分修改,在binlog中只记录修改的部分,减少json大数据在只有少量修改的情况下,对资源的占用。

9. redo & undo 日志加密

增加以下两个参数,用于控制redo、undo日志的加密。
innodb_undo_log_encrypt
innodb_undo_log_encrypt

10. innodb select for update跳过锁等待

select … for update,select … for share(8.0新增语法) 添加 NOWAIT、SKIP LOCKED语法,跳过锁等待,或者跳过锁定。
在5.7及之前的版本,select…for update,如果获取不到锁,会一直等待,直到innodb_lock_wait_timeout超时。

在8.0版本,通过添加nowait,skip locked语法,能够立即返回。如果查询的行已经加锁,那么nowait会立即报错返回,而skip locked也会立即返回,只是返回的结果中不包含被锁定的行。

# session1:
mysql> begin;
mysql> select * from t1 where c1 = 2 for update;
+------+-------+
| c1   | c2    |
+------+-------+
|    2 | 60530 |
|    2 | 24678 |
+------+-------+
2 rows in set (0.00 sec)
 
# session2:
mysql> select * from t1 where c1 = 2 for update nowait;
ERROR 3572 (HY000): Statement aborted because lock(s) could not be acquired  immediately and NOWAIT is set.
mysql> select * from t1 where c1 = 2 for update skip locked;
Empty set (0.00 sec)

11. 增加SET_VAR语法

在sql语法中增加SET_VAR语法,动态调整部分参数,有利于提升语句性能。

  • select /*+ SET_VAR(sort_buffer_size = 16M) */ id from test order id ;
  • insert /*+ SET_VAR(foreign_key_checks=OFF) */ into test(name) values(1);

12. 支持不可见索引

使用INVISIBLE关键字在创建表或者进行表变更中设置索引是否可见。索引不可见只是在查询时优化器不使用该索引,即使使用force index,优化器也不会使用该索引,同时优化器也不会报索引不存在的错误,因为索引仍然真实存在,在必要时,也可以快速的恢复成可见。

# 创建不可见索引
create table t2(c1 int,c2 int,index idx_c1_c2(c1,c2 desc) invisible );
# 索引可见
alter table t2 alter index idx_c1_c2 visible;
# 索引不可见
alter table t2 alter index idx_c1_c2 invisible;

13. 支持直方图

优化器会利用column_statistics的数据,判断字段的值的分布,得到更准确的执行计划。

可以使用 ANALYZE TABLE table_name [UPDATE HISTOGRAM on col_name with N BUCKETS |DROP HISTOGRAM ON clo_name] 来收集或者删除直方图信息。

直方图统计了表中某些字段的数据分布情况,为优化选择高效的执行计划提供参考,直方图与索引有着本质的区别,维护一个索引有代价。每一次的insert、update、delete都会需要更新索引,会对性能有一定的影响。而直方图一次创建永不更新,除非明确去更新它。所以不会影响insert、update、delete的性能。

# 添加/更新直方图
mysql> analyze table t1 update histogram on c1, c2 with 32 buckets;
+--------+-----------+----------+-----------------------------------------------+
| Table  | Op        | Msg_type | Msg_text                                      |
+--------+-----------+----------+-----------------------------------------------+
| db.t1 | histogram | status   | Histogram statistics created for column 'c1'. |
| db.t1 | histogram | status   | Histogram statistics created for column 'c2'. |
+--------+-----------+----------+-----------------------------------------------+
2 rows in set (2.57 sec)
 
# 删除直方图
mysql> analyze table t1 drop histogram on c1, c2;
+--------+-----------+----------+-----------------------------------------------+
| Table  | Op        | Msg_type | Msg_text                                      |
+--------+-----------+----------+-----------------------------------------------+
| db.t1 | histogram | status   | Histogram statistics removed for column 'c1'. |
| db.t1 | histogram | status   | Histogram statistics removed for column 'c2'. |
+--------+-----------+----------+-----------------------------------------------+
2 rows in set (0.13 sec)

14. 新增innodb_dedicated_server参数

能够让InnoDB根据服务器上检测到的内存大小自动配置innodb_buffer_pool_size,innodb_log_file_size,innodb_flush_method三个参数。

15. 日志分类更详细

在错误信息中添加了错误信息编号[MY-010311]和错误所属子系统[Server]

# MySQL 5.7
2018-06-08T09:07:20.114585+08:00 0 [Warning] 'proxies_priv' entry '@ root@localhost' ignored in --skip-name-resolve mode.
2018-06-08T09:07:20.117848+08:00 0 [Warning] 'tables_priv' entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode.
2018-06-08T09:07:20.117868+08:00 0 [Warning] 'tables_priv' entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode.
 
 
# MySQL 8.0
2018-06-21T17:53:13.040295+08:00 28 [Warning] [MY-010311] [Server] 'proxies_priv'  entry '@ root@localhost' ignored in --skip-name-resolve mode.
2018-06-21T17:53:13.040520+08:00 28 [Warning] [MY-010330] [Server] 'tables_priv'  entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode.
2018-06-21T17:53:13.040542+08:00 28 [Warning] [MY-010330] [Server] 'tables_priv'  entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode.

16. undo空间自动回收

  • innodb_undo_log_truncate参数在8.0.2版本默认值由OFF变为ON,默认开启undo日志表空间自动回收。
  • innodb_undo_tablespaces参数在8.0.2版本默认为2,当一个undo表空间被回收时,还有另外一个提供正常服务。
  • innodb_max_undo_log_size参数定义了undo表空间回收的最大值,当undo表空间超过这个值,该表空间被标记为可回收。

17. 增加资源组

MySQL 8.0新增了一个资源组功能,用于调控线程优先级以及绑定CPU核。
MySQL用户需要有 RESOURCE_GROUP_ADMIN权限才能创建、修改、删除资源组。
在Linux环境下,MySQL进程需要有 CAP_SYS_NICE 权限才能使用资源组完整功能。

[root@localhost~]# sudo setcap cap_sys_nice+ep /usr/local/mysql8.0/bin/mysqld
[root@localhost~]# getcap /usr/local/mysql8.0/bin/mysqld
/usr/local/mysql8.0/bin/mysqld = cap_sys_nice+ep

默认提供两个资源组,分别是USR_default,SYS_default

创建资源组:
create resource group test_resouce_group type=USER vcpu=0,1 thread_priority=5;
将当前线程加入资源组:
SET RESOURCE GROUP test_resouce_group;
将某个线程加入资源组:
SET RESOURCE GROUP test_resouce_group FOR thread_id;
查看资源组里有哪些线程:
select * from Performance_Schema.threads where RESOURCE_GROUP=’test_resouce_group';
修改资源组:
alter resource group test_resouce_group vcpu = 2,3 THREAD_PRIORITY = 8;
删除资源组 :
drop resource group test_resouce_group;

# 创建资源组
mysql>create resource group test_resouce_group type=USER vcpu=0,1 thread_priority=5;
Query OK, 0 rows affected (0.03 sec)

mysql> select * from RESOURCE_GROUPS;
+---------------------+---------------------+------------------------+----------+-----------------+
| RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS |  THREAD_PRIORITY |
+---------------------+---------------------+------------------------+----------+-----------------+
| USR_default         | USER                |                      1 | 0-3      |                0 |
| SYS_default         | SYSTEM              |                      1 | 0-3      |                0 |
| test_resouce_group  | USER                |                      1 | 0-1      |                5 |
+---------------------+---------------------+------------------------+----------+-----------------+
3 rows in set (0.00 sec)

# 把线程id为60的线程加入到资源组test_resouce_group中,线程id可通过Performance_Schema.threads获取
mysql> SET RESOURCE GROUP test_resouce_group FOR 60;
Query OK, 0 rows affected (0.00 sec)

# 资源组里有线程时,删除资源组报错
mysql> drop resource group test_resouce_group;
ERROR 3656 (HY000): Resource group test_resouce_group is busy.

# 修改资源组
mysql> alter resource group test_resouce_group vcpu = 2,3 THREAD_PRIORITY = 8;
Query OK, 0 rows affected (0.10 sec)
mysql> select * from RESOURCE_GROUPS;
+---------------------+---------------------+------------------------+----------+-----------------+
| RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS | THREAD_PRIORITY |
+---------------------+---------------------+------------------------+----------+-----------------+
| USR_default         | USER                |                      1 | 0-3      |               0 |
| SYS_default         | SYSTEM              |                      1 | 0-3      |               0 |
| test_resouce_group  | USER                |                      1 | 2-3      |               8 |
+---------------------+---------------------+------------------------+----------+-----------------+
3 rows in set (0.00 sec)

# 把资源组里的线程移出到默认资源组USR_default
mysql> SET RESOURCE GROUP USR_default FOR 60;
Query OK, 0 rows affected (0.00 sec)

# 删除资源组
mysql> drop resource group test_resouce_group;
Query OK, 0 rows affected (0.04 sec)

18. 增加角色管理

角色可以认为是一些权限的集合,为用户赋予统一的角色,权限的修改直接通过角色来进行,无需为每个用户单独授权。

# 创建角色
mysql> create role role_test;
Query OK, 0 rows affected (0.03 sec)
 
# 给角色授予权限
mysql> grant select on db.* to 'role_test';
Query OK, 0 rows affected (0.10 sec)
 
# 创建用户
mysql> create user 'read_user'@'%' identified by '123456';
Query OK, 0 rows affected (0.09 sec)
 
# 给用户赋予角色
mysql> grant 'role_test' to 'read_user'@'%';
Query OK, 0 rows affected (0.02 sec)
 
# 给角色role_test增加insert权限
mysql> grant insert on db.* to 'role_test';
Query OK, 0 rows affected (0.08 sec)
 
# 给角色role_test删除insert权限
mysql> revoke insert on db.* from 'role_test';
Query OK, 0 rows affected (0.10 sec)
 
# 查看默认角色信息
mysql> select * from mysql.default_roles;
+------+-----------+-------------------+-------------------+
| HOST | USER      | DEFAULT_ROLE_HOST | DEFAULT_ROLE_USER |
+------+-----------+-------------------+-------------------+
| %    | read_user | %                 | role_test         |
+------+-----------+-------------------+-------------------+
1 row in set (0.00 sec)
 
# 查看角色与用户关系
mysql> select * from mysql.role_edges;
+-----------+-----------+---------+-----------+-------------------+
| FROM_HOST | FROM_USER | TO_HOST | TO_USER   | WITH_ADMIN_OPTION |
+-----------+-----------+---------+-----------+-------------------+
| %         | role_test | %       | read_user | N                 |
+-----------+-----------+---------+-----------+-------------------+
1 row in set (0.00 sec)
 
# 删除角色
mysql> drop role role_test;
Query OK, 0 rows affected (0.06 sec)
11617181920114
 
Copyright © 2008-2021 lanxinbase.com Rights Reserved. | 粤ICP备14086738号-3 |