当前位置: 首页 > wzjs >正文

网站怎样做漂浮深圳推广公司推荐

网站怎样做漂浮,深圳推广公司推荐,公司做网站广告语,win7系统可以做网站吗目录 一、问题分析 1.1按惯例贴异常: 二、问题定位 2.1结合实际 2.2问题剖析 三、问题解答 3.1.加乐观锁 3.2.分布式锁。 一、问题分析 1.1按惯例贴异常: 187891478:618:46:21 187891478 X RECORD *****.charge_order idx_charge_order …

目录

一、问题分析

1.1按惯例贴异常:

二、问题定位 

2.1结合实际 

 2.2问题剖析

三、问题解答

3.1.加乐观锁

3.2.分布式锁。


一、问题分析

1.1按惯例贴异常:
187891478:618:46:21  187891478  X  RECORD  `*****`.`charge_order`  idx_charge_order  618  46  21  1, 0x99B18692C4, 2, 25, 771, 365

上面的异常可以通过mysql 语句:SHOW ENGINE INNODB STATUS可查到,它展示的是InnoDB 的锁信息。逐字逐句分析:

  • 187891478:618:46:21 是锁持有事务的表空间ID、页号和槽位。

  • 187891478 是事务ID。

  • X 表示该锁是 排他锁(Exclusive Lock)

  • RECORD 表示锁的是 记录锁

  • ***.charge_order 是表名。

  • idx_charge_order 是锁对应的索引。

  • 后面的数字如 1, 0x99B18692C4, 2, 25, 771, 365 是被锁定的记录内容的键值(被加锁的索引键)。

二、问题定位 

 主要的问题

  • 多个事务加锁同一条记录

    • 多个事务持有相同页的锁(例如 618:46:21,被多个事务锁住):

      187891478 187891319 187891257 187831733

      都在 idx_charge_order 索引的同一位置上加了锁,极有可能是争抢同一条数据,导致锁等待。

  • 联合索引或非主键更新

    • idx_charge_order 表示加锁操作通过 非主键索引 进行的。可能是某个字段上的查询或更新导致了间隙锁记录锁

    • 使用非唯一索引更新数据时,MySQL 会加锁相关记录,以防止幻读。

  • 行锁 + GAP 锁混合引发的死锁

    • 如果你用的是 SELECT ... FOR UPDATE 或者更新时条件不是主键,很可能会在 InnoDB 的 Next-Key Locking 策略下加上间隙锁,进而引发死锁。

  • 事务未及时提交

    • 如果多个事务对同一条记录加锁,且长时间未提交,会造成阻塞,甚至死锁。

2.1结合实际 

 那根据我自己的项目分析主要是因为定时任务叠加请求同一个接口,这个接口用了  FOR UPDATE去查询而后这个接口再进行更新。

 public void processChargingNew(OrderEntity order) {TransactionStatus transactionStatus = null;try {// 查询并加锁 charge_order 表的记录LambdaQueryWrapper<ChargeOrderEntity> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(ChargeOrderEntity::getOrderId, order.getId()).eq(ChargeOrderEntity::getIsValid, Constants.VALID).last("LIMIT 1 FOR UPDATE"); // 限制只锁一行ChargeOrderEntity chargeOrderEntity = baseMapper.selectOne(queryWrapper);if (chargeOrderEntity == null) {log.warn("充电订单不存在,orderId={}", order.getId());return;}这边省略业务逻辑……// 更新订单状态为启动中updateChargeOrderStart(chargeOrderEntity.getOrderId(), station.getId(), chargeOrderEntity);
 2.2问题剖析

1.selectOne(... FOR UPDATE) 出现在事务开启前

ChargeOrderEntity chargeOrderEntity = baseMapper.selectOne(queryWrapper); // 含 FOR UPDATE
...
transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
 

FOR UPDATE 需要在数据库事务中执行才有效!在事务开始 之前 加的锁,这意味着该锁 不是在一个有效事务上下文中产生的,实际效果不可靠,甚至不同线程间产生锁等待却得不到释放,导致死锁。 

因为定时任务每3秒会执行一次导致多个线程同时调用 这个接口,并且他们抢的是同一个 order.getId(),那么他们都会尝试 FOR UPDATE 相同的记录,哪怕只加锁一行,也可能形成排他锁等待队列

  • 如果前一个事务迟迟不提交(比如卡在业务逻辑的网络通信或外部设备响应),其他线程将被阻塞。

  • 一旦另一个线程在等待过程中,也去锁别的资源(比如 Redis、充电站表等),就很容易出现“循环等待” → 死锁。

三、问题解答

我的方案措施:

3.1.加乐观锁
  • 如果只是为了防止并发更新同一条订单数据,可以用乐观锁(如版本号 version 字段 + where version = ?)来实现并发控制。这里有个细节就是项目必须是Spring Boot 集成 MyBatis-Plus,配置乐观锁插件。

  • Spring Boot + MyBatis-Plus 项目结构

    <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.x</version>
    </dependency>
    

    需要在 配置类 中添加一个 @Bean,如下

    @Configuration
    public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
    }
    

    放在任何一个 @Configuration 类里都可以,比如项目里的 MyBatisPlusConfig.java 或者 PersistenceConfig.java 等。


    注意事项:

  • MyBatis-Plus 3.4.x 以前版本 用的是旧插件注册方式。

  • 新版 3.5.x 起,都统一使用 MybatisPlusInterceptor 插件机制。

  • 插件加载顺序重要,如果还有分页插件,也得放进去,比如:

interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

配好之后,使用方式不变 

@Version
private Integer version;

 代码示例:

// 查询并加锁 charge_order 表的记录
LambdaQueryWrapper<ChargeOrderEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ChargeOrderEntity::getOrderId, order.getId()).eq(ChargeOrderEntity::getIsValid, Constants.VALID).last("LIMIT 1");// 去掉 FOR UPDATE,改用乐观锁ChargeOrderEntity chargeOrderEntity = baseMapper.selectOne(queryWrapper);

 只要调用 updateById() 等方法,MyBatis-Plus 自动帮你在 SQL 加上 version = ? 的条件并做自增。(大功告成!!)

3.2.分布式锁。

// 调整顺序:
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
try {
    // 查询并加锁必须放在事务内
    ChargeOrderEntity chargeOrderEntity = baseMapper.selectOne(
        new LambdaQueryWrapper<ChargeOrderEntity>()
            .eq(ChargeOrderEntity::getOrderId, order.getId())
            .eq(ChargeOrderEntity::getIsValid, Constants.VALID)
            .last("LIMIT 1 FOR UPDATE")
    );

    // 其余逻辑...
 

 如果是多实例部署(集群中多个服务节点同时跑这个定时任务)这种情况下就建议加上Redis 分布式锁,防止多个节点同时处理同一个订单。可以在任务开始时做类似以下锁控制:

String lockKey = "prepare:charge:order:" + order.getId();
boolean isLocked = redisUtils.tryLock(lockKey, 0, 30); // 不等待,锁30秒
if (!isLocked) {log.info("订单正在处理,跳过 orderId={}", order.getId());return null;
}try {// 执行业务逻辑} finally {redisUtils.releaseLock(lockKey);
}

这样可以防止集群中多个任务节点同时操作同一条订单。

http://www.dtcms.com/wzjs/143443.html

相关文章:

  • 自己做博客网站如何在百度上添加自己的店铺
  • java网站建设兼职南宁排名seo公司
  • 电商网站的功能有哪些seo教程搜索引擎优化
  • wordpress admin南京seo优化培训
  • 帝国cms做下载网站百度查一下
  • 给网站做推广快速排名生客seo
  • 什么是网站版面布局手机网站自助建站系统
  • 114查询seo关键词查询工具
  • 网页设计班级网站怎么做国家认可的教育培训机构
  • 手机电脑同步wordpress厦门网站综合优化贵吗
  • 莱芜论坛二手车seo快速排名软件品牌
  • 永康物流网站百度sem是什么
  • 网站建设优化网站排名百度灰色关键词排名代做
  • 有没有帮忙做推广的网站网站广告投放价格表
  • 正规网站模板设计图百度官方
  • 做网站app怎么赚钱个人如何注册网站
  • 广州做网站海珠信科网站建设的基本流程
  • 雄安个人代做网站排名百度怎么进入官方网站
  • 北京做网站定制价格chrome下载
  • 网站 内页模板之家
  • 做购物类网站有哪些软文写作的十大技巧
  • 网站建设方案书要怎么样写最新新闻消息
  • 上海seo公司bwyseo怎么做网站关键词优化
  • 宁夏做网站的公司全网营销推广方案
  • 网站如何制作做吸引客户免费推广工具
  • 金华网站建设开发李守洪
  • 山西武汉网站建设免费的网络营销方式
  • 上海网页制作找哪家免费seo刷排名
  • 集团网站建设案例西安百度推广怎么做
  • 义乌网站建设联系方式小说网站排名