필드를 증가시킬 때 MySQL 데이터베이스에 레이스 조건이 없는지 확인하는 방법은 무엇입니까?
두 연결이 동일한 레코드를 업데이트하려는 경우 MySQL 데이터베이스에서 레이스 상태를 방지하는 방법은 무엇입니까?
예를 들어, 연결 1에서 "시도" 카운터를 늘리려고 합니다.그리고 두 번째 연결도 그렇게 하고 싶어합니다.두 연결 모두 연결SELECT
"count", 값 증가 및 둘 다UPDATE
증가된 값을 가진 "병아리".갑자기 "tries"는 "tries+2"가 아니라 "tries+1"만 됩니다. 왜냐하면 두 연결 모두 동일한 "tries"를 얻어서 하나씩 증가시켰기 때문입니다.
이 문제를 해결하는 방법은?
다음은 세 가지 접근 방식입니다.
원자 업데이트
update table set tries=tries+1 where condition=value;
원자론적으로 이루어 질 겁니다
행 잠금 사용
먼저 값을 선택하고 응용 프로그램에서 업데이트해야 하는 경우 행 잠금을 사용해야 할 가능성이 높습니다.즉, My ISAM 테이블이 아닌 InnoDB를 사용해야 합니다.쿼리는 다음과 같습니다.
select tries from table where condition=value for update;
.. do application logic to add to `tries`
update table set tries=newvalue where condition=value;
동일한 행을 읽으려는 다른 모든 쿼리는 테이블이 업데이트될 때까지 기다려야 하며, 테이블은 업데이트된 값을 반환합니다.
버전 스킴
일반적인 접근 방식은 표에 버전 열을 소개하는 것입니다.쿼리는 다음과 같은 작업을 수행합니다.
select tries,version from table where condition=value;
.. do application logic, and remember the old version value.
update table set tries=newvalue,version=version + 1 where condition=value and version=oldversion;
해당 업데이트가 실패하거나 영향을 받는 0개의 행을 반환하는 경우, 다른 사용자가 그 동안 테이블을 업데이트한 것입니다.처음부터 다시 시작해야 합니다. 즉, 새 값을 선택하고 애플리케이션 로직을 수행한 후 업데이트를 다시 시도해야 합니다.
두 개 대신 하나의 문장을 사용합니다.싱글UPDATE
읽기와 쓰기를 모두 수행하는 문은 원자적이며 다른 동시 업데이트와 충돌하지 않습니다.
UPDATE table SET tries = tries + 1 WHERE ...
또는 트랜잭션을 사용하여 두 작업을 원자로 만들 수도 있습니다.
BEGIN
SELECT ...
UPDATE ...
COMMIT
또는 테이블을 읽고 쓰는 동안 더 원시적으로 테이블을 잠급니다.
LOCK TABLES table WRITE
SELECT ...
UPDATE ...
UNLOCK TABLES
언급URL : https://stackoverflow.com/questions/2364273/how-to-make-sure-there-is-no-race-condition-in-mysql-database-when-incrementing
'programing' 카테고리의 다른 글
MySql 경고 트래핑 (0) | 2023.09.10 |
---|---|
부트스트랩 3 Navbar(로고 포함) (0) | 2023.09.10 |
모든 개발자가 데이터베이스에 대해 알아야 할 사항은 무엇입니까? (0) | 2023.09.10 |
셀러리로 이미 실행 중인 작업을 취소하시겠습니까? (0) | 2023.09.10 |
jQuery 컨테이너 자체를 포함한 컨테이너의 HTML 가져오기 (0) | 2023.09.05 |