>  기사  >  데이터 베이스  >  데이터베이스의 트랜잭션 및 동시성 문제 예

데이터베이스의 트랜잭션 및 동시성 문제 예

零下一度
零下一度원래의
2017-07-03 16:10:391303검색

데이터베이스의 트랜잭션 및 동시성 문제에 대한 토론

소개

최근 동료가 주문 생성 논리를 담당하는 코드 조각을 작성했는데, 코드 검토 중에 동시성 문제가 있을 수 있다는 사실이 발견되었습니다. 내 동료는 자신의 논리가 저장 프로시저에 작성되었으므로 문제가 없을 것이라고 생각했습니다.

코드의 논리는 아마도 (유사 코드):

begin transaction

if 查询到客户存在进行中的订单
 rollback transaction

if 查询到设备存在进行中的订单
 rollback transaction

插入订单

commit transaction

다음은 이 논리에 대한 분석과 이 트랜잭션에 동시성 문제가 있는 이유입니다.

거래 개요

먼저 두 가지 질문을 하고, 그 질문으로 거래와 관련된 지식 포인트를 토론하고, 마지막으로 이 두 가지 질문을 해결하고 이전 질문에 답합니다.

첫 번째 질문은 트랜잭션이 동시에 이루어질 수 있습니까?

두 번째 질문은 데이터베이스가 트랜잭션을 어떻게 격리합니까?

트랜잭션의 성능 특성

데이터베이스에서 트랜잭션을 실행하는 데는 중요한 리소스를 처리하는 방법, 잠금 및 잠금 해제 방법 등을 포함한 여러 측면이 관련됩니다. 그러나 트랜잭션이 어떻게 실행되든 다음 특성이 보장되어야 합니다.

  • 원자성

  • 일관성

  • 격리성

  • 지속성

  • 원자성: 모든 작업은 논리입니다. 단위는 다음 중 하나입니다.

    일관성: 합법적인 데이터만 데이터베이스에 기록됩니다. 그렇지 않으면 트랜잭션이 원래 상태로 롤백됩니다.

    격리: 정확성과 무결성을 파괴하지 않고 동시에 여러 트랜잭션을 진행할 수 있습니다.

    지속성: 거래가 종료된 후 제출된 결과가 확정되어 저장됩니다.

    다양한 데이터베이스 잠금

  1. 공유 잠금

공유 잠금은 비독점적 업무에 사용되며 여러 트랜잭션이 잠긴 리소스를 동시에 읽을 수 있도록 허용하지만 리소스 업데이트를 허용하지 않습니다.

  • 잠금 타이밍 : select 문 실행 시 기본적으로 추가됩니다

  • 잠금 해제 타이밍 : 읽기 완료 후 기본적으로 해제됩니다

  • 다른 잠금과의 호환성 : 공유 잠금이 설정된 경우 공유 잠금 및 배타적 잠금 추가가 허용됩니다

  • 동시성 성능: 동시성 성능이 좋습니다

    1. 배타적 잠금

    배타적 잠금, 배타적 잠금이라고도 합니다. 이름에서 알 수 있듯이 배타적 잠금으로 리소스를 잠그면 다른 트랜잭션이 어떤 작업도 수행할 수 없습니다.

  • 잠금 타이밍: insert, update, delete

  • 잠금 해제 타이밍: 트랜잭션 종료 후에만 해제 가능

  • 호환성: 데이터에 다른 잠금이 있는 경우, 배타적 잠금은 추가할 수 없습니다. 마찬가지로 배타적 잠금이 존재하는 동안에는 다른 잠금을 추가할 수 없습니다

  • 동시성 성능: 다른 트랜잭션은 실행되기 전에 이전 트랜잭션이 끝날 때까지 기다려야 합니다. 동시에, 순차적으로만 업데이트할 수 있습니다

    읽기 단계에서 공유 잠금을 사용하여 발생하는 교착 상태를 방지하기 위해 업데이트 초기 단계에서 필요한 리소스를 잠그는 데 사용됩니다.

  • 잠금 타이밍: 업데이트 실행 시 업데이트 잠금을 사용해 관련 리소스를 잠급니다.

  • 잠금 해제 타이밍: 읽은 후 업데이트 작업 수행 시 업데이트 잠금이 배타적 잠금으로 업그레이드됩니다.

  • 호환성: 업데이트 잠금 및 공유 잠금 호환성, 즉 업데이트 잠금과 ​​공유 잠금은 동시에 존재할 수 있지만 업데이트 잠금은 하나만 있을 수 있습니다

  • 동시성 성능: 업데이트 초기 단계의 읽기 단계에서는 다른 트랜잭션이 리소스를 읽을 수 있도록 허용할 수 있습니다. 제한된 동시성을 허용하며 나중에 리소스를 사용할 수 있습니다. 배타적일 때는 동시성이 허용되지 않습니다.

  • 트랜잭션 격리 수준

    일반적인 트랜잭션 격리 수준에는 네 가지가 있으며, SQL Server에는 추가 확장 수준이 있으므로 여기서는 자세히 소개하지 않겠습니다.

    1. Serialized

    은 반복 읽기처럼 작동합니다. 하지만 영향을 받은 데이터만 잠그는 것이 아니라 범위도 잠급니다. 이렇게 하면 쿼리가 적용되는 범위에 새 데이터가 삽입되어 팬텀 읽기가 발생할 수 있는 상황이 방지됩니다.

    1. 반복 읽기(반복 읽기)

    커밋된 읽기 수준과 같은 데이터를 읽지만 트랜잭션이 끝날 때까지 공유 잠금을 유지합니다.

    1. Read Commit

    커밋된 데이터만 읽고 다른 트랜잭션이 배타적 잠금을 해제할 때까지 기다립니다. 데이터 읽기를 위한 공유 잠금은 읽기 작업이 완료된 후 즉시 해제됩니다. 커밋된 읽기는 SQL Server의 기본 격리 수준입니다.

    1. Read Uncommited

    는 데이터를 읽을 때 잠금을 확인하거나 사용하지 않습니다. 따라서 이 격리 수준에서는 커밋되지 않은 데이터를 읽을 수 있습니다.

    이전 질문에 답하세요

    첫 번째 질문은 트랜잭션이 동시에 가능할까요?

    답은 '예'입니다. 성능을 향상하기 위해 데이터베이스에서는 여러 트랜잭션 작업을 동시에 수행할 수 있습니다. 사용 저장 프로시저가 초기화되거나, 코드를 사용하여 초기화되거나, 일반 SQL 문을 사용하여 초기화되거나 차이가 없습니다.

    두 번째 질문, 데이터베이스는 어떻게 트랜잭션을 격리합니까?

    이 질문에 대답하려면 먼저 데이터베이스의 잠금 메커니즘과 데이터베이스 트랜잭션 격리 수준을 이해해야 합니다. 데이터베이스 잠금은 공유 잠금, 배타 잠금, 업데이트 잠금의 세 가지 유형으로 나눌 수 있습니다. 다양한 수준의 잠금을 사용하고 다양한 잠금 범위와 협력하여 다양한 트랜잭션 격리 수준을 달성하고 이를 기반으로 트랜잭션을 동시에 또는 순차적으로 실행합니다.

    세 번째 질문, 이 글의 시작 부분에 있는 트랜잭션에 동시성 문제가 있는 이유는 무엇입니까?

    select는 트랜잭션 시작시 실행되고, select는 공유 잠금을 사용하기 때문에 동시 트랜잭션이 select를 동시에 실행하여 동시에 모든 합법적인 작업인 것처럼 생각하고 대기열에 넣을 수 있습니다. 후속 트랜잭션을 실행할 때까지. 결과적으로 실제로는 중복된 데이터를 삽입하는 것이 가능합니다. 예를 들어 상품이 1개밖에 남지 않은데 판매 주문이 2개 생성되는 경우가 있습니다.

    동시성 문제를 방지하는 방법

    1. 트랜잭션에서

    앞서 말한 대로 insert, update, delete를 사용하면 기본 트랜잭션 수준에서 인위적으로 트랜잭션 직렬화가 발생할 수 있으므로 내부에서 처음부터 업데이트를 사용할 수 있습니다. 트랜잭션 동일한 유형의 트랜잭션이 직렬화되도록 공개 데이터를 업데이트한 다음 판단문을 추가하여 후속 트랜잭션 내용을 실행할지 여부를 결정합니다. 이는 모든 작업이 합리적이고 합법적으로 수행되도록 보장하는 데 충분합니다. 유일한 단점은 성능 문제를 일으킬 수 있다는 것입니다.

    1. 트랜잭션 외부

    요즘에는 점점 더 많은 분산 시스템이 있지만 재배포 시스템에도 redis나 Zookeeper와 같은 일부 공유 리소스가 있습니다. Redis나 Zookeeper를 사용하여 일부 분산 잠금을 만들 수 있습니다. 해당 카테고리는 다른 블로그 게시물에 속하며 여기에서는 확장되지 않습니다. 트랜잭션 외부의 잠금을 사용하여 동일한 유형의 트랜잭션을 직렬화한 다음 트랜잭션의 내부 확인 메커니즘과 협력하면 트랜잭션의 동시성 문제가 해결되는 데 충분합니다.

    참고 자료

  • 트랜잭션 동시성 문제 및 처리

  • 데이터베이스 트랜잭션의 4가지 주요 특징과 트랜잭션 격리 수준

  • 데이터베이스 트랜잭션 및 동시성

  • SQL Server 트랜잭션의 격리 수준


  • 위 내용은 데이터베이스의 트랜잭션 및 동시성 문제 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.