>  기사  >  데이터 베이스  >  MySQL 업데이트 sql로 인한 생산 실패를 해결하는 방법

MySQL 업데이트 sql로 인한 생산 실패를 해결하는 방법

WBOY
WBOY앞으로
2023-05-31 13:31:141063검색

결함 발현

  • 한편: Alibaba Cloud 콘솔의 클라우드 데이터베이스 PolarDB에 해당하는 클러스터 관리 페이지, 진단 및 최적화 모듈의 원클릭 진단 세션 관리에서 다음이 발견되었습니다. 특정 업데이트 SQL은 실행하는 데 매우 오랜 시간이 걸렸습니다. 그리고 매우 자주

  • 한편: 비즈니스 모니터링 시스템은 비즈니스 실행 시간 동안 알람 정보 프롬프트를 지속적으로 발행하기 시작했으며 알람의 비즈니스 데이터도 있습니다. 계속 증가했으며 일부 작업은 고객 사용에 영향을 미쳤습니다.

사업 배경

사업 운영에 수반되는 사업 흐름은 상대적으로 복잡하기 때문에, 순수 기술 공유가 논의의 초점이 아닐 경우, 문제 발생 원인을 보다 쉽게 ​​이해할 수 있도록 , 비유는 콤플렉스를 나누는 데 사용됩니다. 비즈니스 비유는 다음과 같습니다. 데이터베이스에 세 개의 테이블이 있으며, 첫 번째 테이블은 t_grandfather(할아버지 테이블), 두 번째 테이블은 t_father(부모 테이블), 세 번째 테이블입니다. is t_grandson(자손 테이블), DDL 다음과 같습니다.

CREATE TABLE `t_grandfather ` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `count` int(11) NOT NULL DEFAULT 0 COMMENT '子孙后代数量',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='老爷表';

CREATE TABLE `t_father ` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `grandfather_id` int(11) NOT NULL COMMENT '老爷表id',
  PRIMARY KEY (`id`),
  KEY `idx_grandfather_id` (`grandfather_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='老爸表';

CREATE TABLE `t_grandson` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `grandfather_id` int(11) NOT NULL COMMENT '老爷表id',
  PRIMARY KEY (`id`),
  KEY `idx_grandfather_id` (`grandfather_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='孙子表';

세 테이블 간의 비즈니스 논리 관계는 먼저 마스터 테이블이 생성되고 그 다음 마스터가 많은 아내(비즈니스)를 취하고 계속해서 아기를 낳는다는 것입니다. 아기가 태어나면 동시에 아빠 테이블이 생성되며, 마스터의 아내(사업)가 계속해서 추가되면 마스터 테이블의 count=count+1이 업데이트됩니다. 아기가 있으면 이전에 태어난 아기도 아내를 갖게 되고, 그 아내도 아기를 갖게 됩니다. 주인에게는 손자가 있다는 의미입니다(새로운 비즈니스 데이터 생성). 마스터 테이블의 count=count+1, 즉 새로운 자손이 추가되었다는 의미 등입니다.

조상 코드는 MySQL 업데이트 sql로 인한 생산 실패를 해결하는 방법t_father

테이블과

t_grandson에 새로운 항목이 추가되는 한 t_grandfather를 업데이트한다는 것입니다. 이러한 논리적 설계는 큰 문제가 되지 않지만, 손자 테이블의 데이터 양이 많다는 점을 고려하면 여기서는 매우 심각한 성능 문제가 발생하게 됩니다. 다음은 비즈니스에서 추출한 의사 코드의 일부입니다

 /**
 * 处理 father 的业务
 */
 public void doFatherBusiness  (){
     //do fatherBusiness baba .... 此处省
     // 插入 t_father 表
    if (fatherMapper.inster(father)){
         //update t_grandfather set count=count+1 where id= #{grandfatherId}
         grandfatherMapper.updateCount(father.getGrandfatherId  ())  ;
     }
}


 /**
 * 处理 grandson 的业务
 */
 public void doGrandsonBusiness  (){
     //do grandson baba .... 此处省略
     // 插入 t_grandson 表
     if(grandsonMapper.inster(grandson)){
          //update t_grandfather set count=count+1 where id= #{grandfatherId}
          grandfatherMapper.updateCount(grandson.getGrandfatherId());
     }
}
여러 비즈니스(스레드)가 각각 위 메서드를 호출하면 t_grandfather

테이블의 업데이트 작업에 큰 부담이 됩니다. 특히 동일한 ID가 업데이트되는 경우 더욱 그렇습니다. .mysql 서버 내 잠금 경쟁은 매우 치열합니다. 최종 성능은 위의 배경 설명과 일치합니다.

Solution

1. 임시 해결 방법:

한편으로는 Alibaba Cloud 콘솔에서 SQL의 흐름을 제한하고, 데이터 스레드가 차단 및 해제되지 않도록 정상적으로 차단된 세션을 강제 종료합니다. 한편, 입력되는 비즈니스 데이터의 양을 줄이기 위한 목적으로 요청을 받는 서비스의 노드 수를 줄입니다.

2. 장기적인 솔루션

한편으로는 위의 비즈니스를 변경합니다. 로직을 작성하고 t_grandfather 테이블과 t_father 테이블을 삽입하면 더 이상 t_grandfather 테이블의 count 필드를 업데이트하지 않습니다. 반면에 count 통계 요구 사항이 필요할 경우 모두 다른 방법으로 전환됩니다.

위 내용은 MySQL 업데이트 sql로 인한 생산 실패를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제