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

用什么l软件做网站了住房和城乡建设部证书查询

用什么l软件做网站了,住房和城乡建设部证书查询,织梦做的相亲网站,搭建网页平台一、业务背景:数据产品的 "定时任务之痛" 我们团队负责一款 ToB 数据产品,核心逻辑是将实时计算平台(如 ODPS)的分析结果同步到 MySQL,供前端 BI 工具快速查询。其中有一张核心表tkn_tb_cinema_show_data&a…

一、业务背景:数据产品的 "定时任务之痛"

我们团队负责一款 ToB 数据产品,核心逻辑是将实时计算平台(如 ODPS)的分析结果同步到 MySQL,供前端 BI 工具快速查询。其中有一张核心表tkn_tb_cinema_show_data(影院排片数据表),表结构如下(关键部分):

sql

CREATE TABLE tkn_tb_cinema_show_data (id BIGINT PRIMARY KEY AUTO_INCREMENT,cinema_id BIGINT COMMENT '影院ID',show_id BIGINT COMMENT '影片ID',now_date VARCHAR(32) COMMENT '统计日期',UNIQUE KEY uid_cinema_show_date (cinema_id, show_id, now_date) -- 联合唯一索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

问题爆发:定时任务的 "死亡循环"

每天凌晨的定时同步任务是数据链路的核心,但最近运维同学反馈:当任务并发量提升至 200 + 线程时,插入成功率从 99% 骤降至 60%,日志中大量出现:

plaintext

com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: 
Deadlock found when trying to get lock; try restarting transaction

DBA 拉取SHOW ENGINE INNODB STATUS死锁日志,关键信息如下:

plaintext

*** (1) TRANSACTION:
TRANSACTION 73278630816, ACTIVE 1 sec inserting
LOCK WAIT 622 lock struct(s), heap size 79400, 743 row lock(s)
LOCKED RECORD indices: uid_cinema_show_date
*** (2) TRANSACTION:
TRANSACTION 73278630826, ACTIVE 0 sec inserting
WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 42 page no 5 n bits 72 index uid_cinema_show_date of table `tkn`.`tkn_tb_cinema_show_data` 
trx id 73278630826 lock_mode X locks gap before rec insert intention waiting

现象矛盾点:明明插入的是不同now_date(统计日期)的记录,为何会出现锁冲突?

二、问题复现:用 Java 代码模拟死锁场景

为定位问题,我们用 Java+Spring Boot 模拟线上环境:

java

// 模拟定时任务的并发插入服务
@Service
public class CinemaDataService {@Autowiredprivate JdbcTemplate jdbcTemplate;// 原始插入逻辑(问题代码)@Transactional(isolation = Isolation.REPEATABLE_READ) // 默认可重复读隔离级别public void batchInsert(List<CinemaShowData> dataList) {String sql = "INSERT INTO tkn_tb_cinema_show_data " +"(cinema_id, show_id, now_date) VALUES (?,?,?)";dataList.forEach(data -> jdbcTemplate.update(sql, data.getCinemaId(), data.getShowId(), data.getNowDate()));}
}// 压测代码(模拟200线程并发)
@Test
void testDeadLock() throws InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(200);// 构造2000条不同now_date的记录(cinema_id=1001, show_id=2001)List<CinemaShowData> dataList = IntStream.range(0, 2000).mapToObj(i -> new CinemaShowData(1001L, 2001L, "2025-05-15-" + i)).collect(Collectors.toList());// 拆分200线程并发插入for (int i = 0; i < 200; i++) {executor.submit(() -> batchInsert(dataList.subList(i*10, (i+1)*10)));}executor.shutdown();executor.awaitTermination(10, TimeUnit.MINUTES);
}

压测结果:10 分钟内抛出 127 次死锁异常,与线上现象完全一致。

三、原理深挖:InnoDB 锁机制的 "隐形冲突"

通过分析 InnoDB 锁机制(参考《MySQL 技术内幕:InnoDB 存储引擎》),问题根源在于唯一索引的插入意向锁(Insert Intention Lock)与 Next-Key Lock 的冲突

1. 关键锁机制回顾

  • 插入意向锁(X IK):插入新记录前,InnoDB 会在目标间隙(Gap)加插入意向锁,表示 "我要插入这里",与其他插入意向锁兼容(不同间隙)。
  • Next-Key Lock(S NK):唯一索引插入时,InnoDB 会先执行唯一性检查(防止重复),此时会加 S 型 Next-Key Lock(记录锁 + 间隙锁),锁范围为(上一记录, 当前记录]

2. 死锁场景推演

假设唯一索引(cinema_id=1001, show_id=2001)已有记录now_date='2025-05-15-0',两个并发事务 T1、T2 分别插入now_date='2025-05-15-1'now_date='2025-05-15-2'

  1. T1 执行唯一性检查,加 S 型 Next-Key Lock 锁间隙('2025-05-15-0', +∞)
  2. T2 同时执行唯一性检查,同样尝试加 S 型 Next-Key Lock 锁同一间隙;
  3. InnoDB 中 S 型 Next-Key Lock 在间隙锁场景下互斥(防止幻读),T1 和 T2 互相阻塞;
  4. 此时 T1 和 T2 都等待对方释放锁以获取插入意向锁,形成循环等待,触发死锁。

四、Java 层面的终极解决方案

针对上述原理,我们从数据库配置、Java 代码、业务逻辑三端协同优化,最终将死锁率降至 0.01% 以下。

方案 1:调整事务隔离级别(核心优化)

将事务隔离级别从默认的REPEATABLE READ改为READ COMMITTED(读已提交),Java 中通过@Transactional注解配置:

java

// 优化后:降低隔离级别减少锁范围
@Transactional(isolation = Isolation.READ_COMMITTED) 
public void batchInsert(List<CinemaShowData> dataList) {// 插入逻辑不变
}

原理READ COMMITTED下,InnoDB 仅保留记录锁(释放间隙锁),且唯一性检查仅加记录锁(非 Next-Key Lock),大幅减少锁冲突。

方案 2:拆分批量插入(缩短事务生命周期)

将单次插入 2000 条改为每 100 条提交一次,避免长事务长时间持锁:

java

// 优化后:拆分批量插入
public void batchInsert(List<CinemaShowData> dataList) {int batchSize = 100;for (int i = 0; i < dataList.size(); i += batchSize) {List<CinemaShowData> batch = dataList.subList(i, Math.min(i + batchSize, dataList.size()));doInsert(batch); // 单独事务提交}
}@Transactional(isolation = Isolation.READ_COMMITTED)
private void doInsert(List<CinemaShowData> batch) {String sql = "INSERT INTO tkn_tb_cinema_show_data (cinema_id, show_id, now_date) VALUES (?,?,?)";jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {@Overridepublic void setValues(PreparedStatement ps, int i) throws SQLException {CinemaShowData data = batch.get(i);ps.setLong(1, data.getCinemaId());ps.setLong(2, data.getShowId());ps.setString(3, data.getNowDate());}@Overridepublic int getBatchSize() {return batch.size();}});
}

方案 3:添加死锁重试逻辑(兜底保障)

通过 Spring Retry 实现死锁自动重试(需引入spring-retry依赖):

java

// 依赖配置(pom.xml)
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>// 启用重试注解
@Service
@EnableRetry
public class CinemaDataService {@Retryable(value = MySQLTransactionRollbackException.class, maxAttempts = 3, backoff = @Backoff(delay = 100))@Transactional(isolation = Isolation.READ_COMMITTED)public void batchInsert(List<CinemaShowData> dataList) {// 插入逻辑}@Recoverpublic void recover(MySQLTransactionRollbackException e, List<CinemaShowData> dataList) {log.error("最终重试失败,数据:{}", dataList, e);// 可选:将失败数据写入补偿队列}
}

方案 4:按索引顺序排序插入(减少锁竞争)

插入前按唯一索引(cinema_id, show_id, now_date)排序,避免随机插入导致多事务竞争同一间隙:

java

// 插入前排序(Java 8 Stream)
List<CinemaShowData> sortedData = dataList.stream().sorted(Comparator.comparingLong(CinemaShowData::getCinemaId).thenComparingLong(CinemaShowData::getShowId).thenComparing(CinemaShowData::getNowDate)).collect(Collectors.toList());

五、效果验证:从 "死亡循环" 到 "丝滑插入"

优化后压测(200 线程并发插入 2000 条数据):

  • 死锁次数:0 次(原 127 次 / 10 分钟);
  • 插入耗时:从 82s 降至 15s(因事务提交次数增加,需平衡批量大小);
  • 业务成功率:从 60% 提升至 99.99%。

总结

高并发插入唯一索引表的死锁问题,本质是 InnoDB 锁机制与业务场景的碰撞。通过调整隔离级别、缩短事务、添加重试等组合拳,可有效解决此类问题。关键是要理解数据库底层锁机制,结合业务场景做针对性优化。

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

相关文章:

  • 分类网站一天做几条合适制作外贸网站开发
  • 上海网站建设服务分录网络公司经营范围和管理条例
  • 天津做网站公司哪家好网站的图片尺寸
  • wordpress上站工具博野网站建设
  • 互联网行业信息网站获得网站所有关键字
  • js博客网站开发计划书食品品牌网站策划
  • 百度怎么做网站广告网店推广计划怎么写免费的
  • php网站 mysql数据库配置文件在线crm平台
  • 美容院网站建设方案书网站运营 开发
  • 企业高端网站建设需要注意哪些事项北京网站优化外包
  • 建立的含义优化绿松石什么意思
  • 网站怎么做弹幕播放器怎么建立网站推广
  • 网站优化 pdf网页设计报告结束语
  • 图书馆新生专栏网站建设最近的重要新闻
  • 网站文件夹名凡科网登录官网
  • 网站建立时间wordpress如何导入模板数据库
  • 企业网站开发需求文档做盗版电影网站违法吗
  • 四川省城乡建设厅官方网站网页特效设计
  • 如何在服务器里建设网站做豆制品的网站
  • 专门做手工的网站钦州网站推广
  • 浦东网站建设哪家好asp.net网站创建浏览器快捷图标
  • 淮南移动网站建设微信兼职网站开发
  • 南通做网站的网站收录在下降
  • 国家工商局网站官网村建站什么部门
  • 江门网站建设硬件设备广告公司推广
  • 单位门户网站建设存在问题陕西手机网站建站
  • 网站建设行业泊头网站建设
  • 免费网站建设视频网站php源码
  • 北京企业营销网站建设wordpress宠物
  • 网站存在的问题及改进措施网站内部链接怎麽做