DevOps平台中的自动化部署框架设计

 

本文目录:

 

一、背景

二、我们的需求是什么?

三、概念澄清

四、概念模型

五、总体设计

六、关键点设计

七、总结

 

一、背景

 

 

说到自动化部署,大家肯定都会想到一些配置管理工具,像ansible,chef,puppet, saltstack等等。虽然这些工具给运维效率和安全性带来了很多好处。但是实际工作中,我们还是会遇到一些问题: 

 

  • 这些工具无法普及到开发、测试人员,经常找运维帮忙,无法自助; 

  • 项目人员无法直观的参看到系统的部署架构设计,及架构的演进过程; 

  • 从物理架构设计到最终上线,无法形成闭环; 

  • 受差异性的基础设施影响较大。

 

二、我们的需求是什么?

 

 

我们DevOps平台的部署模块就克服上面这些问题,为实现DevOps以产品为核心,以项目管理为驱动,将需求、设计、交付、运维整个链路打通这一目标提供有力支持。具体来看其需求涵盖一下几点: 

 

  • 将架构设计纳入DevOps管理过程中,支持架构设计版本化; 

  • 一次架构设计多次部署; 

  • 以最佳实践为基础,实现架构设计模版重用; 

  • 多环境部署,同时支持应用在虚拟机、容器上的部署; 

  • 支持多种部署模式(单机、高可用)、部署策略(全新、蓝绿、滚动升级、回滚)

     

 

三、概念澄清

 

 

在正式讲解我们的设计之前,我们想澄清CI/CD的基本概念,因为本次的主题和持续集成、持续交付和持续部署这些名词总有些渊源。

 

 

 

1、什么是持续集成?

 

 

 

持续集成(Continuous Integration)指的是,频繁地将代码集成到主干,以便快速发现错误、防止分支大幅度偏离主干。 

 

持续集成的目的,就是在产品快速迭代的同时保持代码质量,它的核心措施主要有两点: 

1)代码集成到主干之前,必须通过自动化测试,只要有一个测试用例失败,就不能集成。 

2)通过Code Review、代码质量分析工具对代码质量进行把关,以便确定是否能够集成。

 

Martin Flower说过, “持续集成并不能消除Bug,而是让他们非常容易发现和改正。”

 

2、什么是持续交付?

 

 

 

持续交付(Continuous Delivery)指的是,新版本为了能够快速安全的交付到生产环境中,需要将新版本先交付到类生产(Production-like)环境中(如UAT/Staging/Lab环境),以便进行相应的业务验证、安全验证、性能验证等过程。 

 

一旦类生产环境验证通过,新版本就进入到生产阶段。 

 

持续交付可以看作是持续集成的进一步。它强调的是,不管怎么更新,软件是随时随地可以交付的。

 

 

3、什么是持续部署?

 

 

 

持续部署(Continuous Deployment)指的是,新版本通过类生产环境的验证后,自动部署到生产环境中。 

 

持续部署可以看成持续交付的进一步。持续部署的前提是自动化完成测试、构建、验证等步骤。 

 

持续部署的目标是,代码在任何时刻都可以进入自动地进入生产阶段,为最终用户提供服务。 

 

持续交付和持续部署的区别可以参考下图:

 

(点击可放大查看)

从上图中,我们可以看出:

持续交付流程将自动的测试新版本应用,但是否将新版本交付到生产环境中是一个手动过程。持续部署则是自动地将新版本交付到生产环境中去。

 

关于持续交付/持续部署,我们不能说哪一个是最好的方案。对于不同的组织,适合的就是最好的。

 

 

4、什么是自动化部署?

 

 

自动化部署(Automatic Deployment)指的是,通过自动化工具将应用介质部署到指定环境中去。 

自动化部署只是持续交付和持续部署流程中的一个功能单元。 

自动化部署工具:Ansible、Puppet、SaltStack等等。 

 

通过以上概念的澄清,我们了解了什么是持续集成、持续交付、持续部署以及自动化部署。 

本文的主题不是介绍持续集成、持续交付、持续部署的Pipeline与实现,而是介绍DevOps平台中,在传统自动化部署工具之上的自动化部署框架的设计与实现。而自动化部署模块也是我们DevOps平台中的CI/CD的底层能力。 

 

下面我们就来聊聊具体的设计。

 

四、概念模型

 

(点击可放大查看)

除了系统内置的一些模版概念,我们将自动化部署流程分为三个阶段,即设计、转换、运维。每个阶段都会有相应的基本模型。 

下面,我们分阶段的去解释一下这些概念模型。

 

 

1、设计阶段

 

设计(Design),是在装配(Assembly)内对应用/系统的架构的描述;而应用/系统,是由含有多个组件(Component)的系统(Platform)组成的。 

Design阶段的基本流程:

 

(1)创建装配(Assembly) 

  • 通过选择可用的系统模版(Platform Template),添加一个新的Platform;

  • 每一个Platform都对应一种应用(如mysql,tomcat,springboot,nginx);

  • 每一个Platform都是有一组组件(Component)组成的,并且已定义好了组件之间的依赖关系;

  • 在Assembly内,用户可以通过设置Platform Link设置各个Platform之间的关系

 

(2)配置系统(Platform)内的组件(Component)的属性值 

  • Component是最底层的部署(或者配置)单元,如springboot中的secgroup, compute, os, jdk, fatjar, lb都是一个组件;

  • 每一个Component都有相应的配置模版

 

(3)提交设计 

  • 提交的过程是将已经完成的设计做一次Commit,做一次归档。

 

2、转换阶段

 

转换(Transition),是在Assembly内对应用/系统在某一Environment内的部署过程。 

Transition阶段的基本流程: 

 

(1)创建部署环境(Deploy Environment) 

  • 根据环境类型(如dev, test, prod等),添加属于某个Assembly的部署环境

  • 部署之前,部署环境是应用/系统用于部署的配置的抽象

  • 部署之后,部署环境就是管理和监控应用/系统的具体实例的集合

 

(2)配置部署环境 

  • 设置每个Platform关联的资源(vm/container)、部署模式(单点,高可用)

 

(3)选择Assembly内的一个或多个Platform生成并提交执行计划 

  • 根据部署策略不同,一个Platform的执行计划可能包含几个子计划

 

(4)执行部署 

  • 每个Assembly/Environment/Platform下面的每个Component都有一个instance,这些instance可以进行单独Repair

 

3、运维阶段

 

运维(Operation),是在Assembly内对各个部署环境内Instances的管理和监控。 

Operation阶段的基本任务: 

 

(1)组件实例运维,例如 

  • Compute: Status, Reboot, upgrade-os-security, powercycel, repair, upgrade-os-all

  • Tomcat/Jboss: Status, Stop, Start, Restart, Repair, Debug

  • Artifact: Repair, Redeploy, Custom User Attachment

 

(2)展现正在部署的操作,有可能还会Replace或Cancel其中一项组件部署或整个部署 

 

(3)展示Assembly某一Environment下的组件实例图谱 

 

(4)日志查询 

  • 对基本的概念模型有了基本认识后,我们来看一下自动化部署框架的总体思路。 

 

五、总体思路

 

DevOps自动化部署框架采用DevOps平台(设计)+Jenkins(执行)的方式完成。 

 

DevOps的职责

  • 完成部署架构设计;

  • 根据部署架构设计和部署环境的配置创建生成相应的执行计划及子执行计划,每一个子计    划对应一个Jenkins pipeline job配置文件(config.xml);

  • 查询Jenkins执行job的实时进度与结果。

 

Jenkins的职责

  • 根据config.xml创建Jenkins Pipeline Job;

  • 执行pipeline job;

  • Jenkins job 通过pipeline script中ansible/openshift命令进行相应的部署等执行操作;

  • 提供查询job执行情况的Rest API。

 

结合上面提到的三个阶段,具体的流程如下所示:

 

(点击可放大查看)

 

下面是具体的部署视图:

 

 

(点击可放大查看)

 

看完整体思路和部署视图,大家肯定会问为什么选择jenkins作为具体的执行引擎? 

首先,jenkins支持master/slave架构,能根据性能需求水平扩张,slave又可以支持多种环境,可以将不同的job分配到不同的slave节点。 

 

还有非常重要的一点,就是Jenkins Pipeline的能力。 

Jenkins中pipeline的设计理念是实现基于groovy脚本,灵活,可扩展的工作流。

 

  • durable持久性:在jenkins的master按计划和非计划的重启后,pipeline的job仍然能够工作,不受影响。

  • 可暂停性:pipeline基于groovy可以实现job的暂停和等待用户的输入或批准然后继续执行。 

  • 更灵活的并行执行,更强的依赖控制,通过groovy脚本可以实现step,stage间的并行执行,和更复杂的相互依赖关系。 

  • 可扩展性:通过groovy的编程更容易的扩展插件。

  • 丰富插件:Jenkins已经支持通过groovy命令调用git、maven、npm、gradle、shell、junit、sonarqube、ansible、docker、openshift、kubernetes等插件,不需要我们再单独实现集成。

  • Rest API:Jenkins提供通过Rest API的方式获取每一个stage的执行情况。

 

由于我们最终会将应用部署到虚拟机和容器云中,虚拟机部署主要通过jenkins中提供的ansible插件+jenkins pipeline script来实现;容器云部署则根据具体的容器云,通过openshift插件(会有一定扩展)或者http request插件+jenkins pipeline script来实现。 

 

下面我们来看一下Jenkins2的主要概念。

 

step, 其实跟jenkins1中的概念一样, 是jenkins里job中的最小单位,可以认为是一个脚本的调用和一个插件的调用。比如通过git拉取代码就是一个step,mvn clean package也是一个step,一个http远程调用等等。  

 

node, 是pipleline里groovy的一个概念,node可以给定参数用来选择agent,node里的steps将会运行在node选择的agent上。这里与jenkins1的区别是,一个 job里可以有多个node,将job的steps按照需求运行在不同的机器上。例如一个job里有好几个测试集合需要同时运行在不同的机器上。  

 

stage, 是pipeline里groovy里引入的一个虚拟的概念,是一些step的集合,通过stage我们可以将job的所有steps划分为不同的stage,使得整个job像管道一样更容易维护。pipleline还有针对stage改进过的view,使得监控更清楚。这里补充一句,多个stage可以在一个node里定义及执行,一个stage内的多个step可以分到不同的node上执行。 

 

六、关键点设计

 

前面我们说的都是概念和流程上的东西,那么用户该如何进行部署架构设计?部署架构设计完成后,如何提交呢? 如何将提交的设计在具体的部署环境中转换成执行计划与子执行计划呢?子计划又如何与jenkins pipeline job映射呢?这就是我们下面要介绍的一些关键点设计。

 

 

1、模块化

 

 

(点击可放大查看)

前面提到,当用户创建Platform时,我们的DevOps平台提供可选的Platform Template,Platform Template定义了其中可以包含的组件类型(Component Template)等信息。也就是说,我们的平台提供了一种基于最佳实践的方式,帮助用户完成系统的架构设计。不仅如此,通过对Platform Template/Component Template等相关数据准备的介绍,也对以后用户扩展添加新的组件类型,提供了充足依据。基本思路如下:

 

1)定义不同的系统模版Platform Template(见表DPS_DLV_PLATFORM_TEMPLATE)。系统模版就是我们通过最佳实践的方式提供了一套应用/中间件系统的模版。如tomcat,nginx、springboot、mysql等。 

一个Platform Template定义了这个模版中包含的组件模版,定义了组件模版之间的依赖关系(见表DPS_DLV_COM_RELATION_DEFINITION),以及每一种组件类型所在的层以及每一种组件类型允许添加的组件的个数(见表DPS_DLV_COMP_CONTAINER_DEFINITION)。当用户添加一个Platform时,必须要选择一种Platform Template。 

 

2)根据不同的部署模式(单节点、高可用)、不同的目标资源(虚拟机、容器)、不同的部署策略(全新、蓝绿、滚动升级、回滚),一个系统模版会对应到多个执行计划模版 (见表DPS_DLV_PLATFORM_ACTION_PLAN_TEMPLATE)。 

 

3)一个系统由多个组件组成,因此系统模版和组件模版之间也是多对多的关系。例如springboot模版对应的组件模版有:secgroup模版、os模版、jdk模版、java application模版等等。 

 

组件模版Component Template(见表DPS_DLV_COMP_TEMPLATE)以及组件的所有属性(见表DPS_DLV_COMP_ATTRIBUTE_DEFINITION)。组件模版就是组件的元数据,为Platform添加的Component都是源于Component Template。 

 

4)为每个Component Template定义Operation模版(见表DPS_DLV_COMP_OPERATION),以便对单个组件实例进行操作,如restart, repair, stop等。  

 

通过以上4步系统预置的Platform Template和Component Template以及相应的数据,就可以提供给用户添加一个Platform了。这些预置数据也为后面生成部署计划Deploy Plan做好的准备。 

 

 

2、变量管理

 

 

 

在需求分析中,我们就提出希望一次设计多次部署。但是在设计阶段设置各个组件属性时,并不能确定在不同的部署环境中其值是一致的,并且一个系统的不同组件的属性也可能是共用一个值。这时候我们就需要引入变量管理。变量管理的主要思路如下: 

 

1)设计阶段,为系统定义一些变量(ConfigMeta)并设置一个默认值,如install_dir。然后在设置某个组件属性值时可以用@P{install_dir}来表示。

 

2)提交设计时,也一同将变量定义作为设计的一部分进行提交。 

 

3)转换阶段,在部署环境中,为每一个变量设置当前环境下的值(ConfigValue)。当创建执行计划时,会将属性@P{install_dir}替换为当前环境的值。 

 

不仅Platform内可以定义变量供该Platform下的Component使用,我们也可以给Assembly定义变量供所有Platform及其组件使用, 形如@A{assembly_var}。

 

3、设计提交

(点击可放大查看)

 

当用户设计完部署架构、设置每个组件属性及变量后,需要将当前的设计指定好版本进行提交,即归档。只有提交的设计,才能在部署环境中获取的到指定的版本。通过版本化,我们可以设计的不同版本做相关的对比。 

 

上面的表结构是比较清晰的表述。

 

 

 

4、执行计划

 

  • 根据不同的部署模式(单节点、高可用)、不同的目标资源(虚拟机、容器)、不同的部署策略(全新、蓝绿、滚动升级、回滚),一个系统模版会对应到多个执行计划模版,并且计划模版之间有父子关系。

  • 每一个子执行模版就是一个jenkins pipeline script模版。

  • 当用户在部署环境中选择某个具体系统及部署策略生成相应的执行计划(含子计划)时,每一个子计划的jenkins pipeline script就是将具体的组件属性注入到执行模版中生成的。

 

另外,为什么需要显示的创建出子计划呢?例如,对于一个高可用的应用,除了要部署具体的应用,还需要更新load balance配置,而这两者之间可能需要加入一些人工活动。所以我们通过显示的创建处子计划,支持用户按子计划一步步的来做。 

 

而jenkins pipeline script的stage几乎都对应到一个具体的组件,具体可以看下图。

 

 


(点击可放大查看)

 

5、部署策略

 

前面我们提到了“部署策略”这个词,除了全新部署,我们常见的部署策略有蓝绿发布、滚动升级、灰度发布/金丝雀发布、回滚。下面来看看我们的相应解决方案。每一种部署策略都会有相应的执行计划模版(含子计划)。 

 

蓝绿发布

 

什么是蓝绿发布?

在发布的过程中用户无感知服务的重启,通常情况下是通过新旧版本并存的方式实现,也就是说在发布的流程中,新的版本和旧的版本是相互热备的,通过切换路由权重的方式(非0即100)实现不同的应用的上线或者下线。

 

  • 前提条件

  • 双份资源 or 支持双端口模式

  • 负载均衡服务 + 操作API接口

 

  • 实施方案

  • 第一步,设置系统将要部署的资源列表。

  • 第二步,将新版本部署容器部署到资源列表中。

  • 第三步,调用负载均衡服务的API接口更新负责均衡配置。第四步,更新资源的标签。

 

考虑到用户可能会手工介入确定是否需要更新负载配置,我们会将第二步、第三步分为两个子执行计划。 

 

滚动升级

 

什么是滚动升级?

滚动发布,一般是取出一个或者多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本。 

这种部署方式相对于蓝绿部署,更加节约资源——它不需要运行两个集群、两倍的实例数。我们可以部分部署,例如每次只取出集群的20%进行升级。 

 

  • 前提条件

  • 负载均衡服务 + 操作API 接口

 

  • 实施方案

  • 第一步,设置滚动升级系数(步进),如20%/n个。

  • 第二步,依次将20%的部署容器移除负载,然后在原资源处部署新版本,然后加入负载。

 

灰度发布/金丝雀发布

 

什么是灰度发布/金丝雀发布?

灰度发布是增量发布的一种类型,它的执行方式是在原有软件生产版本可用的情况下,同时部署一个新的版本。同时运行同一个软件产品的多个版本。 

其实,灰度发布是滚动升级的一种变体,其实灰度发布是先划分出新版本的路由权重,新版本在真实数据验证通过后,在进行剩余老版本的升级。 

 

  • 前提条件

  • 负载均衡服务 + 操作API 接口

 

  • 实施方案

  • 第一步,设置新老版本的路由权重,如90%的用户维持使用老版本,10%的用户使用新版本。

  • 第二步,将10%的部署容器移除负载,然后在原资源处部署新版本,然后加入负载。

  • 第三步,待真实数据验证通过后,再进行剩余老版本的滚动升级。

 

回滚

 

什么是回滚?

回滚是指将应用/服务回退到上一可用版本,并使之可用。 

我们暂时只支持针对蓝绿发布的回滚。

 

  • 前提条件

  • 新版本是基于蓝绿发布策略完成的部署。

  • 负载均衡服务+操作API接口。

 

  • 实施方案

 

  • 更新负载配置

 

七、总结

 

本文大致向大家介绍了我们的DevOps平台中自动化部署框架的相关设计,主要简单介绍了实现思路和几个关键点。 其中还有很多细节,比如如何与CMDB集成,如何与各种容器云集成,以及我们实践过程中遇到的各种坑等等,这里不再一一赘述,有问题可在本文文末留言。 

转载于:https://www.cnblogs.com/jiahe/p/6729261.html

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

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

相关文章

胃癌2019csco指南_2019 CSCO胃癌诊疗指南精华来了!

一文轻松get 2019 CSCO胃癌诊疗指南更新要点!文丨青青子衿 中山大学肿瘤防治中心来源丨医学界肿瘤频道近日,2019年CSCO指南发布会于南京召开。今天为大家推送的是2019 CSCO胃癌诊疗指南的最新更新,在发布专场中,来自华中科技大学同…

learn opengl 中文_LearnOpenGL CN

欢迎来到OpenGL的世界欢迎来到OpenGL的世界。这个工程只是我(Joey de Vries)的一次小小的尝试,希望能够建立起一个完善的OpenGL教学平台。无论你学习OpenGL是为了学业,找工作,或仅仅是因为兴趣,这个网站都将能够教会你现代(Core-p…

MYSQL5.7 日志管理

2019独角兽企业重金招聘Python工程师标准>>> 慢查询日志slow-query-log1 slow-query-log-filefile_name long_query_time1 #SQL执行多长时间以上会记录到慢查询日志,0~10s log_slow_admin_statementsOFF #在写入慢查询日志的语句中包含缓慢的管理语句。 …

cad导出 dxf后中文不显示_CAD快速看图 for Mac

CAD快速看图 for Mac是一款非常小巧、快速、方便的DWG看图工具,CAD快速看图 Mac版可脱离AutoCAD最快速、最方便浏览DWG和DXF图纸,支持二维或三维图纸,支持高清、多文件和云字体,非常实用的一款CAD看图软件,CAD快速看图…

关于java.util.ConcurrentModificationException和remove倒数第二个元素

2019独角兽企业重金招聘Python工程师标准>>> 首先是两段代码的执行结果&#xff1a; 代码一&#xff1a; public class TestListRemove {public static void main(String[] args) {List<Integer> list new ArrayList<Integer>();list.add(1);list.add(…

怎么删除mysql的压缩包_压缩包版mysql怎么卸载

MySQL是一个小巧玲珑但功能强大的数据库&#xff0c;目前十分流行。但是官网给出的安装包有两种格式&#xff0c;一个是msi格式&#xff0c;一个是zip格式的。那么压缩版mysql要怎么卸载&#xff1f;下面本篇文章就来大家介绍一下&#xff0c;希望对你们有所帮助。卸载压缩包版…

lambda表达式之进化

前言在C#我们可以自定义委托&#xff0c;但是C#为什么还要内置泛型委托呢&#xff1f;因为我们常常要使用委托&#xff0c;如果系统内置了一些你可能会用到的委托&#xff0c;那么就省去了定义委托&#xff0c;然后实例化委托的步骤&#xff0c;这样一来既使代码看起来简洁而干…

mysql返回行数_如何计算MySQL查询返回的行数?

How can I count the number of rows that a MySQL query returned?解决方案Getting total rows in a query result...You could just iterate the result and count them. You dont say what language or client library you are using, but the API does provide a mysql_nu…

md5不是对称密码算法_密码学中的消息摘要算法5(MD5)

md5不是对称密码算法In cryptography, MD5 (Message-Digest algorithm 5) is a mainly used cryptographic hash function with a 128-bit hash value. As we use in an Internet standard (RFC 1321), MD5 has been employed or developed in a more variety of security appl…

Windows 7 SID 修改

在安裝Windows系統時會產生一個獨一無二的SID (Security ID)&#xff0c;它用來識別每一部主機&#xff0c;若在同一個區域網路內有兩部相同SID的主機&#xff0c;會出現警告訊息。一般而言&#xff0c;每次安裝時的SID不可能會發生重複&#xff0c;但若是使用TrueImage或Ghost…

1 并发模型

并发系统可以采用多种并发编程模型来实现。并发模型指定了系统中的线程如何通过协作来完成分配给它们的作业。不同的并发模型采用不同的方式拆分作业&#xff0c;同时线程间的协作和交互方式也不相同。这篇并发模型教程将会较深入地介绍目前&#xff08;2015年&#xff0c;本文…

mysql log4jlogger_mybatis结合log4j打印SQL日志

mybatis结合log4j打印SQL日志1.Maven引用jar包默认的mybatis不能打印出SQL日志&#xff0c;不便于查看调试&#xff0c;须要结合log4jdbc-log4j2就能够完整的输入SQL的调试信息。pom.xml 配置maven。注意以下3个都须要org.bgee.log4jdbc-log4j2log4jdbc-log4j2-jdbc4.11.16org.…

cellpadding_在CSS中设置cellpadding和cellspacing

cellpaddingIntroduction: 介绍&#xff1a; It is not unknown anymore that now and then we make use of tables in our web page or website, therefore we all are familiar with how to create tables or grids in our website or web page but there are times when we…

mongodb 排序_技术分享 | MongoDB 一次排序超过内存限制的排查

本文目录&#xff1a;一、背景1. 配置参数检查2. 排序字段是否存在索引二、测试环境模拟索引对排序的影响1. 测试环境信息2. 报错语句的执行计划解释 3. 建立新的组合索引进行测试三、引申的组合索引问题1. 查询语句中&#xff0c;排序字段 _id 使用降序2. 查询语句中&#xff…

spark源码分析之Executor启动与任务提交篇

任务提交流程 概述 在阐明了Spark的Master的启动流程与Worker启动流程。接下继续执行的就是Worker上的Executor进程了&#xff0c;本文继续分析整个Executor的启动与任务提交流程Spark-submit 提交一个任务到集群通过的是Spark-submit通过启动脚本的方式启动它的主类&#xff0…

mysql 5.5.22.tar.gz_MySQL 5.5.22源码编译安装

MySQL 最新的版本都需要cmake编译安装&#xff0c;估计以后的版本也会采用这种方式&#xff0c;所以特地记录一下安装步骤及过程&#xff0c;以供参考。注意&#xff1a;此安装是默认CentOS下已经安装了最新工具包&#xff0c;比如GNU make, GCC, Perl, libncurses5-dev&#x…

利用python进行数据分析D2——ch03IPython

为无为,事无事,味无味。大小多少,报怨以德。图难于其易,为大于其细;天下难事必作于易,天下大事必作于细。——老子关于图片的例子&#xff1a;import matplotlib.pyplot as plt imgplt.imread(ch03/stinkbug.png) import pylab plt.imshow(img) pylab.show()结果&#xff1a;调…

mysql 视图 字典_MySQL深入01-SQL语言-数据字典-服务器变量-数据操作DML-视图

SQL语言的组成部分常见分类&#xff1a;DDL&#xff1a;数据定义语言DCL&#xff1a;数据控制语言&#xff0c;如授权DML&#xff1a;数据操作语言其它分类&#xff1a;完整性定义语言&#xff1a;DDL的一部分功能约束约束&#xff1a;包括主键&#xff0c;外键&#xff0c;唯一…

为什么我会被淘汰?

这是一个值得讨论的问题。华为前段时间也传出了大规模裁员的一些负面新闻&#xff0c;一时间搞的人心惶惶。总结起来说&#xff0c;还是怕失去这份赖以生存的工作&#xff0c;尤其是对于上有老下有小的中年人来说&#xff0c;工作尤为重要。 淘汰&#xff0c;是软件行业不变的真…

mysql 存储过程死循环_pl/sql存储过程loop死循环

今早&#xff0c;一个存储过程&#xff0c;写过很多次的存储过程&#xff0c;随手一写&#xff0c;各种报错&#xff0c;各种纠结&#xff0c;网上一搜&#xff0c;有好多个都遇到&#xff0c;论坛上给出的结局答案&#xff0c;今早&#xff0c;一个存储过程&#xff0c;写过很…