[MySQL] XA Transaction
- Databases/MySQL
- 2020. 9. 13.
■ XA 트랜잭션
▶︎ XA 트랜잭션 SQL 문
▶︎ XA 거래 상태
▶︎ XA 거래에 대한 제한
InnoDB 스토리지 엔진에 XA 트랜잭션 지원이 제공됩니다. MySQL XA구현은 X/Open CAE 문서의 분산 트랜잭션 처리:XA 사양을 기반으로 합니다. 이 문서는 The Open Group에서 발행했으며 http://www.opengroup.org/public/pubs/catalog/c193.htm에서 볼 수 있습니다. 현재 XA 구현의 제한 사항은 아래에서 설명드립니다.
클라이언트 측에는 특별한 요구 사항이 없습니다. MySQL 서버에 대한 XA 인터페이스는 XA 키워드로 시작하는 SQL 문으로 구성됩니다. MySQL 클라이언트 프로그램은 SQL 문을 전송하고 XA문 인터페이스의 의미를 이해할 수 있어야 합니다. 최근 클라이언트 라이브러리와 연결될 필요는 없습니다. 이전 클라이언트 라이브러리도 작동합니다.
MySQL 커넥터중 MySQL Connector/J 5.0.0 이상은 XA SQL 문 인터페이스를 처리하는 클래스 인터페이스를 통해 XA를 직접 지원합니다.
XA는 분산 트랜잭션, 즉 여러 개의 개별 트랜잭션 자원이 글로벌 트랜잭션에 참여할 수 있게하는 기능을 지원합니다. 트랜잭션 자원은 종종 RDBMS이지만 다른 종류의 자원일 수도 있습니다.
글로벌 트랜잭션에는 자체적으로 트랜잭션이 되는 몇 가지 조치가 포함되지만 모두 그룹으로 완료되거나 모두 그룹으로 롤백되어야 합니다. 본질적으로 이것은 ACID 속성을 "일정 수준 이상으로"확장하여 여러 ACID 트랜잭션을 ACID속성이 있는 전역 작업의 구성 요소로 함께 실행할 수 있습니다. 분산되지 않은 트랜잭션과 마찬가지로 응용 프로그램이 읽기 현상에 민감한 경우 SERIALIZABLE이 선호될 수 있습니다. 분산 트랜잭션에는 반복 읽기가 충분하지 않을 수 있습니다.
분산 트랜잭션의 예 :
+ 응용 프로그램은 메시징 서비스와 RDBMS를 결합하는 통합 도구 역할을 할 수 있습니다. 응용 프로그램은 트랜잭션 데이터베이스와 관련된 메시지 전송, 검색 및 처리를 다루는 트랜잭션이 모두 전역 트랜잭션에서 발생하도록합니다. 이것을 "트랜잭션화 이메일"로 생각할 수 있습니다.
+ 애플리케이션은 MySQL 서버 및 Oracle 서버(또는 여러 MySQL 서버)와 같은, 혹은 서로 다른 데이터베이스 서버와 관련된 작업을 수행합니다. 이 작업은 각 서버에 로컬로 수행되는 별도의 트랜잭션이 아니라 글로벌 트랜잭션의 일부로 수행되어야 합니다.
+ 은행은 계좌 정보를 RDBMS에 보관하고 현금 자동 입출금기(ATM)를 통해 돈을 분배하고 받습니다. ATM 조치가 계정에 올바르게 반영되도록 해야하지만 RDBMS만으로는이를 수행 할 수 없습니다. 글로벌 트랜잭션 관리자는 ATM과 데이터베이스 자원을 통합하여 금융 트랜잭션의 전반적인 일관성을 보장합니다.
글로벌 트랜잭션을 사용하는 응용 프로그램에는 하나 이상의 자원 관리자 및 트랜잭션 관리자가 포함됩니다.
+ RM (Resource Manager)은 트랜잭션 리소스에 대한 액세스를 제공합니다. 데이터베이스 서버는 일종의 자원 관리자입니다. RM이 관리하는 트랜잭션을 커미트하거나 롤백할 수 있어야 합니다.
+ 트랜잭션 관리자 (TM)는 글로벌 트랜잭션의 일부인 트랜잭션을 조정합니다. 각 트랜잭션을 처리하는 RM과 통신합니다. 글로벌 트랜잭션 내의 개별 트랜잭션은 글로벌 트랜잭션의 "분기"입니다. 글로벌 트랜잭션 및 해당 지점은 나중에 설명하는 이름 지정 체계로 식별됩니다.
XA의 MySQL 구현을 통해 MySQL 서버는 글로벌 트랜잭션 내에서 XA 트랜잭션을 처리하는 리소스 관리자로 작동할 수 있습니다. MySQL 서버에 연결되는 클라이언트 프로그램은 트랜잭션 관리자 역할을 합니다.
글로벌 트랜잭션을 수행하려면 어떤 구성 요소가 관련되어 있는지 파악하고 각 구성 요소를 커밋하거나 롤백 할 수 있는 시점으로 가져와야 합니다. 각 구성 요소가 성공하는 능력에 대해 보고하는 내용에 따라 모두 원자 그룹으로 커밋하거나 롤백해야 합니다. 즉, 모든 구성 요소가 커미트되거나 모든 구성 요소가 롤백되어야합니다. 글로벌 트랜잭션을 관리하려면 모든 구성 요소 또는 연결 네트워크가 실패할 수 있음을 고려해야합니다.
글로벌 트랜잭션을 실행하는 프로세스는 2단계 커밋 (2PC)을 사용합니다. 이것은 글로벌 트랜잭션의 브랜치에 의해 수행된 조치가 실행된 후에 발생합니다.
1. 첫 번째 단계에서 모든 브랜치가 준비됩니다. 즉, TM에 의해 커밋 할 준비가 되었음을 알려줍니다. 일반적으로 이는 브랜치를 관리하는 각 RM이 안정적인 저장소에 지점에 대한 작업을 기록함을 의미합니다. 분기는이 작업을 수행할 수 있는지 여부를 나타내며이 결과는 두 번째 단계에 사용됩니다.
2. 두 번째 단계에서 TM은 RM에게 커밋 또는 롤백 여부를 알려줍니다. 모든 지점에서 커밋할 수 있음을 표시한 경우 모든 지점에 커밋하라는 메시지가 표시됩니다. 준비된 시점에 커밋할 수 없다고 표시된 브랜치가 있으면 모든 브랜치가 롤백하라는 메시지가 표시됩니다.
경우에 따라 글로벌 트랜잭션은 1단계 커밋 (1PC)을 사용할 수 있습니다. 예를 들어, 트랜잭션 관리자가 글로벌 트랜잭션이 하나의 트랜잭션 자원 (즉, 단일 브랜치)으로만 구성된 것을 발견하면 해당 자원은 동시에 준비 및 커밋하도록 지시할 수 있습니다.
<
■ XA 트랜잭션 SQL 구문
MySQL에서 XA 트랜잭션을 수행하려면 다음 명령문을 사용합니다.
XA {START|BEGIN} xid [JOIN|RESUME]
XA END xid [SUSPEND [FOR MIGRATE]]
XA PREPARE xid
XA COMMIT xid [ONE PHASE]
XA ROLLBACK xid
XA RECOVER [CONVERT XID]
XA START의 경우 JOIN 및 RESUME 절이 인식되지만 효과는 없습니다.
XA END의 경우 SUSPEND [FOR MIGRATE] 절이 인식되지만 효과는 없습니다.
각 XA문은 XA키워드로 시작하며 대부분 xid 값이 필요합니다. xid는 XA 트랜잭션 식별자입니다. 명령문이 적용되는 트랜잭션을 나타냅니다. xid 값은 클라이언트에 의해 제공되거나 MySQL 서버에 의해 생성됩니다. xid 값은 1 ~ 3 개의 부분으로 구성됩니다.
xid: gtrid [, bqual [, formatID ]]
gtrid는 전역 트랜잭션 식별자이고 bqual은 분기 한정자이며 formatID는 gtrid 및 bqual 값에 사용되는 형식을 식별하는 숫자입니다. 구문에서 알 수 있듯이 bqual 및 formatID는 선택 사항입니다. 지정하지 않으면 기본 bqual 값은 ''(아무것도없음)입니다. 지정하지 않은 경우 기본 formatID 값은 1입니다.
gtrid 및 bqual은 최대 64바이트 (문자가 아님)의 문자열 리터럴이어야 합니다. gtrid와 bqual은 여러 가지 방법으로 지정할 수 있습니다. 따옴표 붙은 문자열 ( 'ab'), 16 진 문자열 (X'6162 ', 0x6162) 또는 비트 값 (b'nnnn')을 사용할 수 있습니다.
formatID는 부호없는 정수입니다.
gtrid 및 bqual 값은 MySQL 서버의 기본 XA지원 루틴에 의해 바이트 단위로 해석됩니다. 그러나 XA 문을 포함하는 SQL 문을 구문 분석하는 동안 서버는 특정 문자 세트로 작동합니다. 안전을 위해 gtrid와 bqual을 16진 문자열로 작성합니다.
xid 값은 일반적으로 트랜잭션 관리자에 의해 생성됩니다. 한 TM에 의해 생성된 값은 다른 TM에 의해 생성 된 값과 달라야합니다. 지정된 TM은 XA RECOVER문이 리턴한 값 목록에서 자체 xid 값을 인식 할 수 있어야합니다.
XA START xid는 주어진 xid 값으로 XA 트랜잭션을 시작합니다. 각 XA 트랜잭션에는 고유한 xid 값이 있어야 하므로 현재 다른 XA트랜잭션에서 이 값을 사용해서는 안됩니다. 독창성은 gtrid 및 bqual 값을 사용하여 평가됩니다. XA 트랜잭션에 대한 다음의 모든 XA문은 XA START문에 제공된 것과 동일한 xid 값을 사용하여 지정해야 합니다. 해당 명령문 중 하나를 사용하지만 일부 기존 XA 트랜잭션에 해당하지 않는 xid 값을 지정하면 오류가 발생합니다.
하나 이상의 XA 트랜잭션이 동일한 글로벌 트랜잭션의 일부일 수 있습니다. 지정된 글로벌 트랜잭션 내의 모든 XA 트랜잭션은 xid 값에서 동일한 gtrid값을 사용해야 합니다. 이러한 이유로 gtrid 값은 전역적으로 고유해야 특정 XA 트랜잭션이 어떤 글로벌 트랜잭션에 속하는지 모호하지 않습니다. xid 값의 bqual 부분은 글로벌 트랜잭션 내의 각 XA 트랜잭션마다 달라야합니다. bqual 값이 달라야한다는 요구 사항은 현재 MySQL XA 구현의 제한 사항입니다. 이는 XA사양의 일부가 아닙니다.
XA RECOVER 문은 PREPARED 상태에있는 MySQL서버에서 해당 XA트랜잭션에 대한 정보를 리턴합니다. 출력에는 시작한 클라이언트에 관계없이 서버에서 이러한 각 XA 트랜잭션에 대한 행이 포함됩니다.
XA RECOVER 출력 행은 다음과 같습니다 (예 : 'abc', 'def'및 7 부분으로 구성된 xid 값).
mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+--------+
| 7 | 3 | 3 | abcdef |
+----------+--------------+--------------+--------+
출력 열의 의미는 다음과 같습니다.
+ formatID는 트랜잭션 xid의 formatID 부분입니다.
+ gtrid_length는 xid의 gtrid 부분의 길이 (바이트)입니다
+ bqual_length는 xid의 bqual 부분의 길이 (바이트)입니다
+ 데이터는 xid의 gtrid와 bqual 부분의 연결입니다
XID 값은 인쇄할 수 없는 문자를 포함할 수 있습니다. MySQL 5.7.5부터 XA RECOVER는 선택적 CONVERT XID 절을 허용하므로 클라이언트가 16진수로 XID 값을 요청할 수 있습니다.
■ XA 거래 상태
XA 트랜잭션은 다음 상태를 통해 진행됩니다.
1. XA START를 사용하여 XA 트랜잭션을 시작하고 ACTIVE 상태로 둡니다.
2. ACTIVE XA 트랜잭션의 경우 트랜잭션을 구성하는 SQL 문을 실행한 후 XA END 문을 실행합니다. XA END는 트랜잭션을 유휴 상태에 둡니다.
3. 유휴 XA 트랜잭션의 경우 XA PREPARE 문 또는 XA COMMIT ... ONE PHASE 문을 수행할 수 있습니다.
+ XA PREPARE는 트랜잭션을 PREPARED 상태로 둡니다. XA RECOVER는 PREPARED 상태에있는 모든 XA 트랜잭션을 나열하므로이 시점에서 XA RECOVER 문은 트랜잭션의 xid 값을 출력에 포함합니다.
+ XA COMMIT ... ONE PHASE는 트랜잭션을 준비하고 커밋합니다. 트랜잭션이 종료되므로 xid 값은 XA RECOVER에 의해 나열되지 않습니다.
4. PREPARED XA 트랜잭션의 경우 XA COMMIT 문을 발행하여 트랜잭션을 커미트 및 종료하거나 XA ROLLBACK을 사용하여 트랜잭션을 롤백 및 종료 할 수 있습니다.
다음은 글로벌 트랜잭션의 일부로 테이블에 행을 삽입하는 간단한 XA 트랜잭션입니다.
mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)
mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)
mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)
mysql> XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)
주어진 클라이언트 연결의 맥락에서 XA 트랜잭션과 로컬 (XA이외) 트랜잭션은 상호 배타적입니다. 예를 들어, XA START가 XA 트랜잭션을 시작하도록 발행된 경우 XA 트랜잭션이 커미트되거나 롤백될 때까지 로컬 트랜잭션을 시작할 수 없습니다. 반대로 START TRANSACTION으로 로컬 트랜잭션이 시작된 경우 트랜잭션이 커밋되거나 롤백 될 때까지 XA 문을 사용할 수 없습니다.
XA 트랜잭션이 ACTIVE 상태인 경우 내재된 커미트를 유발하는 명령문을 발행할 수 없습니다. XA 트랜잭션을 롤백할 수 없기 때문에 XA 트랜잭션을 위반하게 됩니다. 이러한 명령문을 실행하려고 하면 다음 오류가 발생합니다.
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
■ XA 거래에 대한 제한
XA 트랜잭션 지원은 InnoDB 스토리지 엔진으로 제한됩니다.
"외부 XA"의 경우 MySQL서버는 리소스 관리자 역할을 하며 클라이언트 프로그램은 트랜잭션 관리자 역할을합니다. “내부 XA”의 경우 MySQL 서버 내의 스토리지 엔진은 RM(Resource Manager)의 역할을 하며 서버 자체는 TM의 역할을합니다. 내부 XA지원은 개별 스토리지 엔진의 기능에 의해 제한됩니다. 하나 이상의 스토리지 엔진과 관련된 XA 트랜잭션을 처리하려면 내부 XA가 필요합니다. 내부 XA를 구현하려면 스토리지 엔진이 테이블 핸들러 레벨에서 2단계 커밋을 지원해야하며 현재 InnoDB에만 해당됩니다.
XA START의 경우 JOIN 및 RESUME 절이 인식되지만 효과는 없습니다.
XA END의 경우 SUSPEND [FOR MIGRATE] 절이 인식되지만 효과는 없습니다.
xid 값의 bqual부분이 전역 트랜잭션 내의 각 XA트랜잭션마다 달라야한다는 요구 사항은 현재 MySQL XA 구현의 제한 사항입니다. XA 사양의 일부가 아닙니다.
MySQL 5.7.7 이전에는 XA트랜잭션이 복제와 호환되지 않았습니다. PREPARED 상태인 XA 트랜잭션이 클린 서버 종료 또는 클라이언트 연결 해제시 롤백되기 때문입니다. 마찬가지로 서버가 비정상적으로 종료되었다가 다시 시작된 경우 PREPARED 상태인 XA 트랜잭션은 여전히 PREPARED 상태로 존재하지만 트랜잭션의 내용을 2진 로그에 쓸 수 없습니다. 이 두 가지 상황에서 XA 트랜잭션을 올바르게 복제 할 수 없습니다.
MySQL 5.7.7 이상에서는 동작에 변화가 있으며 XA트랜잭션은 두 부분으로 이진 로그에 기록됩니다. XA PREPARE가 실행될 때 XA PREPARE까지의 트랜잭션의 첫 번째 부분은 초기 GTID를 사용하여 작성됩니다. XA_prepare_log_event는 이진 로그에서 이러한 트랜잭션을 식별하는 데 사용됩니다. XA COMMIT 또는 XA ROLLBACK이 발행될 때 XA COMMIT 또는 XA ROLLBACK문만 포함하는 트랜잭션의 두 번째 부분은 두번째 GTID를 사용하여 작성됩니다. XA_prepare_log_event로 식별되는 트랜잭션의 초기 부분 뒤에 반드시 XA COMMIT 또는 XA ROLLBACK이 오는 것은 아니며 두 XA 트랜잭션의 인터리브 이진 로깅을 유발할 수 있습니다. XA 트랜잭션의 두 부분은 다른 이진 로그 파일에도 나타날 수 있습니다. 이는 PREPARED 상태의 XA 트랜잭션이 이제 명시적 XA COMMIT 또는 XA ROLLBACK 문이 발행될 때까지 지속되어 XA 트랜잭션이 복제와 호환되도록합니다.
복제 슬레이브에서는 XA 트랜잭션이 준비된 직후에 슬레이브 애플리케이션 스레드에서 분리되어 슬레이브의 모든 스레드에 의해 커밋되거나 롤백될 수 있습니다. 이는 동일한 XA 트랜잭션이 다른 스레드에서 다른 상태로 events_transactions_current 테이블에 나타날 수 있음을 의미합니다. events_transactions_current 테이블은 스레드에서 가장 최근에 모니터링된 트랜잭션 이벤트의 현재 상태를 표시하며 스레드가 유휴 상태일 때 이 상태를 업데이트하지 않습니다. 따라서 XA 트랜잭션은 다른 스레드에서 처리된 후에도 원래 적용자 스레드에 대해 PREPARED 상태로 계속 표시될 수 있습니다. 여전히 PREPARED 상태이고 복구해야하는 XA 트랜잭션을 긍정적으로 식별하려면 성능 스키마 트랜잭션 테이블 대신 XA RECOVER 문을 사용합니다.
MySQL 5.7.7 이상에서 XA 트랜잭션을 사용하는 경우 다음과 같은 제한 사항이 있습니다.
+ XA 트랜잭션은 이진 로그와 관련하여 예기치 않은 중지로 완전히 복원되지 않습니다. 서버가 XA PREPARE, XA COMMIT, XA ROLLBACK 또는 XA COMMIT ... ONE PHASE문을 실행하는 동안 예기치 않게 중지가 발생하면 서버는 올바른 상태로 복구되지 않아 서버와 바이너리 로그가 일치하지 않는 상태로 남아 있을 수 있습니다. 이 상황에서 바이너리 로그에는 적용되지 않은 추가 XA 트랜잭션이 포함되거나 적용되는 XA 트랜잭션이 누락 될 수 있습니다. 또한 GTID가 사용 가능한 경우 복구 후 @@ GLOBAL.GTID_EXECUTED가 적용된 트랜잭션을 올바르게 설명하지 않을 수 있습니다. XA PREPARE 이전, XA PREPARE와 XA COMMIT (또는 XA ROLLBACK) 사이 또는 XA COMMIT (또는 XA ROLLBACK) 이후에 예기치 않은 중지가 발생하면 서버 및 바이너리 로그가 올바르게 복구되고 일관된 상태가됩니다.
+ XA 트랜잭션과 함께 복제 필터 또는 바이너리 로그 필터를 사용할 수 없습니다. 테이블을 필터링하면 복제 슬레이브에서 XA 트랜잭션이 비어있을 수 있으며 빈 XA 트랜잭션은 지원되지 않습니다. 또한 MySQL 8.0에서 기본값이 된 복제 슬레이브에서 master_info_repository=TABLE 및 relay_log_info_repository=TABLE 설정을 사용하면 필터링 된 XA 트랜잭션에 따라 데이터 엔진 트랜잭션의 내부 상태가 변경되고 복제 트랜잭션 컨텍스트와 일치하지 않을 수 있습니다. 상태.
트랜잭션이 비어 있는지 여부에 관계없이 XA 트랜잭션이 복제 필터의 영향을받을 때마다 오류 ER_XA_REPLICATION_FILTERS가 기록됩니다. 트랜잭션이 비어 있지 않으면 복제 슬레이브는 계속 실행할 수 있지만 잠재적 문제를 피하기 위해 XA 트랜잭션에서 복제 필터 사용을 중단하는 단계를 수행해야 합니다. 트랜잭션이 비어 있으면 복제 슬레이브가 중지됩니다. 이 경우 복제 슬레이브가 결정되지 않은 상태에 있을수 있으며 이 경우 복제 프로세스의 일관성이 손상될 수 있습니다. 특히 슬레이브의 슬레이브에 설정된 gtid_executed는 마스터의 슬레이브와 일치하지 않을 수 있습니다. 이 상황을 해결하려면 마스터를 격리하고 모든 복제를 중지한 다음 복제 토폴로지에서 GTID 일관성을 확인합니다. 오류 메시지를 생성 한 XA 트랜잭션을 실행 취소 한 후 복제를 다시 시작합니다.
+ MySQL 5.7.19 이전에는 FLUSH TABLES WITH READ LOCK은 XA 트랜잭션과 호환되지 않습니다.
+ XA 트랜잭션은 명령문 기반 복제에 안전하지 않은 것으로 간주됩니다. 마스터에서 병렬로 커밋된 두 개의 XA 트랜잭션을 역순으로 슬레이브에서 준비하는 경우 잠금 문제가 발생하여 안전하게 해결할 수 없으며 슬레이브에서 교착 상태로 인해 복제가 실패할 수 있습니다. 이 상황은 단일 스레드 또는 다중 스레드 복제 슬레이브에 발생할 수 있습니다. binlog_format = STATEMENT가 설정되면 XA 트랜잭션 내부의 DML 문에 대해 경고가 발행됩니다. binlog_format = MIXED 또는 binlog_format = ROW가 설정되면 XA 트랜잭션 내부의 DML 문은 행 기반 복제를 사용하여 기록되며 잠재적인 문제는 없습니다.
'Databases > MySQL' 카테고리의 다른 글
[MySQL] Truncate Table 명령 (0) | 2020.09.21 |
---|---|
[MySQL] 메모리 사용 최적화 (0) | 2020.09.16 |
[MySQL] SET TRANSACTION 문 (0) | 2020.09.12 |
[MySQL] SAVEPOINT, ROLLBACK TO SAVEPOINT, 그리고 RELEASE SAVEPOINT문 (0) | 2020.09.08 |
[MySQL] Table Partitioning - MAXVALUE 파티션에 따른 테이블 재구성시 유의사항 (0) | 2020.09.07 |