商城订单模块实战 - 数据库设计、ABA问题处理、读写分离分库分表

引言

订单系统可以说是整个电商系统中最重要的一个子系统,因此订单数据可以算作电商企业最重要的数据资产。这篇文章我们来看看在我们的商城系统中订单服务是如何实现的,特别是在设计和实现一个订单系统的过程中有哪些问题是需要特别考虑的。

业务分析

订单系统业务分析

对于一个合格的订单系统,最基本的要求是什么?数据不能出错。用户的每一次购物,从下单开始到支付、发货,再到收货,流程中的每个环节,都需要同步更新订单数据,每次更新操作可能都需要同时更新好几张表。这些操作可能会随机分发到不同的服务器节点上执行,服务器或网络都有可能会出问题,在这么复杂的情况下,如何保证订单数据不出错呢?

  • 第一,代码必须是正确的没有Bug,当然这个要求很简单也很复杂,全是bug系统无法正常运行,但是也没有什么系统能保证没有一个bug。当然要确保不能因为代码Bug而导致数据错误。
  • 第二,要能够正确地使用事务。比如,在创建订单的时候,如果需要同时在订单表和订单商品表中插入数据,那么我们必须在一个数据库事务中执行这些插入数据的INSERT 语句,数据库事务可以确保:执行需要同时进行的操作语句时,要么一起成功,要么一起失败。而实际上,在微服务下,仅仅使用数据库事务是不够的,很多时候还需要分布式事务。后面课程会专门的讲解分布式事务在项目中的实现。

即使满足了上面列举的这两个基本要求,某些特殊情况也仍然可能会引发数据错误,是什么样的数据错误问题?如何解决呢?都都会在后续讲述

在此之前,我们需要首先了解对于一个订单系统而言,它的核心功能和数据结构是怎样的。其实任何一个公司的电商系统,其订单系统的功能都是独一无二的,因为订单系统会基于其业务配置了很多的功能,并且都很复杂。因此我们的电商系统只能化繁为简,聚焦那些最核心的、共通的业务功能和数据模型,并且以此为基础讨论其中的实现技术。

订单系统的核心功能和数据表

为了支撑订单模块的必备功能,一般订单数据库中至少需要具备如下4张表。

  • 订单主表:也称订单表,用于保存订单的基本信息,也就是我们的order表。
  • 订单商品表:用于保存订单中的商品信息,也就是我们的order_item表。
  • 订单支付表:用于保存订单的支付和退款信息。
  • 订单优惠表:用于保存订单使用的所有优惠信息。

这4张表之间的关系是订单主表与后面的几个子表都是一对多的关系,关联的外键就是订单主表的主键,即订单ID。

在我们的商城系统中,做了适度的改造和简化,表现在:
因为取消了一般的促销优惠,自然没有专门的订单优惠表;
订单的是否支付和是否退款直接保存在订单主表中,没有设计单独订单支付表用以保存支付和退款相关信息;
我们系统中没有单独的库存系统,所以库存扣减由订单系统发起,由产品服务执行实际的扣减库存操作。
对应到存储上,则是oms_order作为订单主表,其中的status字段表示了订单状态,包括

0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单

产品的库存则是保存在产品服务product对应数据库tl_goods的sku_stock表中。

从上面我们对订单的流程描述来看,订单系统的实现其实并不复杂,就是标准的CRUD。

但是前面我们也说过,某些情况也仍然可能会引发数据错误,是哪些情况呢?我们来一一分析下。

订单重复下单问题

仔细分析一下订单创建的场景:订单系统为用户提供创建订单的HTTP接口,用户在浏览器页面上点击“提交订单”按钮,浏览器向订单系统发送一条创建订单的请求,订单系统的后端服务收到请求,向数据库的订单表中插入一条订单数据,至此,订单创建成功。

那么我们设想一下,用户在点击“提交订单”的按钮时,不小心点了两下,那么浏览器就会向服务端连续发送两条创建订单的请求,最终的结果将会是什么?很自然会创建两条一模一样的订单。这样肯定是不行的,因此我们还需要做好防重工作,怎么做呢?

可能有人会想到,前端页面上应该防止用户重复提交表单,当用户“提交订单”的按钮后,将该按钮置灰不可用。但是仔细想想,即使前端控制了用户不重复提交,网络错误也有可能会导致重传,很多RPC框架和网关都拥有自动重试机制,所以对于订单服务来说,重复请求的问题是客观存在的。

解决办法是,让订单服务具备幂等性。什么是幂等性?幂等操作的特点是,操作任意多次执行所产生的影响,均与一次执行所产生的影响相同。也就是说,对于幂等方法,使用同样的参数,对它进行多次调用和一次调用,其对系统产生的影响是一样的。

例如:

update tableA set count = 10 where id = 1

这个操作多次执行,id 等于1的记录中的 count字段的值都为10,这个操作就是幂等的,我们不用担心这个操作被重复。

update tableA set count = count + 1 where id = 1;

这样的SQL操作就不是幂等的,一旦重复,结果就会产生变化。

所以,不用担心幂等方法的重复执行会对系统造成任何改变。如果创建订单的服务具备幂等性,那么无论创建订单的请求发送了多少次,正确的结果都是数据库只有一条新创建的订单记录。

这里又会涉及一个不太好解决的问题:对于订单服务来说,如何判断收到的创建订单的请求是不是重复请求呢?

在插入订单数据之前,先查询一下订单表里面有没有重复的订单,是不是就可以做出判斯了呢?这个方法看起来容易。实际上却很难实现。原因是我们很难通过SQL的WHERE语句来定义“重复的订单”,如果订单的用户、商品、数量和价格都一样,是否就能认为它们是重复订单呢?这个其实是无法确定的,因为有可能用户就是连续下了两个一模一样的订单。

这个问题的思路是利用数据库的唯一约束来判断数据是否重复。在数据库的最佳实践中,其中一条是要求数据库的每个表都有主键。在非分库分表的情况下,我们在向数据库的表中插入一条记录的时候,无需提供主键,插入的同时由数据库自动生成一个主键。这样,重复的请求就会导致插入重复的数据。

表的主键是自带唯一约束的,如果我们在一条INSERT语句中提供了主键,并且这个主键的值已经存在于表中,那么这条INSERT语句就会执行失败,数据也不会成功插入表中。我们可以利用数据库的这种“主键唯一约束”特性,在插入数据的时候带上主键,来解决创建订单服务的幂等性问题。

具体做法如下:首先,为订单系统增加一个“生成订单号”的服务,这个服务没有参数,返回值就是一个新的、全局唯一的订单号。在用户进入创建订单的页面时,前端页面会先调用这个生成订单号的服务得到一个订单号,在用户提交订单的时候,在创建订单的请求中带着这个订单号。

这个订单号就是订单表的主键,这样,无论是用户原因,还是网络原因等各种情况导致的重试,这些重复请求中的订单号都是相同的。订单服务在订单表中插入数据的时候,这些重复的INSERT语句中的主键,都是同一个订单号。数据库的主键唯一约束特性就可以保证,只有一次INSERT语句的执行是成功的,这样就实现了创建订单服务的幂等性。

时序图如下:
在这里插入图片描述

所以,可以看到,在PortalOrderController中专门提供了generateOrderId方法供外部系统获得订单ID。

而秒杀系统相关的微服务中虽然没有提供类似的generateOrderId方法,但依然注意了避免重复下单问题,在生成订单确认信息时,将预先生成的订单ID传递给了前端订单确认页。

还有一点需要注意的是,在具体实现时,如果是因为重复订单导致插入订单表的语句失败,那么订单服务就不要再把这个错误返回给前端页面了。否则,就有可能会出现用户点击创建订单按钮后,页面提示创建订单失败,而实际上订单已经创建成功了。正确的做法是,遇到这种情况,订单服务直接返回“订单创建成功”的响应即可。
要做到这一点,可以捕获java.sql.SQLIntegrityConstraintViolationException或者org.springframework.dao.DuplicateKeyException来实现。

订单ABA问题和解决

订单系统中,各种更新订单的服务同样也需要具备幂等性。

更新订单的服务,比如支付、发货等这些步骤中的更新订单操作,最终都会落到订单库上,都是对订单主表进行更新操作。

比如对支付操作的数据库的更新操作、无论是执行一次还是重复执行多次,订单状态都是已支付,不用我们额外设置任何逻辑,这就是天然幂等性。

在实现这些更新订单的服务时,还有哪些问题需要特别注意呢?在并发环境下,我们需要特别注意ABA问题。

什么是更新下的ABA问题呢?我们知道并发编程下的CAS有ABA问题,这个ABA问题和并发的ABA问题有相似之处。我们来看这么一个例子:
订单支付完成,填入物流单号666提交后,发现填错了,修改成正确的单号888,对于订单服务来说,这里就产生了两个更新订单的请求。
按照我们的设想,正常情况下,订单中的快递单号会先更新成666,再更新成888,这是没有问题的。但是现实生活有很多不正常的情况,比如,更新成666的请求到了,快递单号更新成666,然后更新成888的请求到了,快递单号又更新成888。但是订单服务在向调用方返回666更新成功的响应时,这个响应在网络传输过程中丢失了。如果调用方没有收到成功响应,触发自动重试逻辑,再次发起更新成666的请求,快递单号将会再次更新成666,这种情况下数据显然就会出错了。这就是ABA问题。

那么ABA问题应该怎么解决呢?仔细想想并发编程里怎么解决ABA问题的?版本戳。所以这里同样可以使用版本戳。

为订单主表增加一列,列名可以叫 version、也就是“版本号”的意思。每次查询订单的时候,版本号需要随着订单数据返回给页面。页面在更新数据的请求时,需要把该版本号作为更新请求的参数再带回给订单更新服务。

订单服务在更新数据的时候需要比较订单当前数据的版本号与消息中的版本号是否一致,如果不一致就拒绝更新数据。如果版本号一致,则还需要在更新数据的同时,把版本号加1。当然需要特别注意的是,“比较版本号、更新数据和把版本号加1”这个过程必须在同一个事务里面执行,只有这一系列操作具备原子性,才能真正保证并发操作的安全性。

具体的SQL语句参考如下:

UPDATE orders set tracking_number = 666,version = version + 1 WHERE version = ?;

版本号的机制可用于保证,从打开某条订单记录开始,一直到这条订单记录更新成功,这期间不会存在有其他人修改过这条订单数据的情况。因为如果被其他人修改过,数据库中的版本号就会发生改变,那么更新订单的操作就不会执行成功,而只能重新查询新版本的订单数据,然后再尝试更新。

所以可以看到,在order中专门设计了version字段:
在这里插入图片描述

但是因为牵涉到更新订单的操作未执行成功(表现为update语句返回行数为0)时的重试机制,代码修改较大,所以在OmsOrderMapper.xml和相关订单业务方法中没有实现上述的ABA解决方案,感兴趣的同学可以自行调整。

总的来说,因为网络、服务器等导致的不确定因素,重试请求是普遍存在且不可避免的问题。具有幂等性的服务可以克服由于重试问题而导致的数据错误。

所以,总的来说,对于创建订单的服务,可以通过预先生成订单号作为主键,然后利用数据库中“主键唯一约束”的特性,避免重复写入订单,实现创建订单服务的幂等性。对于更新订单的服务,可以通过一个版本号机制,即在每次更新数据之前校验版本号,以及在更新数据的同时自增版本号这样的方式来解决ABA问题,以确保更新订单服务的幂等性。

通过这样两种具备幂等性的实现方法,我们可以保证,无论是不是重复请求,订单表中的数据都是正确的。

当然这里讲到的实现订单幂等性的方法,在其他需要实现幂等性的服务中也完全可以套用,只需要这个服务操作的数据保存在数据库中,并且数据表带有主键即可。

实现服务幂等性的方法,远不止本章介绍的这两种,其实,实现幂等性的方法可分为两大类,一类是通过一些精巧的设计让更新本身就是幂等的,这种方法并不能适用于所有的业务。另一类是利用外部的具备一致性的存储(比如 MySQL)来做冲突检测,在设计幂等方法的时候,通常可以顺着这两个思路来展开。

读写分离与分库分表

使用Redis 作为MySQL的前置缓存,可以帮助MySQL挡住绝大部分的查询请求。这种方法对于像电商中的商品系统、搜索系统这类与用户关联不大的系统、效果特别好。因为在这些系统中、任何人看到的内容都是一样的,也就是说,对后端服来说,任何人的查询请求和返回的数据都是一样的。在这种情况下,Redis 缓存的命中率非常高,几乎所有的请求都可以命中缓存。

但是与用户相关的系统(不是用户系统本身,用户信息等相关数据在用户登录时进行缓存,就价值很高),使用缓存的效果就没有那么好了,比如,订单系统、账户系统、购物车系统、订单系统等等。对于这些系统而言,各个用户查询的信息与用户自身相关,即使同一个功能界面,用户看到的数据也是不一样的。

比如,“我的订单”这个功能,用户看到的都是自己的订单数据。在这种情况下,缓存的命中率就比较低了,会有相当一部分查询请求因为命中不了缓存,穿透到 MySQL 数据库中。

随着系统的用户数量越来越多,穿透到MySQL 数据库中的读写请求也会越来越多,当单个MySQL支撑不了这么多的并发请求时,该怎么办?

读写分离

读写分离是提升 MySQL 并发能力的首选方案,当单个MySQL无法满足要求的时候,只能用多个MySQL实例来承担大量的读写请求。MySQL与大部分常用的关系型数据库一样,都是典型的单机数据库,不支持分布式部署。用一个单机数据库的多个实例组成一个集群,提供分布式数据库服务,是一件非常困难的事情。

一个简单且非常有效的是用多个具有相同数据的MySOL实例来分担大量查询请求,也就是“读写分离”。很多系统,特别是互联网系统,数据的读写比例严重不均衡,读写比例一般在9:1到几十比1,即平均每发生几十次查询请求,才会有一次更新请求,那就是说数据库需要应对的绝大部分请求都是只读查询请求。

分布式存储系统支持分布式写是非常困难的,因为很难解决好数据一致性的问题。但分布式读相对来说就简单得多,能够把数据尽可能实时同步到只读实例上,它们就可以分担大量的查询请求了。

读写分离的另一个好处是,实施起来相对比较简单。把使用单机MySQL的系统升级为读写分离的多实例架构非常容易,一般不需要修改系统的业务逻辑,只需要简单修改DAO (Data Access Object,一般指应用程序中负责访问数据库的抽象层)层的代码,把对数据库的读写请求分开,请求不同的MySQL实例就可以了。通过读写分离这样一个简单的存储架构升级,数据库支持的并发数量就可以增加几倍到十几倍。所以,当系统的用户数越来越多时,读写分离应该是首要考虑的扩容方案。

在这里插入图片描述

主库负责执行应用程序发来的数据更新请求,然后将数据变更同步到所有的从库中。这样,主库和所有从库中的数据一致,多个从库可以共同分担应用的查询请求。

读写分离的数据不一致问题

读写分离的一个副作用是,可能会存在数据不一致的问题。原因是数据库中的数据在主库完成更新后,是异步同步到每个从库上的,这个过程会有一个微小的时间差。正常情况下,主从延迟非常小,以几毫秒计。但即使是这样小的延迟,也会导致在某个时刻主库和从库上数据不一致的问题。

应用程序需要能够接受并克服这种主从不一致的情况,否则就会引发一些由于主从延迟而导致的数据错误。

回顾我们的订单系统业务,用户对购物车发起商品结算创建订单,进入订单页,打开支付页面进行支付,支付完成后,按道理应该再返回到支付之前的订单页。但如果这时马上自动返回到订单页,就很有可能会出现订单状态还是显示“未支付”的问题。因为支付完成后,订单库的主库中订单状态已经更新了,但订单页查询的从库中这条订单记录的状态可能还未更新,如何解决这种问题呢?

其实这个问题并没有特别好的技术手段来解决,所以可以看到,稍微上点规模的电商网站并不会支付完成后自动跳到到订单页,而是增加了一个支付完成页面,这个页面其实没有任何新的有效信息,就是告诉你支付成功的信息。如果想再查看一下刚刚支付完成的订单,需要手动选择,这样就能很好地规避主从同步延迟的问题。

如果是那些数据更新后需要立刻查询的业务,这两个步骤可以放到一个数据库事务中,同一个事务中的查询操作也会被路由到主库,这样就可以规避主从不一致的问题了,还有一种解决方式则是对查询部分单独指定进行主库查询。

总的来说,对于这种因为主从延迟而带来的数据不一致问题,并没有一种简单方便且通用的技术方案可以解决,对此,我们需要重新设计业务逻辑,尽量规避更新数据后立即去从库查询刚刚更新的数据。

分库分表

除了访问MySQL的并发问题,还要解决海量数据的问题,很多的时候,我们会使用分布式的存储集群,因为MySQI本质上是一个单机数据库,所以很多场景下,其并不适合存储TB级别以上的数据。

但是绝大部分电商企业的在线交易类业务,比如订单、支付相关的系统,还是无法离开MySQL的。原因是只有MySOL 之类的关系型数据库,才能提供金融级的事务保证。目前的分布式事务的各种解法方案多少都有些不够完善。

虽然 MySQL 无法支持这么大的数据量,以及这么高的并发需求,但是交易类系统必须用它来保证数据一致性,那么,如何才能解决这个问题呢?这个时候我们就要考虑分片,也就是拆分数据。

如果一个数据库无法支撑1TB的数据,那就把它拆分成100个库,每个库就只有10GB的数据了。这种拆分操作就是MySOL的分库分表操作。

如何规划分库分表

以订单表为例,首先,我们需要思考的问题是,选择分库还是分表,或者两者都有,分库就是把数据拆分到不同的MySQL 数据库实例中,分表就是把数据拆分到一个数据库的多张表里面。

在考虑到底是选择分厍还是分表之前,我们需要首先明确一个原则,那就是能小拆就小非,能少抖就小多拆。原因很简单,数据拆得越分散,并发和维护就越麻烦,系统出问题的概率也就越大。

遵循上面这个原则,还需要进一步了解,哪种情况适合分表,哪种情况适合分库。选择分厍或是分表的目的是解决如下两个问题。

第一,是为了解决因数据量太大而导致查询慢的问题。这里所说的“查询”,其实主要是事务中的查询和更新操作,因为只读的查询可以通过缓存和主从分离来解决。分表主要用于解决因数据量大而导致的查询慢的问题。

第二,是为了应对高并发的问题。如果一个数据库实例撑不住,就把并发请求分散到多个实例中,所以分库可用于解决高并发的问题。
简单地说,如果数据量太大,就分表;如果并发请求量高,就分库。一般情况下,我们的解决方案大都需要同时做分库分表,我们可以根据预估的并发量和数据量,分别计算应该拆分成多少个库以及多少张表。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【笔记】cuda大师班1-4

一.基本概念 进程(process)一个正在被执行的计算机程序的实例 上下文(context):待处理数据的集合,允许处理器暂停,保持处理的执行和恢复处理 并发:上下文切换,主要应用于…

二叉搜索树中的众数

1题目 给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。 如果树中有不止一个众数,可以按 任意顺序 返回。 假定 BST 满足如下定义&…

用Python分析周杰伦歌曲并进行数据可视化

大家好,今天我们用python分析下周杰伦歌曲。为了尽量完整地呈现从原始数据到可视化的过程,接下来我们会先简单讲解数据的预处理过程,即如何将 JSON 数据转化为Excel 格式,以及如何对周杰伦的歌曲进行分词。 本案例中的歌词数据来…

对顶堆模板!!【DS对顶堆】ABC281 E - Least Elements

我想的思路和正解是差不多的 就是滑动窗口,每过去一个用DS维护一下前k个元素和sum 本来想的是用优先队列维护前k个 然后想着multiset维护前k个,但是具体不知道怎么操作 这里用的是multiset维护对顶堆 关于对顶堆,我在寒假的时候总结过 …

从根本上理解Synchronized的加锁过程

作为一个Java开发,对于Synchronized这个关键字并不会陌生,无论是并发编程,还是与面试官对线,Synchronized可以说是必不可少。 在JDK1.6之前,都认为Synchronized是一个非常笨重的锁,就是在之前的《谈谈Java…

ChatGPT真的有那么牛吗?

ChatGPT真的有那么牛吗?ChatGPT真的有那么牛吗? 作为一款大型语言模型,ChatGPT确实具有很高的自然语言处理和生成能力,可以生成流畅、准确和有逻辑性的语言,而且能够理解和回答广泛的问题。 它是目前最先进和最强大的…

八股+面经

文章目录 项目介绍1.不动产项目数据机器学习算法调研图像提取算法调研数据集-ImageNetXceptionVGGInceptionDensenetMobilenet 2.图书项目技术栈面试问题 Java基础反射接口和抽象类MapHashMap v.s Hashtable(5点)ConcurrentHashMap v.s Hashtable(2点)代理模式1. 静态代理2. 动…

Rust - 变量与数据的交互方式(clone)

在上一篇文章中我们介绍了变量与数据的交互方式-move,通过底层原理我们知道Rust 永远也不会自动创建数据的 “深拷贝”。因此,任何 自动的复制可以被认为对运行时性能影响较小。 但是如果我们 确实需要深度复制 String中堆上的数据,而不仅仅…

mitmproxy抓包

0.mitmproxy功能简介 实时拦截、修改 HTTP/HTTPS 请求和响应可保存完整的 http 会话,方便后续分析和重放支持反向代理模式将流量转发到指定服务器支持 macOS 和 Linux上的透明代理模式支持用 Python 脚本对 HTTP 通信进行修改 1. 安装mitmproxy pip3 install mit…

你知道如何使用C语言实现递归吗?

本篇博客会讲解如何使用C语言实现递归,以及2个注意事项。 递归是什么 递归,简单来说,就是自己调用自己。C语言中,可以使用函数来实现递归,也就是让一个函数自己调用自己。举一个简单的例子: 请你求斐波…

考验大家指针功底的时候到了:请问如何理解 (int*)1 + 1 ?

来,猜猜看,这里的执行结果是什么? 这是今天课上的一道理解题,给大家一点点思考时间。 (心里有答案了再往下滑哦) 5 4 3 2 1 . 答案是,报warning!因为%d不是用来输出指针的哈…

PromQL,让你轻松实现监控可视化!快来了解一下吧!

Prometheus 中的一些关键设计,比如注重标准和生态、监控目标动态发现机制、PromQL等。 PromQL 是 Prometheus 的查询语言,使用灵活方便,但很多人不知道如何更好利用它,发挥不出优势。 PromQL主要用于时序数据的查询和二次计算场…

学习系统编程No.23【信号实战】

引言: 北京时间:2023/4/23,最近学习状态不怎么好,总是犯困,没精力的感觉,可能是病没有好彻底的原因,也可能是我内心因为生病而认为摆烂理所应当,反正最后导致摆烂,课现在…

Postman预请求脚本、测试脚本(pre-request scripts、tests常用工作总结)

文章目录 Postman预请求脚本(pre-request scripts工作常用总结)Postman预请求脚本Postman测试脚本预请求脚本和测试脚本有什么区别常用工作总结登录接口返回的是Set-Cookie标头 Postman预请求脚本(pre-request scripts工作常用总结&#xff0…

2008-2019年主要城市PITI指数

2008-2019年主要城市PITI指数 1、来源:附在文件内 2、时间区间:2008-2019年 3、具体时间分布:、2008、2009-2010、2011、2012、2013-2014、2014-2015、2015-2016、2016-2017、2017-2018、2018-2019、 4、范围:包括110个城市&a…

Afkayas.1(★)

软件运行 要输入正确的Name和Serial 查壳 一个VB程序,没有加壳 载入OD 直接开搜索字符串。 这里看到了错误的提示,“You Get It”应该就是成功的字符串了。 前面的“AKA-”应该是在什么时候拼接的字符串 去成功的字符串附近看看 这个字符串上面…

网络编程 总结三

一、并发服务器模型 【1】 循环服务器 1>一次只能处理一个客户端的请求,等待这个客户端退出后,才能处理下一个客户端 2>缺点:循环服务器所处理的客户端不能有耗时操作 //*****模型****** sfd socket(); bind(); listen(); while(1)…

js 操作数组内容

js 操作数组内容 数组添加元素(更改原数组) push和unshift会返回添加了新元素的数组长度 push从数组最后加入,unshift从数组最前面加入 const arr ["a", "b", "c"]; arr.push("d"); //返回4…

【高危】泛微 e-cology <10.57 存在 SQL注入漏洞(POC)(MPS-ndqt-0im5)

漏洞描述 泛微协同管理应用平台(e-cology)是一套企业大型协同管理平台。 泛微 e-cology 受影响版本存在SQL注入漏洞,未经授权的远程攻击者可通过发送特殊的HTTP请求来获取数据库的敏感信息。 漏洞名称GeoServer 存在 sql 注入漏洞漏洞类型SQL注入发现时间2023/4/…

解密PyTorch动态计算图:打破深度学习束缚的秘密武器

❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…