欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > 高并发场景下的数据库优化

高并发场景下的数据库优化

2025/3/10 10:22:13 来源:https://blog.csdn.net/u012561308/article/details/146014225  浏览:    关键词:高并发场景下的数据库优化

在高并发系统中,数据库通常是性能瓶颈。面对高并发请求,我们需要采用合适的优化策略,以保证数据库的稳定性和高效性。本文将介绍数据库高并发问题的成因,并结合 Mybatis-Plus,探讨 乐观锁、悲观锁、高并发优化及数据库连接池优化 的最佳实践。


1. 数据库高并发问题分析

1.1 高并发数据库问题的常见表现

  • 数据库连接耗尽:过多的并发请求导致数据库连接池资源被占满,新的请求无法获取连接。
  • 锁竞争严重:多个事务对同一行或同一表的数据竞争锁,导致等待时间变长,甚至发生死锁。
  • 读写压力过大:业务场景下 大量写操作(INSERT、UPDATE)查询操作(SELECT) 导致数据库压力增大,影响系统响应时间。
  • 数据不一致:并发修改同一数据时,可能导致数据丢失或覆盖,产生 脏读、幻读、不可重复读 等问题。

2. 乐观锁与悲观锁的使用

在高并发场景下,数据库并发控制策略主要分为 乐观锁悲观锁
在高并发场景下,数据库并发控制策略主要分为 乐观锁悲观锁

2.1 乐观锁

适用场景:适用于 读多写少 的场景,例如 订单支付状态修改、库存扣减 等。

实现方式

  • 通过 版本号机制(Version) 进行更新。
  • UPDATE 时,带上 version 条件,只有 version 匹配时才更新成功,否则更新失败。

Mybatis-Plus 乐观锁实现

  1. 在实体类中增加 @Version 注解
@Data
@TableName("user")
public class User {@TableId(type = IdType.AUTO)private Long id;private String name;private Integer age;@Version  // 版本号字段private Integer version;
}
  1. 开启 Mybatis-Plus 乐观锁插件
    MybatisPlusConfig 配置类中启用 乐观锁插件
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}
  1. 更新时,Mybatis-Plus 自动维护版本号
@Autowired
private UserMapper userMapper;public void updateUserAge(Long userId) {User user = userMapper.selectById(userId);user.setAge(user.getAge() + 1);userMapper.updateById(user); // Mybatis-Plus 会自动带上 version 字段
}

如果 version 发生变化,更新失败,需要重新读取数据再更新。


2.2 悲观锁

适用场景:适用于 写多读少、强一致性 场景,例如 金融交易、订单扣款 等。

实现方式

  • SELECT … FOR UPDATE:在事务内查询数据并加锁,防止其他事务修改数据。
  • 使用数据库本身的行锁(Row Lock)

示例:使用 FOR UPDATE 进行悲观锁控制

@Select("SELECT * FROM user WHERE id = #{id} FOR UPDATE")
User selectForUpdate(Long id);
  • 事务提交前,其他事务无法修改该行数据。
  • 适用于事务范围内需要严格一致性的操作。

缺点

  • 如果锁住的数据较多,会导致 大量事务等待,影响并发能力。

3. Mybatis-Plus 高并发优化实践

3.1 批量插入

在高并发写入场景下,逐条 INSERT 可能会导致 SQL 频繁执行,影响性能。Mybatis-Plus 提供了 批量插入 的方式:

@Autowired
private UserMapper userMapper;public void batchInsertUsers(List<User> users) {userMapper.insertBatchSomeColumn(users);
}

注意insertBatchSomeColumn 需要开启 Mybatis-Plus 扩展插件。


3.2 避免 N+1 查询

问题:当查询列表数据时,可能会引发多次 SQL 查询:

List<Order> orders = orderMapper.selectList(null);
for (Order order : orders) {User user = userMapper.selectById(order.getUserId());
}

解决方案

  • 使用 IN 查询 一次性获取所有用户数据:
List<Long> userIds = orders.stream().map(Order::getUserId).collect(Collectors.toList());
List<User> users = userMapper.selectBatchIds(userIds);
  • 使用 Mybatis-Plus 关联查询
@Select("SELECT o.*, u.name as userName FROM orders o JOIN user u ON o.user_id = u.id WHERE o.id = #{orderId}")
OrderWithUser selectOrderWithUser(Long orderId);

4. 数据库连接池优化

数据库连接池(DataSource)是高并发优化的核心组件,推荐使用 Druid 或 HikariCP

4.1 HikariCP 连接池优化

application.yml 配置:

spring:datasource:url: jdbc:mysql://localhost:3306/testusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driverhikari:minimum-idle: 10maximum-pool-size: 50idle-timeout: 30000max-lifetime: 1800000connection-timeout: 3000

参数解析

  • maximum-pool-size: 连接池最大连接数,通常设置为 CPU 核心数 * 2 + 1
  • minimum-idle: 最小空闲连接数。
  • connection-timeout: 获取连接的超时时间(建议不超过 3 秒)。
  • max-lifetime: 连接最大存活时间,防止长时间占用连接。

5. 总结

优化点方法适用场景
并发控制乐观锁 @Version读多写少,如库存扣减
悲观锁SELECT ... FOR UPDATE高一致性,如订单扣款
批量插入insertBatchSomeColumn()大批量数据插入
避免 N+1 查询IN 查询、Mybatis-Plus 关联查询避免多次查询
连接池优化HikariCP提高数据库连接管理效率

在高并发场景下,数据库优化是一个系统性工程。合理选择 乐观锁/悲观锁、批量插入、数据库连接池优化,可以极大提高数据库吞吐能力,确保系统在高并发下依然稳定高效!🚀

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词