이 페이지에서는 Spanner의 트랜잭션을 설명하고 트랜잭션 실행을 위한 샘플 코드를 포함합니다.
소개
Spanner의 트랜잭션은 데이터베이스의 열, 행, 테이블 전체에 걸쳐 단일 논리 시점에서 원자적으로 실행되는 읽기 및 쓰기 집합입니다.
Spanner는 다음과 같은 트랜잭션 모드를 지원합니다.
읽기-쓰기 잠금. 이러한 트랜잭션은 최악 잠금과 필요한 경우 2단계 커밋에 의존합니다. 읽기-쓰기 잠금 트랜잭션이 중단되면 애플리케이션을 다시 시도해야 할 수 있습니다.
읽기 전용. 이 트랜잭션 유형은 여러 읽기에서 일관성을 보장하지만 쓰기를 허용하지 않습니다. 기본적으로 읽기 전용 트랜잭션은 외적 일관성을 보장하는 시스템에서 선택한 타임스탬프에서 실행되지만 이전의 타임스탬프에서 읽도록 구성될 수도 있습니다. 읽기 전용 트랜잭션은 커밋할 필요가 없으며 잠금을 사용하지 않습니다. 또한 읽기 전용 트랜잭션은 실행 전에 진행 중인 쓰기가 완료될 때까지 기다릴 수 있습니다.
Partitioned DML. 이 트랜잭션 유형은 데이터 조작 언어(DML) 문을 Partitioned DML로 실행합니다. Partitioned DML은 일괄 업데이트 및 삭제, 특히 정기적인 정리 및 백필을 위해 설계되었습니다. 블라인드 쓰기를 대량으로 커밋해야 하지만 원자적 트랜잭션이 필요하지 않은 경우 일괄 쓰기를 사용하여 Spanner 테이블을 일괄 수정할 수 있습니다. 자세한 내용은 일괄 쓰기를 사용하여 데이터 수정을 참조하세요.
이 페이지에서는 Spanner 트랜잭션의 일반적인 속성과 시맨틱스를 설명하고, Spanner의 읽기-쓰기, 읽기 전용, Partitioned DML 트랜잭션 인터페이스를 소개합니다.
읽기-쓰기 트랜잭션
읽기-쓰기 잠금 트랜잭션을 사용해야 하는 상황은 다음과 같습니다.
- 한 개 이상의 읽기 결과에 따라 쓰기를 수행하는 경우, 동일한 읽기-쓰기 트랜잭션에서 해당 쓰기와 읽기를 수행해야 합니다.
- 예: 은행 계좌 A의 잔액을 두 배로 늘립니다. A 잔액 읽기는 잔액을 두 배로 대체할 쓰기와 동일한 트랜잭션에 있어야 합니다.
- 원자적으로 커밋해야 하는 쓰기 작업을 한 개 이상 수행하는 경우, 동일한 읽기-쓰기 트랜잭션으로 해당 쓰기 작업을 수행해야 합니다.
- 예: A 계좌에서 B 계좌로 200달러를 이체합니다. 초기 계좌 잔액의 쓰기(A를 200달러 줄이는 쓰기와 B를 200달러 늘리는 쓰기)와 읽기 모두 동일한 트랜잭션에서 있어야 합니다.
- 한 개 이상의 읽기 결과에 따라 쓰기 작업을 한 개 이상 수행할 수 있는 경우, 쓰기를 실행하지 않게 되더라고 동일한 읽기-쓰기 트랜잭션으로 해당 쓰기 및 읽기 작업을 수행해야 합니다.
- 예: A의 현재 잔액이 500달러 이상인 경우, 은행 계좌 A에서 은행 계좌 B로 200달러를 이체합니다. 이 트랜잭션에는 A 잔액의 읽기와 쓰기가 포함된 조건문이 포함되어야 합니다.
다음은 읽기-쓰기 잠금 트랜잭션을 사용하지 않아야 하는 상황입니다.
- 읽기만 수행하고 단일 읽기 메서드를 사용하여 읽기를 표현할 수 있는 경우, 해당 단일 읽기 메서드 또는 읽기 전용 트랜잭션을 사용해야 합니다. 단일 읽기는 읽기-쓰기 트랜잭션과 달리 잠기지 않습니다.
속성
Spanner의 읽기-쓰기 트랜잭션은 단일 논리 시점에서 원자적으로 읽기 및 쓰기 집합을 실행합니다. 또한 읽기-쓰기 트랜잭션이 실행되는 타임스탬프는 벽시계 시간과 일치하고, 직렬화 순서는 타임스탬프 순서와 일치합니다.
읽기-쓰기 트랜잭션을 왜 사용할까요? 읽기-쓰기 트랜잭션은 관계형 데이터베이스의 ACID 속성을 제공합니다. 실제로, Spanner 읽기-쓰기 트랜잭션은 기존의 ACID보다 훨씬 강력한 보장을 제공합니다. 아래 시맨틱스 섹션을 참조하세요.
격리
다음은 읽기-쓰기 및 읽기 전용 트랜잭션의 격리 속성입니다.
읽고 쓰는 트랜잭션
다음은 일련의 읽기(또는 쿼리) 및 쓰기가 포함된 트랜잭션을 성공적으로 커밋한 후 제공되는 격리 속성입니다.
- 트랜잭션 내 모든 읽기는 트랜잭션의 커밋 타임스탬프에서 작성된 일관된 스냅샷을 반영하는 값을 반환했습니다.
- 커밋 시점에 빈 행이나 범위가 남아 있었습니다.
- 트랜잭션 내 모든 쓰기는 트랜잭션의 커밋 타임스탬프에서 커밋되었습니다.
- 쓰기는 트랜잭션이 커밋될 때까지 어떠한 트랜잭션에도 표시되지 않았습니다.
특정 Spanner 클라이언트 드라이버에는 트랜잭션을 다시 실행하고 클라이언트에서 관찰된 데이터를 검증하여 일시적인 오류를 마스킹하는 트랜잭션 재시도 로직이 포함됩니다.
트랜잭션 자체의 관점과 Spanner 데이터베이스에 대한 다른 판독기와 기록기의 관점 모두에서 모든 읽기와 쓰기가 단일 시점에서 발생한 것으로 보이는 효과가 있습니다. 즉, 읽기와 쓰기는 결국 동일한 타임스탬프에서 발생합니다(아래 직렬 가능성 및 외적 일관성 섹션 설명 참조).
읽기 전용 트랜잭션
읽기 전용인 읽기-쓰기 트랜잭션에 대한 보장은 유사합니다. 해당 트랜잭션 내의 모든 읽기는 행이 없는 경우에도 동일한 타임스탬프의 데이터를 반환합니다. 한 가지 차이점은 데이터를 읽고 나중에 쓰기 없이 읽기-쓰기 트랜잭션을 커밋하는 경우 읽기 후와 커밋 전에 데이터가 데이터베이스에서 변경되지 않았다는 보장하지 않는다는 점입니다. 마지막으로 읽은 후 데이터가 변경되었는지 여부를 알고 싶으면 읽기-쓰기 트랜잭션에서 또는 강력한 읽기를 사용하여 데이터를 다시 읽는 것이 가장 좋은 방법입니다. 또한 효율성을 위해 읽기만 하고 쓰지는 않을 것을 미리 알고 있다면 읽기-쓰기 트랜잭션 대신 읽기 전용 트랜잭션을 사용해야 합니다.
원자성, 일관성, 내구성
격리 속성 외에도 Spanner는 원자성(트랜잭션에서 쓰기 중 어느 하나라도 커밋되면 모두 커밋됨), 일관성(트랜잭션 후 데이터베이스가 일관된 상태로 유지됨) 및 내구성(커밋된 데이터가 커밋된 상태로 유지됨)을 제공합니다.
이러한 속성의 이점
이러한 속성으로 인해 애플리케이션 개발자는 동시에 실행될 수 있는 다른 트랜잭션에서 해당 실행을 보호할 방법을 걱정하지 않고 각 트랜잭션의 정확성에만 집중할 수 있습니다.
인터페이스
Spanner 클라이언트 라이브러리는 읽기-쓰기 트랜잭션의 컨텍스트에서 트랜잭션 중단을 위한 재시도와 함께 작업 본문을 실행하기 위한 인터페이스를 제공합니다. 이 점을 설명하기 위한 약간의 컨텍스트가 있습니다. Spanner 트랜잭션은 커밋되기 전에 Spanner 트랜잭션을 여러 번 시도해야 할 수 있습니다. 예를 들어 두 트랜잭션이 교착 상태를 유발할 수 있는 방식으로 동시에 데이터에서 작업을 시도하면 Spanner는 다른 트랜잭션이 진행될 수 있도록 이들 중 하나를 중단합니다. (드물게, Spanner 내의 일시적인 이벤트로 인해 일부 트랜잭션이 중단될 수 있습니다.) 트랜잭션은 원자적이므로, 중단된 트랜잭션은 데이터베이스에 가시적인 영향을 미치지 않습니다. 따라서 트랜잭션이 성공할 때까지 트랜잭션을 다시 시도하여 실행해야 합니다.
Spanner 클라이언트 라이브러리에서 트랜잭션을 사용하는 경우, 함수 객체 형태로 트랜잭션 본문을 정의합니다(즉, 데이터베이스에 있는 한 개 이상의 테이블에서 수행하는 읽기 및 쓰기). 백그라운드에서 Spanner 클라이언트 라이브러리는 트랜잭션이 커밋되거나 다시 시도할 수 없는 오류가 발생할 때까지 함수를 반복적으로 실행합니다.
예
스키마 및 데이터 모델 페이지에 나와 있는 Albums
테이블에 MarketingBudget
열을 추가했다고 가정해 보겠습니다.
CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), MarketingBudget INT64 ) PRIMARY KEY (SingerId, AlbumId);
마케팅 부서는 Albums (1, 1)
로 키가 지정된 앨범에 대해 마케팅을 추진하기로 결정하고 Albums
(2, 2)
의 예산에서 $200,000를 전환해달라고 요청했지만 해당 앨범의 예산 내에서만 이 금액을 사용할 수 있습니다. 읽기 결과에 따라 트랜잭션이 쓰기를 수행할 수 있으므로 이 작업에 읽기-쓰기 잠금 트랜잭션을 사용해야 합니다.
다음은 읽기-쓰기 트랜잭션을 실행하는 방법을 보여줍니다.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
시맨틱스
직렬 가능성 및 외적 일관성
Spanner는 '직렬 가능성'을 제공합니다. 즉, 고유 트랜잭션의 일부 읽기, 쓰기 및 기타 작업이 실제로 병렬로 발생하더라도 모든 트랜잭션이 순차적으로 실행되는 것처럼 나타난다는 것을 의미합니다. Spanner는 이 속성을 구현하기 위해 커밋된 트랜잭션 순서를 반영하는 커밋 타임스탬프를 할당합니다. 실제로, Spanner는 외적 일관성이라는 직렬 가능성보다 강력한 보장을 제공합니다. 트랜잭션은 커밋 타임스탬프에 반영되는 순서로 커밋되며 이러한 커밋 타임스탬프는 실시간을 반영되므로, 보유하고 있는 시계와 타임스탬프를 비교할 수 있습니다. 트랜잭션에서 읽기는 이 트랜잭션이 커밋되기 전에 커밋된 모든 내용을 확인하고 쓰기는 트랜잭션이 커밋된 후에 시작되는 모든 내용을 통해 확인됩니다.
예를 들어 아래 다이어그램과 같이 트랜잭션 두 개 실행을 고려합니다.
파란색의 트랜잭션 Txn1
은 일부 데이터 A
를 읽고 A
에 쓰기를 버퍼링한 후 성공적으로 커밋됩니다. 녹색의 트랜잭션 Txn2
는 Txn1
이후에 시작되고 일부 데이터 B
를 읽은 후 데이터 A
를 읽습니다. Txn2
는 Txn1
이 A
에 대한 쓰기를 커밋한 후 A
의 값을 읽으므로 Txn1
이 완료되기 전에 Txn2
가 시작되었더라도 Txn2
는 A
에 대한 Txn1
의 쓰기 효과를 인식합니다.
Txn1
과 Txn2
가 모두 실행되는 시간이 일부 중첩되지만 해당 커밋 타임스탬프 c1
및 c2
는 선형적 트랜잭션 순서를 따릅니다. 즉, Txn1
의 모든 읽기 및 쓰기 효과는 단일 시점(c1
)에 발생한 것으로 나타나고 Txn2
의 모든 읽기 및 쓰기 효과는 단일 시점(c2
)에 발생한 것으로 나타납니다. 또한 Txn2
전에 Txn1
발생 순서를 따르는 c1 < c2
의 관계는 Txn1
과 Txn2
모두를 커밋했으므로 보장되며 쓰기가 서로 다른 머신에서 발생했더라도 마찬가지입니다.
그러나 Txn2
가 트랜잭션에서 읽기만 수행한 경우 c1 <= c2
관계가 됩니다.
읽기는 커밋 기록의 프리픽스를 관찰합니다. 읽기가 Txn2
의 효과를 인식하면 Txn1
의 효과도 인식할 수 있습니다. 성공적으로 커밋된 모든 트랜잭션에는 이 속성이 있습니다.
읽기 및 쓰기 보장
트랜잭션을 실행하기 위한 호출이 실패하면 사용자는 기본 커밋 호출이 실패한 오류에 따라 가질 수 있는 읽기 및 쓰기 보장을 가집니다.
예를 들어, 'Row Not Found(행을 찾을 수 없음)' 또는 'Row Already Exists(행이 이미 있음)'와 같은 오류는 버퍼링된 변형에 일부 오류가 발생했음을 의미합니다. 클라이언트가 업데이트하려고 하는 행이 존재하지 않는 경우를 예로 들 수 있습니다. 이 경우 읽기 일관성이 보장되고 쓰기가 적용되지 않습니다. 그뿐만 아니라, 행이 없으면 읽기 일관성이 보장됩니다.
트랜잭션 작업 취소
사용자는 트랜잭션 내의 다른 기존 작업에 영향을 주지 않으면서 언제든지 비동기 읽기 작업을 취소할 수 있습니다(예: 더 높은 수준의 작업이 취소되거나 읽기에서 받은 초기 결과에 따라 읽기를 중지하려는 경우).
그러나 읽기 취소를 시도하더라도 Spanner는 실제로 읽기가 취소된다고 보장하지 않습니다. 읽기 취소를 요청한 후 일부 다른 이유(예: 중단)로 읽기가 성공적으로 완료되거나 실패할 수 있습니다. 또한 취소된 읽기가 실제로 결과를 반환할 수 있으며, 이러한 불완전할 수 있는 결과는 트랜잭션 커밋의 일부로 확인됩니다.
읽기와 달리 트랜잭션 커밋 작업을 취소하면 트랜잭션이 이미 커밋되었거나 다른 이유로 실패하지 않는 한 트랜잭션이 중단됩니다.
성능
잠금
Spanner를 사용하면 여러 클라이언트가 동시에 동일한 데이터베이스와 상호 작용할 수 있습니다. 여러 동시 트랜잭션의 일관성을 보장하기 위해 Spanner는 공유 잠금과 배타적 잠금을 결합 및 사용하여 데이터 액세스를 제어합니다. 트랜잭션의 일부로 읽기를 수행하면 Spanner는 공유 읽기 잠금을 획득하여 트랜잭션이 커밋될 수 있을 때까지 다른 읽기가 계속해서 데이터에 액세스할 수 있게 합니다. 트랜잭션이 커밋되고 쓰기가 적용되면 트랜잭션은 배타적 잠금으로 업그레이드하려 합니다. 트랜잭션은 데이터에 대한 새로운 공유 읽기 잠금을 차단하고 기존 공유 읽기 잠금이 해제될 때까지 기다린 후 데이터에 배타적으로 액세스하기 위한 배타적 잠금을 설정합니다.
잠금에 대한 참고 사항:
- 잠금은 행과 열로 세분화되어 수행됩니다. 트랜잭션 T1이 'foo' 행의 'A' 열을 잠갔고 트랜잭션 T2가 'foo' 행의 'B' 열을 쓰려는 경우에는 충돌이 발생하지 않습니다.
- 기록되는 데이터를 동시에 읽지 않는 데이터 항목에 대한 쓰기('블라인드 쓰기'라고도 함)는 동일한 항목의 다른 블라인드 작성자와 충돌하지 않습니다. 각 쓰기의 커밋 타임스탬프가 데이터베이스에 적용되는 순서를 결정합니다. 결과적으로 사용자가 작성 중인 데이터를 읽은 경우에만 Spanner가 배타적 잠금으로 업그레이드되어야 합니다. 그렇지 않으면 Spanner는 작성자 공유 잠금이라는 공유 잠금을 사용합니다.
- 읽기-쓰기 트랜잭션 내에서 행 조회를 수행할 때는 검사되는 행을 더 작은 범위로 제한하기 위해 보조 색인을 사용합니다. 그러면 Spanner가 테이블에서 더 적은 행 수를 잠그기 때문에 범위 바깥에서 행 동시 수정이 가능해집니다.
Spanner 외부 리소스에 대한 독점 액세스를 보장하는 데 잠금을 사용해서는 안 됩니다. 예를 들어 인스턴스의 컴퓨팅 리소스 간 데이터 이동을 허용하는 경우와 같이 Spanner에서 여러 가지 이유로 트랜잭션을 취소할 수 있습니다. 애플리케이션 코드에서 명시적으로 또는 Spanner JDBC 드라이버와 같은 클라이언트 코드에서 암시적으로 트랜잭션이 재시도되는 경우 실제로 커밋된 시도 중에만 잠금이 보장됩니다.
잠금 통계 점검 도구를 사용하여 데이터베이스의 잠금 충돌을 조사할 수 있습니다.
교착 상태 감지
여러 트랜잭션이 교착 상태에 빠진 경우, Spanner는 이를 감지하고 트랜잭션 중 하나를 제외한 모든 트랜잭션을 강제로 중단합니다. 예를 들어 다음 상황을 생각해 보겠습니다. 트랜잭션 Txn1
은 레코드 A
에서 잠금을 가지고 있고 레코드 B
에서는 잠금을 대기하고 있습니다. 한편, Txn2
는 레코드 B
에서 잠금을 가지고 있고 레코드 A
에서 잠금을 대기하고 있습니다. 이 상황에서 계속 작업을 진행하기 위한 유일한 방법은 트랜잭션 중 하나를 중단하여 잠금을 해제함으로써 다른 트랜잭션이 진행될 수 있게 하는 방법입니다.
Spanner는 교착 상태 감지를 처리하기 위해 표준 'wound-wait' 알고리즘을 사용합니다. Spanner는 충돌하는 잠금을 요청하는 각 트랜잭션의 기간을 계속해서 추적합니다. 또한 더 오래된 트랜잭션이 덜 오래된 트랜잭션을 중단하도록 합니다('더 오래된'은 읽기, 쿼리 또는 커밋이 트랜잭션에서 먼저 발생한 것을 의미함).
오래된 트랜잭션에 우선순위를 부여함으로써 Spanner는 결국 모든 트랜잭션이 다른 트랜잭션보다 우선순위가 높아질 만큼 충분히 오래되었다는 이유로 결국 잠금을 획득할 수 있는 기회를 보장합니다. 예를 들어 판독기 공유 잠금을 획득한 트랜잭션은 작성자 공유 잠금이 필요한 더 오래된 트랜잭션에 의해 중단될 수 있습니다.
배포 실행
Spanner는 여러 서버에 걸쳐진 데이터로 트랜잭션을 실행할 수 있습니다. 이러한 이점은 단일 서버 트랜잭션에 비해 성능을 희생시키면서 얻어집니다.
어떤 유형의 트랜잭션이 배포될 수 있을까요? Spanner는 내부에서 여러 서버 사이에서 데이터베이스의 행에 대한 책임을 나눌 수 있습니다. 인접한 키를 가지고 있는 동일한 테이블의 두 행과 마찬가지로 어떤 행과 인터리브 처리된 테이블의 해당 행은 일반적으로 동일한 서버에서 처리됩니다. Spanner는 서로 다른 서버의 전체 행에서 트랜잭션을 수행할 수 있습니다. 그러나 경험에 비추어 볼 때 같은 위치에 있는 여러 행에 영향을 미치는 트랜잭션이 데이터베이스 전체나 큰 테이블 전체에 분산된 많은 행에 영향을 미치는 트랜잭션보다 빠르고 경제적입니다.
Spanner의 가장 효율적인 트랜잭션에는 원자적으로 적용되어야 하는 읽기 및 쓰기만 포함됩니다. 트랜잭션은 모든 읽기 및 쓰기가 키 공간의 동일한 부분에서 데이터에 액세스할 때 가장 빠릅니다.
읽기 전용 트랜잭션
읽기-쓰기 잠금 트랜잭션 외에도 Spanner는 읽기 전용 트랜잭션을 제공합니다.
동일한 타임스탬프에서 읽기를 두 개 이상 실행해야 하는 경우, 읽기 전용 트랜잭션을 사용합니다. Spanner의 단일 읽기 메서드 중 하나를 사용하여 읽기를 표현할 수 있는 경우, 이 단일 읽기 메서드를 대신 사용해야 합니다. 이러한 단일 읽기 호출 사용 시의 성능과 읽기 전용 트랜잭션에서 수행된 단일 읽기의 성능을 비교해야 합니다.
대량의 데이터 읽기를 수행할 경우에는 파티션을 사용하여 데이터 병렬로 읽기를 수행하는 것이 좋습니다.
읽기 전용 트랜잭션은 쓰지 않으므로 잠금을 보유하지 않으며 다른 트랜잭션을 차단하지 않습니다. 읽기 전용 트랜잭션은 트랜잭션 커밋 기록의 일관된 프리픽스를 관찰하므로 애플리케이션이 항상 일관된 데이터를 가져옵니다.
속성
Spanner 읽기 전용 트랜잭션은 읽기 전용 트랜잭션 자체의 관점과 Spanner 데이터베이스에 대한 다른 판독기 및 작성자의 관점 모두에서 볼 때 단일 논리 시점에서 일련의 읽기를 실행합니다. 즉, 읽기 전용 트랜잭션은 항상 트랜잭션 기록에서 선택한 시점에서 일관된 데이터베이스 상태를 관찰합니다.
인터페이스
Spanner는 읽기 전용 트랜잭션의 컨텍스트에서 트랜잭션 중단을 위한 재시도와 함께 작업 본문을 실행하기 위한 인터페이스를 제공합니다.
예
다음은 읽기 전용 트랜잭션을 사용하여 동일한 타임스탬프에서 2개의 읽기에 일관된 데이터를 얻는 방법을 보여 줍니다.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Partitioned DML 트랜잭션
파티션을 나눈 데이터 조작 언어(Partitioned DML)를 사용하면 트랜잭션 제한에 걸리거나 전체 테이블을 잠그지 않고 대규모 UPDATE
및 DELETE
문을 실행할 수 있습니다.
Spanner는 키 공간을 파티션으로 나누고 각 파티션에서 별도의 읽기-쓰기 트랜잭션으로 DML 문을 실행합니다.
코드에서 명시적으로 만드는 읽기-쓰기 트랜잭션에서 DML 문을 실행하세요. 자세한 내용은 DML 사용을 참조하세요.
속성
클라이언트 라이브러리 메서드 또는 Google Cloud CLI 사용 여부에 관계없이 한 번에 Partitioned DML 문 하나만 실행할 수 있습니다.
파티션을 나눈 트랜잭션은 커밋이나 롤백을 지원하지 않습니다. Spanner는 DML 문을 즉시 실행하고 적용합니다. 작업을 취소하거나 작업이 실패하면 Spanner는 실행 중인 파티션을 모두 취소하며, 나머지 파티션을 시작하지 않습니다. Spanner는 이미 실행된 파티션을 롤백하지 않습니다.
인터페이스
Spanner는 단일 Partitioned DML 문을 실행하기 위한 인터페이스를 제공합니다.
Examples
다음 코드 예시에서는 Albums
테이블의 MarketingBudget
열을 업데이트합니다.
C++
ExecutePartitionedDml()
함수를 사용하여 Partitioned DML 문을 실행합니다.
C#
ExecutePartitionedUpdateAsync()
메서드를 사용하여 Partitioned DML 문을 실행합니다.
Go
PartitionedUpdate()
메서드를 사용하여 Partitioned DML 문을 실행합니다.
Java
executePartitionedUpdate()
메서드를 사용하여 Partitioned DML 문을 실행합니다.
Node.js
runPartitionedUpdate()
메서드를 사용하여 Partitioned DML 문을 실행합니다.
PHP
executePartitionedUpdate()
메서드를 사용하여 Partitioned DML 문을 실행합니다.
Python
execute_partitioned_dml()
메서드를 사용하여 Partitioned DML 문을 실행합니다.
Ruby
execute_partitioned_update()
메서드를 사용하여 Partitioned DML 문을 실행합니다.
다음 코드 예시에서는 SingerId
열을 기준으로 Singers
테이블에서 행을 삭제합니다.