동시 쿼리가 작업을 엉망으로 만들지 않도록 쿼리를 작성하고 있습니다. 나는 그것을 할 수있는 훨씬 더 좋은 방법이 있다고 확신합니다, 그래서 여기에 있습니다.INSERT 문에서 다중 SELECT를 사용하여 경쟁 조건 방지
기본적으로 테이블의 컬럼은 다음과 같이 :
- 지난 경우 : 나는 새 행을 삽입 할 때
id : INT(10) unsigned auto_incremented number : INT(6) unsigned zerofill date : DATETIME
가, 여기에 내가 그 수 값을 설정해야하는 방법이다 삽입 된 행의 날짜가 일 때 번호 = 마지막으로 삽입 된 행 번호 +1
- 전자 마지막으로 삽입 된 행의 날짜 어제 또는 내가 생각
1 = 다음 번호, 전에 대해 먼저 마지막 행의 날짜와 번호를 선택, PHP를 사용하여 새 번호를 설정 한 다음 내 삽입을합니다.
$pdo->beginTransaction();
$stmt = $pdo->prepare("SELECT `number`, `date` FROM `table` ORDER BY `id` DESC LIMIT 1");
$stmt->execute();
$infos = $stmt->fetch(PDO::FETCH_ASSOC);
$date = date("Y-m-d H:i:s");
if (date("Ymd", strtotime($infos['date'])) < date("Ymd", strtotime($date))) {
$number = 1;
} else {
$number = $infos['number'] + 1;
}
$stmt2 = $pdo->prepare("INSERT INTO `table` (`number`, `date`) VALUES (:number, :date)");
$stmt2->execute(array(":number" => $number, ":date" => $date));
$pdo->commit();
는 같은 번호를 선택 다른 스레드를 방지하기 위해 충분한 거래인가 및 그 난에 노력하고 같은 번호를 삽입하려고?
친애하는 친구 인 Google과 SO를 사용해도 직접 질문에 대답 할 수 없었기 때문에 "나는 MySQL에서 모든 작업을 수행 할 수 있습니까?"라고 생각했습니다. 이 쿼리와 함께 나온 :
INSERT INTO `table`(`number`, `date`)
SELECT IF(
DATE((SELECT `date` FROM `table` ORDER BY `id` DESC LIMIT 1)) < CURDATE(),
'1',
(SELECT `number` + 1 FROM `table` ORDER BY `id` DESC LIMIT 1)
), NOW()
더 좋은 방법인가요?
아무것도 수행하기 전에 테이블을 고정해야합니까?
이 작업을 수행하는 방법을보기에는 너무 바보일까요? ,
먼저 테이블을 변경
시나리오를 살펴보면 날짜가 증가하는 순서로 숫자를 삽입하려는 것으로 결론을 내었습니다. 날짜와 숫자 열에 복합 고유 인덱스를 만들 수 있으며 두 개의 동시 쿼리가 진행될 경우 예외를 catch 블록에서 처리 할 수 있습니다 같은 날에 같은 번호를 입력하십시오. –
예, 그냥 메모였습니다. 나는 거래가 다른 거래 상태에 의존한다고 생각하지 않는다. 한 번에 30 명의 사용자가로드 한 경우 30 명의 사용자가 먼저 29 개의 모든 트랜잭션을 완료해야합니다. 나는 당신이 시간을 허락하는'update'를 '선택'하지 않았고, 한번에 모든 것을 할 수 있습니다. – chris85
트랜잭션이 동일한 번호를 선택하는 것만으로는 충분하지 않지만 키가 고유 한 경우 두 번째 삽입이 실패하고 트랜잭션을 취소 한 다음 다시 완전히 시도 할 수 있습니다. – awiebe