jenkins docker 部署-02

news2025/2/21 7:16:50

镜像说明

镜像ponylee/jenkins-centos7:v2.0基于镜像ponylee/jenkins-centos7:v1.0(镜像ponylee/jenkins-centos7:v1.0基于jenkins/jenkins:lts-centos7-jdk8, 添加 git maven jdk8 等java部署常用的工具。同时改变运行用户jenkins为root,放大权限),添加node-v14.18.2, 更改 openjdk 为 oracle jdk1.8,具体请参考。

启动jenkins

  • host mode
    docker run -d \
    --network host \
    -v /data/jenkins/jenkins_home:/var/jenkins_home \
    -v /etc/localtime:/etc/localtime \
    --name jenkins \
    ponylee/jenkins-centos7:v2.0
  • bridge mode
    docker run -d \
    -p 8080:8080 \
    -p 50000:50000 \
    -v /data/jenkins/jenkins_home:/var/jenkins_home \
    -v /etc/localtime:/etc/localtime \
    --name jenkins \
    ponylee/jenkins-centos7:v2.0

jenkins配置

用到的plugins: Publish Over SSH、SSH plugin、Maven Integration、Date Parameter、NodeJS Plugin和 jenkins社区推荐的插件

General

选择参数配置

status选择

在这里插入图片描述hosts

在这里插入图片描述

字符串参数配置

rollback_date

在这里插入图片描述

时间参数配置

依赖Date Parameter插件
在这里插入图片描述

选丢弃旧的构建

在这里插入图片描述

源码管理

Repositories 配置

在这里插入图片描述

git Credentials 配置

  • 生成秘钥
ssh-keygen -t rsa -C "xxx@xx.com" #邮箱
git config --global user.name xxx
git config --global user.email xxx@xx.com
ssh -vT xx.github.com #验证联通性
cd ~/.ssh/
cat ~/.ssh/id_rsa.pub | clip #复制公钥
  • 上传公钥
    在这里插入图片描述
  • 配置Credentials
    Manage Jenkins -> Manage Credentials -> 全局凭据 ->添加凭据
    在这里插入图片描述

构建

执行shell

后端构建

在这里插入图片描述后端构建shell:

if [ ${status} = "deploy" ]
then
    echo "================开始maven构建===================="
    . /etc/bashrc
    mvn -U clean  package -Dmaven.test.skip=true -P release
else
    echo "================开始回滚===================="
fi

前端构建

构建环境
在这里插入图片描述
构建
在这里插入图片描述前端构建shell

if [ ${status} = "deploy" ]
then
    echo "================开始构建===================="
    npm install -unsafe-perm=true
    npm run build
    mv dist frontend
    zip -qr frontend-${deploy_date}.zip frontend
else
    echo "================开始回滚===================="
fi

Send files or execute commands over SSH

将后端/前端构建完成的包传送到指定的服务器节点
后端
在这里插入图片描述前端
在这里插入图片描述

Publish over SSH 配置

Manage Jenkins -> Configure System -> Publish over SSH

在这里插入图片描述在这里插入图片描述在这里插入图片描述

Execute shell script on remote host using ssh

构建镜像
在这里插入图片描述建构镜像shell

if [ ${status} = "deploy" ]
then
    echo "================开始部署===================="
    echo "开始构建镜像!!!"
    cd /root/Images/
    /bin/bash -x /root/Images/build.sh  ${deploy_date}  app-backend
else
    echo "================开始回滚===================="
fi

后端部署服务
在这里插入图片描述后端部署服务shell

if [ ${hosts} = "192.168.1.1"  -o  ${hosts} = "all" ]
then
    echo "================开始部署192.168.1.1服务器===================="
    /bin/bash -x /root/deploy/start/app-backend-start.sh ${status}  app-backend  ${deploy_date} ${rollback_date}  
    echo "================app-backend部署成功====================";
    sleep 180;#热部署
fi

前端部署服务
前端服务不需要构建镜像,只需要部署服务
在这里插入图片描述前端部署服务shell:

echo "================构建完成,开始发布===================="
/bin/bash /root/deploy/start/frontend-start.sh ${status} frontend01 ${deploy_date} ${rollback_date}  

SSH site 配置

Manage Jenkins -> Configure System -> SSH remote hosts

在这里插入图片描述

SSH remote hosts Credentials配置

Manage Jenkins -> Manage Credentials -> 全局凭据 ->添加凭据
在这里插入图片描述

build.sh脚本

构建docker 镜像并推送到镜像私服

#!/bin/bash
#build.sh

BACKEND_PROJECTS="xx-backend-service1|xx-backend-service2"

function build(){
  if (( $# < 2 )) ;then
      echo "Please specify images version date parameters and project . eg: [20221215150431] [$BACKEND_PROJECTS]"
      exit;
  fi

  IMAGE_VERSION=v${1}
  PROJECT=${2}

  #DATE=$(date '+%Y%m%d%H%M%S')
  IMAGE="172.16.0.19:5000/${PROJECT}:$IMAGE_VERSION"

  echo "docker build -t $IMAGE ."

  docker build -t "${IMAGE}" .

  echo "push ${IMAGE} ... "

  docker push $IMAGE

  echo "push success!"

  mv *.jar ../builds/${PROJECT}-${1}.jar

  echo "backup jar success!"
}

build $@

Dockerfile

#from java:8-jre-alpine
From anapsix/alpine-java
VOLUME /tmp
ADD *.jar app.jar
RUN sh -c 'touch /app.jar'
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ENV JAVA_OPTS="-Xms8g -Xmx8g -XX:NewRatio=1 -XX:SurvivorRatio=8 -XX:+UseG1GC  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/gc/heapdump.hprof"
ENV JAVA_LOG_OPTS="-Xloggc:/var/log/gc/gc_%t.log -XX:+UseGCLogFileRotation  -XX:NumberOfGCLogFiles=10  -XX:GCLogFileSize=500m -XX:+PrintGCDateStamps -XX:+PrintGCDetails  -XX:+PrintHeapAtGC -XX:+PrintGCApplicationStoppedTime  -XX:+PrintGCApplicationConcurrentTime -XX:+PrintCommandLineFlags"
#ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
CMD exec java $JAVA_OPTS $JAVA_LOG_OPTS  -Djava.security.egd=file:/dev/./urandom -jar /app.jar

部署脚本

后端部署脚本

#!/bin/bash
#backend-start.sh

BACKEND_PROJECTS="xx-backend-service1|xx-backend-service2"
#TEST="sleep 100000"

[ -d /root/deploy/versions ]  || mkdir -p /root/deploy/versions
IP=`hostname -i | awk '{print $1}'`
function deploy() {
        if (( $# < 2 )) ;then
            echo "Please specify images version date parameters and project . eg: [20221215150431] [$BACKEND_PROJECTS]"
            exit 1;
        fi
        PROJECT=${1}
        IMAGE_VERSION=v${2}
        NEW_IMAGE=x.x.x.x:5000/${PROJECT}:$IMAGE_VERSION
        LAST_CONTAINER=$(docker ps -a |awk '{print $NF}'| grep ${PROJECT})
        touch /root/deploy/versions/$PROJECT
        LAST_IMAGE=`awk 'END {print}' /root/deploy/versions/$PROJECT`
        if [ -n $LAST_IMAGE ]
        then
            echo "當前版本: " $LAST_IMAGE
        else
            echo "当前为第一次部署"
        fi
        echo "docker pull $NEW_IMAGE"
        docker pull $NEW_IMAGE
        if [ $? -eq 0 ]; then
                echo "镜像下载完毕"
        else
                echo "镜像下载失败,停止部署!"
                exit 1;
        fi


        echo "即将部署新版本: $NEW_IMAGE"
        echo "开始启动${PROJECT}服务 ..."

        #shutdown 旧的服务
        # stop the previous image and remove it
        if [ -n "${LAST_CONTAINER}" ]; then
            docker stop $LAST_CONTAINER
            docker rm -f $LAST_CONTAINER
        fi

        if [[ $PROJECT =~ "backend" ]]
        then
            docker run -d \
            -v /etc/localtime:/etc/localtime \
            -v /data/log/:/var/log/app \
            -v /data/gc:/var/log/gc \
            -p 8080:8080\
            --name=${PROJECT} \
            --restart=always \
            --privileged=true \
            "$NEW_IMAGE"  $TEST
        else
            if [ $IP="192.168.1.2" ]
            then
                PORT=8080
            else
                PORT=8081
            fi
            docker run -d \
            -p $PORT:8080\
            --restart=always   \
            --name=${PROJECT} \
            -v /data/log:/var/log \
            -v /etc/localtime:/etc/localtime \
            -v /data/uploadFileTemp:/uploadFileTemp \
            -v /data/gc:/var/log/gc  \
            --privileged=true \
            $NEW_IMAGE  $TEST
        fi
        echo  $NEW_IMAGE >> /root/deploy/versions/$PROJECT
        echo "服务${PROJECT}启动完成!"
        if [ -n "${LAST_IMAGE}" ]; then
             docker rmi $LAST_IMAGE
        fi
}

function rollback() {
        if (( $# < 1 )) ;then
            echo "Please specify the project . eg: [${BACKEND_PROJECTS}] ,or [20221215150431]  [${BACKEND_PROJECTS}] "
            exit 1;
        fi
        PROJECT=${1}
        IMAGE_VERSION=v${2}
        NEW_IMAGE=x.x.x.x:5000/${PROJECT}:$IMAGE_VERSION
        LAST_IMAGE=`awk 'END {print}' /root/deploy/versions/$PROJECT`
        if [ $? -ne 0 ]; then
            echo "尚未上綫,不可回滾,請開始第一次部署吧!"
            exit 1;
        fi

        [ $LAST_IMAGE == $NEW_IMAGE ] && echo "當前版本已經是: " $NEW_IMAGE && exit 1

        if  [ ${IMAGE_VERSION} = v ]
        then
            # rollback_date無值,上一版本
             CNT=`cat /root/deploy/versions/$PROJECT | wc -l`
             if (( $CNT < 2 ))
             then
                     echo "已经是最初的版本,已经没有版本可以回滚!!!"
                     exit 1;
             fi
             NEW_IMAGE=`cat /root/deploy/versions/$PROJECT | grep -B 1 $IMAGE_VERSION | awk 'NR==1{print}'`
        fi

        docker pull $NEW_IMAGE
        if [ $? -eq 0 ]; then
                echo "镜像下载完毕"
        else
                echo "镜像下载失败,停止回滚!"
                exit 1;
        fi
        echo "即将回滚镜像至: $NEW_IMAGE"
        echo "开始回滾${PROJECT}服务 ..."
        #shutdown 旧的服务
        LAST_CONTAINER=$(docker ps -a |awk '{print $NF}'| grep ${PROJECT})
        # stop the previous image and remove it
        if [ -n "${LAST_CONTAINER}" ]; then
            docker stop $LAST_CONTAINER
            docker rm -f $LAST_CONTAINER
        fi

        if [[ $PROJECT =~ "backend" ]]
        then
            docker run -d \
            -v /etc/localtime:/etc/localtime \
            -v /data/log/:/var/log/ \
            -v /data/gc:/var/log/gc \
            -p 8080:8080\
            --name=${PROJECT} \
            --restart=always \
            --privileged=true \
            ${NEW_IMAGE}  $TEST
        else
            if [ $IP = "192.168.1.2" ]
            then
                PORT=8080
            else
                PORT=8081
            fi
            docker run -d \
            -p $PORT:8080\
            --restart=always   \
            --name=${PROJECT} \
            -v /data/log:/var/log/  \
            -v /etc/localtime:/etc/localtime \
            -v /data/uploadFileTemp:/uploadFileTemp \
            -v /data/gc:/var/log/gc \
            --privileged=true \
            ${NEW_IMAGE}  $TEST
        fi
        echo  $NEW_IMAGE >> /root/deploy/versions/$PROJECT
        echo "服务${PROJECT}回滚完成!"
        if [ -n "${LAST_IMAGE}" ]; then
             docker rmi $LAST_IMAGE
        fi
}

function printUsage(){
        echo -e "Usage: [status] [project] [deploy_date] [rollback_date]  . eg:  [deploy|rollback] [${BACKEND_PROJECTS}] [20221215150431] [20221215150431]  "
}

case "$1" in
    (deploy)
        deploy  $2  $3
    ;;
    (rollback)
        rollback  $2  $4
    ;;
    (*)
        printUsage
        exit 1;
    ;;
esac

前端部署脚本

#!/bin/bash
#frontend-start.sh

FRONT_PROJECTS="frontend01|frontend02|frontend03"

[ -d /root/deploy/versions ]  || mkdir -p /root/deploy/versions
[ -d /root/deploy/builds ]  || mkdir -p /root/deploy/builds

function deploy() {
        if (( $# < 2 )) ;then
            echo "Please specify the version date parameters and the project . eg: [20221215150431] [${FRONT_PROJECTS}]"
            exit 1;
        fi

        PROJECT=${1}
        DATE=${2}

        NEW_VERSION=${PROJECT}-$DATE.zip
        ls /root/deploy/builds/${PROJECT}-${DATE}.zip

        if [ $? -ne 0 ]; then
                echo "新版本不存在或未构建成功,停止部署!"
                exit 1;
        fi

        CURRENT_VERSION=`cat /root/deploy/versions/$PROJECT`
        if [ $? -ne 0 ]; then
            echo "當前版本: " `cat /root/deploy/versions/$PROJECT`
        else
            echo "当前为第一次部署"
        fi
        echo "即将部署新版本: $NEW_VERSION"
        echo "开始部署${PROJECT}服务 ..."

        set -e
        cd /root/deploy
        rm -rf ${PROJECT}
        unzip -q  builds/${NEW_VERSION} -d ./
        /usr/sbin/nginx -s reload
        echo  $NEW_VERSION >> ./versions/$PROJECT

        echo "服务${PROJECT}部署完成!"
}

function rollback() {
        if (( $# < 1 )) ;then
            echo "Please specify the project . eg: [${FRONT_PROJECTS}] ,or [20221215150431]  [${FRONT_PROJECTS}] "
            exit 1;
        fi
        PROJECT=${1}
        DATE=${2}

        CURRENT_VERSION=`cat /root/deploy/versions/$PROJECT`
        if [ $? -ne 0 ]; then
            echo "尚未上綫,不可回滾,請開始第一次部署吧!"
            exit 1;
        fi

        if  [ x${DATE} != x ]
        then
                # rollback_date有值,指定版本
                ls /root/deploy/builds/${PROJECT}-${DATE}.zip
                if [ $? -ne 0 ]; then
                        echo "要回滾的版本不存在,停止部署!"
                        exit 1;
                fi
                OLD_VERSION=${PROJECT}-${DATE}.zip
                [ $CURRENT_VERSION == $OLD_VERSION ] && echo "當前版本已經是: " $CURRENT_VERSION && exit 1
        else
                # rollback_date無值,上一版本
                CNT=`ls  /root/deploy/builds | grep ${PROJECT} | grep p -B 1 $CURRENT_VERSION | wc -l`
                if (( $CNT < 2  || $? ))
                then
                        echo "已经是最早的版本,已经没有版本可以回滚!!!"
                        exit 1;
                fi

                OLD_VERSION=`ls  /root/deploy/builds |  grep ${PROJECT} | grep -B 1  $CURRENT_VERSION  | awk 'NR==1{print}'`
        fi

        echo "當前版本: " $CURRENT_VERSION
        echo "即将回滚版本至: $OLD_VERSION"
        echo "开始回滾${PROJECT}服务 ..."

        set -e
        cd /root/deploy
        rm -fr ${PROJECT}
        unzip -q  builds/${OLD_VERSION} -d ./
        /usr/sbin/nginx -s reload
        echo  $OLD_VERSION >> versions/$PROJECT

        echo "服务${PROJECT}回滚完成!"
}

function printUsage(){
        echo -e "Usage: [status] [project] [deploy_date] [rollback_date]  . eg:  [deploy|rollback] [${FRONT_PROJECTS}] [20221215150431] [20221215150431]  "
}

case "$1" in
    (deploy)
        deploy  $2  $3
    ;;
    (rollback)
        rollback  $2  $4
    ;;
    (*)
        printUsage
        exit 1;
    ;;
esac


jenkins 部署

在这里插入图片描述
jenkins部署自动化实现,git仓库拉去代码、打包(包括后端打包和前端打包)、docker镜像构造、服务部署、版本控制。实现了一键部署和一键回滚。

参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/184261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【GD32F427开发板试用】基于GD32F427的纳姆轮小车

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;Ljfly 目标&#xff1a; 做一个四轮驱动小车&#xff0c;实现通过GD32F427控制小车前进&#xff0c;后退&#xff0c;左移&#xff0c;右移&a…

一起自学SLAM算法:12.1 ros-navigation导航系统

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 可以说ros-navigation是ROS系统中最重要的组件之一&#xff0c;绝大部分自主移动机器人的导航功能都是基于ros-navigation导航系统实现的。下面将从原理分析、源码解读和安装与运行这3个方面展开讲解ros-navigat…

一篇五分生信临床模型预测文章代码复现——FIgure 9.列线图构建,ROC分析,DCA分析 (一)

之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…

拉伯证券|2023年净利“超十倍潜力股”揭秘

本年成绩有望暴增的个股有哪些&#xff1f; 2022年各首要指数调整较大&#xff0c;但2023年开年以来A股体现继续强势&#xff0c;三大股指到目前涨幅均超5%&#xff0c;创业板指更是大涨超10%&#xff0c;医药、消费、科技等赛道轮番体现。 外资也对A股进行新一轮的加仓调仓&a…

Redis学习笔记:慢查询,Pipeline,事务,乐观锁

本文是自己的学习笔记。主要参考资料如下&#xff1a; 马士兵 1、Redis的慢查询1.1、慢查询的相关参数1.1.1、设置阈值1.1.2、慢查询日志存储长度1.1.2.1、慢查询日志解析1.2、生产环境下慢查询的配置2、Pipeline2.1、简单的pipeline代码示例2.2、使用Pipeline的注意事项3、事务…

自己写的功能简单的 http server 文件下载服务器 http服务器

最近在项目中遇到过 通过ssh登录到某台机器A &#xff0c;然后 又从A机器上ssh到机器B 而B机器是没有外网功能&#xff0c;这个时候如果想从B机器上传文件到A机器上就很不好办了 由于B机器没有外网 很多工具软件都没有 原来是是用python 起的http服务器 但是B机器没有安装py…

Black Basta 勒索软件利用 QakBot 进行分发

自 2022 年 4 月投入运营以来&#xff0c;Black Basta 对全球近 50 家组织发起了攻击。攻击者使用了“双重勒索”策略&#xff0c;如果受害者不交付赎金就会被公开数据。 勒索团伙会不断改进攻击方式&#xff0c;最近研究人员发现 Black Basta 与银行木马 QakBot 勾结在一起&a…

nginx+uwsgi部署django项目

1. python3.9环境安装 安装依赖 yum install zlib zlib-devel libffi-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make wget下载源码 官网地址 wget https://www.python.org/ftp/python/3.9.6/Python-3.9.6.tar.xz解压 &…

maven的下载与安装

前言 本篇文章是基于win11系统下载安装Maven的教程。 一、 Maven介绍 1. 什么是Maven&#xff1f; Maven是基于项目对象模型(POM project object model)&#xff0c;可以通过一小段描述信息&#xff08;配置&#xff09;来管理项目的构建&#xff0c;报告和文档的软件项目管…

【FreeRTOS】详细讲解FreeRTOS中任务管理并通过示例讲述其用法

任务状态 在FreeRTOS中一个任务经创建后会有多个状态&#xff0c;通常可分为以下几种状态&#xff1a; 就绪态&#xff1a;新创建的任务一般处于就绪态。处于就绪态的任务表明其已经存在于就绪列表中&#xff0c;其已经具备所有的任务执行需要条件&#xff0c;只等待调度器调度…

社科院杜兰大学金融管理硕士项目——美丽的风景,在你前行的路上

一个人的强大源于内心的坚定&#xff0c;内心强大的人&#xff0c;是平和的、自信的、乐观的。在工作中也是奋发图强、积极向上的&#xff0c;就像选择来社科院与杜兰大学金融管理硕士充电&#xff0c;为职场发展注入能量&#xff0c;为未来发展奠定基础。近些年来&#xff0c;…

Centos7离线安装MySQL

使用tar.gz文件安装MySQL 1、下载MySQL离线包 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 根据需要下载对应版本tar.gz文件&#xff0c;下载完成后上传到服务器 2、解压tar.gz文件 tar -zxvf mysql-5.7.37-linux-glibc2.12-x86_64.tar.gz等待解…

【计算机网络】TCP/UDP协议

传输层协议 负责数据能够从发送端传输接收端,这篇文章主要介绍TCP和UDP协议 UDP协议 学习UDP协议需要掌握&#xff0c;UDP协议如何做到封装和解包的&#xff0c;如何做到向上交付的&#xff08;分用问题&#xff09; UDP协议格式 封装&#xff1a;添加定长报头 解包&…

用Python掌握QQ群聊天记录数据分析

当你打开QQ群时,你是否想过如何用Python提取里面的数据呢?随着社交媒体的兴起,QQ群成为了人们交流的重要平台,而提取这些数据可以帮助我们了解用户喜好和行为。那么,如何使用Python提取QQ群数据呢? 这里做了一套脚本用于提取QQ群的消息并进行一些简单的处理。 其中包括…

IB、AP、A-LEVEL,哪种最适合自己呢?

刚开始了解新加坡留学的家长和学生&#xff0c;一定看到这些就觉得头大吧。当下国际学校里的课程可以说五花八门&#xff0c;在选择之前一定要弄清楚这些名词背后的含义…… IB是什么 IB&#xff08;International Baccalaureate&#xff09;全称为国际预科证书课程&#xff0c…

Linux下rabbitmq的集群搭建

1 修改 3 台机器的主机名称 在三台服务器分别执行 hostnamectl set-hostname master hostnamectl set-hostname node01 hostnamectl set-hostname node022 配置各个节点的 hosts 文件 vim /etc/hosts 192.168.5.6 master 192.168.5.7 node01 192.168.5.8 node023 确保各个节…

【工具】苏格拉底式诘问法解决工作问题

目录一、什么是苏格拉底式诘问法二、苏格拉底式诘问法的细分三、在实际工作中运用苏格拉底式诘问法解决问题一、什么是苏格拉底式诘问法 苏格拉底式诘问法&#xff08;Socratic Elenchus&#xff09;是苏格拉底式提问的一种&#xff0c;也叫做"诘问法"。它是由古希腊…

OpenCV-PyQT项目实战(2)QtDesigner 和 PyUIC 快速入门

欢迎关注『OpenCV-PyQT项目实战 Youcans』系列&#xff0c;持续更新中 OpenCV-PyQT项目实战&#xff08;1&#xff09;安装与环境配置 OpenCV-PyQT项目实战&#xff08;2&#xff09;QtDesigner 和 PyUIC 快速入门 OpenCV-PyQT项目实战&#xff08;3&#xff09;信号与槽机制 …

【Java】final的关键字和final的四种用法

final定义 final翻译成中文的意思是 “最终” &#xff0c; 它是java当中的一个关键字&#xff0c;使用final修饰的对象不允许修改或替换其原始值或定义。 假如当final修饰一个类的时候&#xff0c;是不能被其他类继承的。 final的四种用法 修饰类修饰方法修饰变量修饰参数 1.…

Oracle 里的优化器

对于关系型数据库而言&#xff0c;优化器是最核心的部分。主要是因为优化器负责解析SQL。而大家都是通过SQL来访问存储在数据库中的数据。故此&#xff0c;优化器的好坏直接决定该关系型数据库的强弱。 同时&#xff0c;想要做好SQL优化&#xff0c;就必须深入了解优化器。这是…