MySQL 스터디에서 공유했던 MySQL 8과 5.7 간 replication 기능의 차이점 위주로 정리한 내용입니다.
복제관련해서 무언가 기존엔 없던 새로운 기능이 생겨난 게 아니라 기존 기능에서 좀 더 개선된 사항들이 나왔다.
- MSR replicate_rewrite_db 필터 적용 범위 개선 (global -> channel)
- crash safe replication을 위한 파라미터의 변경
- semi-sync의 동작방식에 대한 변경
- binary log 트랜잭션 압축 기능 추가
- multi threaded replication에서 writeset 기능 추가
multi source replication
변경사항 : multi source replication에서 replication filter 중 REPLICATE_REWRITE_DB가 global이 아닌 channel 별로 적용됨 mysql 5.7 버전부터 multi-source replication 기능이 생기면서 유용하게 사용되고 있지만 두대 이상의 Master 에서 같은 이름의 database를 구분 지어 다른 db명으로 변경해서 replication 설정은 불가능했음 MySQL 8.0부터 MSR 구성에서 REPLICATE_REWRITE_DB 설정이 global 이 아닌, channel 별로 가능해짐
mysql 5.7
Master 1: kimdubi_db => Slave : kimdubi_db
Master 2: kimdubi_db => Slave : kimdubi_db
- Master server들의 논리DB명이 같으면 Slave 서버에서는 이를 구분해서 각각 받아올 수가 없음
- change replication filter replicate_do_db=(master1,master2), replicate_rewrite_db=((kimdubi_test,master1),(kimdubi_test,master2));
- 이렇게 해도 replicate_rewrite_db 설정이 channel 별이 아닌 global로 적용되어서 master1로 데이터를 받게됨
- 만약 Master 1번 서버에서 delete 를 했다? binlog format=ROW 가 아니면 복제가 깨질 수 있음
mysql 8.0
Master 1: kimdubi_db => Slave : kimdubi_db1
Master 2: kimdubi_db => Slave : kimdubi_db2
- MySQL 5.7과 달리 Master서버들의 논리DB가 같아도 채널별로 논리DB를 rewrite해서 받아올 수 있음
mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (kimdubi_db1), REPLICATE_REWRITE_DB = (kimdubi_db, kimdubi_db1)) FOR CHANNEL 'master_1';
mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (kimdubi_db2), REPLICATE_REWRITE_DB = (kimdubi_db, kimdubi_db2)) FOR CHANNEL 'master_2';
- REPLICATE_REWRITE_DB = kimdubi_db,kimdubi_db2
- 앞의 kimdubi_db는 source DB의 논리DB, 뒤의 kimdubi_db2는 앞의 kimdubi_db를 rewrite 치환해서 slave에서 replication 받는 DB
- relay log에서 kimdubi_db로 들어오고 sql_thread가 relaylog를 읽고 DB에 반영하면서 kimdubi_db2로 바꾸어 읽게 됨
구성방법
mysql> show variables like '%repository%';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| master_info_repository | TABLE |
| relay_log_info_repository | TABLE |
+---------------------------+-------+
- MSR 설정을 위해서는 replication 관련 정보 repository 를 TABLE 에 저장해야함
- master_info_repository=TABLE 의미는 Slave가 복제하는 MASTER DB의 status와 connection inforamtion 정보를 mysql.slave_master_info 에 저장하겠다는 의미
- relay_log_info_repository=TABLE => 복제 관련 파일 및 포지션 정보를 mysql.slave_relay_log_info 에 저장
- 8.0부터 default TABLE
replication channel 구성
mysql> change master to
-> master_host='172.17.0.6',
-> master_port=3306,
-> master_user='replUser',
-> master_password='!dlatl00',
-> master_log_file='mysql-bin.000011',
-> master_log_pos=789
-> for channel 'master_1'; <============= 채널
Query OK, 0 rows affected, 2 warnings (0.05 sec)
mysql> change master to
-> master_host='172.17.0.7',
-> master_port=3306,
-> master_user='replUser',
-> master_password='!dlatl00',
-> master_log_file='mysql-bin.000010',
-> master_log_pos=1099
-> for channel 'master_2'; <============= 채널
Query OK, 0 rows affected, 2 warnings (0.04 sec)
mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (kimdubi_db1), REPLICATE_REWRITE_DB = (kimdubi_db, kimdubi_db1)) FOR CHANNEL 'master_1';
Query OK, 0 rows affected (0.01 sec)
mysql> CHANGE REPLICATION FILTER REPLICATE_DO_DB = (kimdubi_db2), REPLICATE_REWRITE_DB = (kimdubi_db, kimdubi_db2)) FOR CHANNEL 'master_2';
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.0.6
Master_User: replUser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000011
Read_Master_Log_Pos: 992
Relay_Log_File: relay-bin-master_1.000003
Relay_Log_Pos: 322
Relay_Master_Log_File: mysql-bin.000011
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: kimdubi_db1
Exec_Master_Log_Pos: 992
Relay_Log_Space: 903
Until_Condition: None
Master_Server_Id: 64
Master_UUID: ba315763-e7e8-11e9-9c29-0242ac110002
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Replicate_Rewrite_DB: (kimdubi_db,kimdubi_db1)
Channel_Name: master_1
*************************** 2. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.0.7
Master_User: replUser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000010
Read_Master_Log_Pos: 1302
Relay_Log_File: relay-bin-master_2.000004
Relay_Log_Pos: 322
Relay_Master_Log_File: mysql-bin.000010
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: kimdubi_db2
Exec_Master_Log_Pos: 1302
Relay_Log_Space: 903
Master_Server_Id: 2
Master_UUID: ba315763-e7e8-11e9-9c29-0242ac110002
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Replicate_Rewrite_DB: (kimdubi_db,kimdubi_db2)
Channel_Name: master_2
2 rows in set (0.00 sec)
복제 테스트
- MySQL 8.0
### MASTER_1 에서 수행
mysql> use kimdubi_db;
Database changed
mysql> create table test (t int);
Query OK, 0 rows affected (0.09 sec)
mysql> insert into test values(1);
Query OK, 1 row affected (0.05 sec)
### MASTER_2 에서 수행
mysql> use kimdubi_db;
Database changed
mysql> create table test (t int);
Query OK, 0 rows affected (0.07 sec)
mysql> insert into test values(2);
Query OK, 1 row affected (0.03 sec)
### SLAVE에서 데이터 확인
mysql> select * from kimdubi_db1.test;
+------+
| t |
+------+
| 1 |
+------+
1 row in set (0.01 sec)
mysql> select * from kimdubi_db2.test;
+------+
| t |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
- MySQL 5.7
### MASTER_1 에서 수행
mysql> use kimdubi_db;
Database changed
mysql> create table test (t int);
Query OK, 0 rows affected (0.09 sec)
mysql> insert into test values(1111111);
Query OK, 1 row affected (0.05 sec)
### MASTER_2 에서 수행
mysql> use kimdubi_db;
Database changed
mysql> create table test (t int);
Query OK, 0 rows affected (0.07 sec)
mysql> insert into test values(222222);
Query OK, 1 row affected (0.03 sec)
### slave에서 조회
mysql> select * from kimdubi_db2.tb_test;
Empty set (0.01 sec)
mysql> select * from kimdubi_db1.tb_test;
+---------+
| a |
+---------+
| 222222 |
| 1111111 |
+---------+
2 rows in set (0.01 sec)
### 데이터 깨짐 현상
### master_1
mysql> select * from tb_test;
+---------+
| a |
+---------+
| 1111111 |
+---------+
1 row in set (0.00 sec)
### 복제DB
mysql> select * from tb_test;
+---------+
| a |
+---------+
| 22222 |
| 1111111 |
+---------+
2 rows in set (0.00 sec)
### master_1
mysql> set session binlog_format='STATEMENT';
Query OK, 0 rows affected (0.00 sec)
mysql> delete from tb_test where a < 11111111;
Query OK, 1 row affected (0.01 sec)
### 복제DB
mysql> select * from tb_test;
Empty set (0.00 sec)
=> master_2 에서 받은 데이터도 모두 날아간 상태에서 master_2에서 해당 데이터에 대해 DML이 들어오면?
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.0.4
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4046
Relay_Log_File: 8bb84cc87d63-relay-bin-master_1.000005
Relay_Log_Pos: 856
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB: master1,master2
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1032
Last_Error: Could not execute Delete_rows event on table master1.tb_test; Can't find record in 'tb_test', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000001, end_log_pos 4015
crash safe replication
변경사항 : crash_safe replication의 필수 설정 중 하나인 relay_log_info_repository 설정의 default 값이 FILE -> TABLE로 변경됨 MySQL 서버가 예기치 못한 장애로 인해 비정상 종료 되는 경우, SLAVE를 재기동 했을 때 복제가 원활하게 재개될수 있도록 하는 여러 설정 조합의 효과
- I/O thread가 relay log에 복제할 event를 기록하고 sync_master_info 파일에 기록하기 전에 MySQL서버가 비정상 종료되면, MySQL을 재기동한 뒤 I/O thread가 위의 이벤트를 relay log에 또다시 기록해서 복제 duplicate 날 수 있음
- SQL thread가 relay log에 기록된 트랜잭션을 커밋한 후 sync_relay_log_info 파일에 포지션 정보를 기록하기 전에 MySQL서버가 비정상 종료되면, MySQL을 재기동한 뒤 위의 동일한 트랜잭션을 또 replay할 수 있음
crash-safe Replicaion 설정
필수
- relay_log_info_repository=TABLE
- relay_log_recovery = on
그 외 상황별 필요 파라미터
variable | MySQL 5.7 (default) | MySQL 8.0 (default) | comment |
---|---|---|---|
relay_log_recovery | OFF | OFF | 필수 ON |
relay_log_info_repository | FILE | TABLE | GTID 복제 시엔 필요없음 (mysql.gtid_executed가 대체) |
sync_relay_log | 10000 | 10000 | MTS + slave_preserve_commit_order=0 일 땐 sync_relay_log = 1 필요 |
slave_preserve_commit_order | OFF | OFF / ON (MySQL 8.0.27이상부터는 ON) | 권장값 ON (트랜잭션 갭 메울 필요 없어짐) |
sync_binlog | 1 | 1 | GTID 복제 시 sync_binlog = 1 필요 (replica서버에서) |
innodb_flush_log_at_trx_commit | 1 | 1 | GTID 복제 시 innodb_flush_log_at_trx_commit =1 필요 (replica서버에서) |
동작 방식
### relay_log_info_repository = TABLE
begin;
insert into tb_test values(1);
update mysql.slave_relay_log_info set Relay_log_name='./relay-bin.000006',replay_log_pos=1356;
commit;
### relay_log_recovery = ON
2020-05-03T12:19:21.402872Z 0 [Warning] [MY-010539] [Repl] Recovery from master pos 1142 and file mysql-bin.000003 for channel ''. Previous relay log pos and relay log file had been set to 322, ./relay-bin.000014 respectively.
- relay_log_info_repository = TABLE 설정 시 위 처럼, SQL thread가 position 정보 업데이트와 실제 트랜잭션 처리를 원자적으로 수행함
- 반면 I/O thread는 실제 relay log 파일에도 쓰고, mysql.slave_master_info 테이블에도 update하는 작업을 sql thread처럼 원자적으로 수행할 수 없음
- relay_log_recovery = ON 설정 시 I/O thread의 포지션을 SQL thread가 마지막으로 실행했던 포지션으로 초기화 하고 새로운 relay log 파일을 생성해서 sql thread가 읽어야할 relay log position을 초기화하는 식으로 동작하게 하여 I/O thread의 문제를 해결할 수 있음
mysql.slave_master_info, mysql.slave_relay_log_info 테이블 내용
mysql> select * from slave_relay_log_info;
+-----------------+------------------------------------------+---------------+------------------+----------------+-----------+-------------------+----+--------------+
| Number_of_lines | Relay_log_name | Relay_log_pos | Master_log_name | Master_log_pos | Sql_delay | Number_of_workers | Id | Channel_name |
+-----------------+------------------------------------------+---------------+------------------+----------------+-----------+-------------------+----+--------------+
| 7 | ./8bb84cc87d63-relay-bin-master_1.000005 | 856 | mysql-bin.000001 | 3763 | 0 | 0 | 1 | master_1 |
| 7 | ./8bb84cc87d63-relay-bin-master_2.000004 | 1124 | mysql-bin.000001 | 3493 | 0 | 0 | 1 | master_2 |
+-----------------+------------------------------------------+---------------+------------------+----------------+-----------+-------------------+----+--------------+
2 rows in set (0.00 sec)
mysql> select * from slave_master_info;
+-----------------+------------------+----------------+------------+-----------+---------------+------+---------------+-------------+--------+------------+----------+------------+---------+------------------------+-----------+------+--------------------+--------------------------------------+-------------+---------+-------------+-----------------------+--------------+-------------+
| Number_of_lines | Master_log_name | Master_log_pos | Host | User_name | User_password | Port | Connect_retry | Enabled_ssl | Ssl_ca | Ssl_capath | Ssl_cert | Ssl_cipher | Ssl_key | Ssl_verify_server_cert | Heartbeat | Bind | Ignored_server_ids | Uuid | Retry_count | Ssl_crl | Ssl_crlpath | Enabled_auto_position | Channel_name | Tls_version |
+-----------------+------------------+----------------+------------+-----------+---------------+------+---------------+-------------+--------+------------+----------+------------+---------+------------------------+-----------+------+--------------------+--------------------------------------+-------------+---------+-------------+-----------------------+--------------+-------------+
| 25 | mysql-bin.000001 | 3227 | 172.17.0.4 | root | qhdks123 | 3306 | 60 | 0 | | | | | | 0 | 30 | | 0 | 6ee46ea8-753f-11ec-be3b-0242ac110004 | 86400 | | | 0 | master_1 | |
| 25 | mysql-bin.000001 | 2689 | 172.17.0.5 | root | qhdks123 | 3306 | 60 | 0 | | | | | | 0 | 30 | | 0 | bfe2850b-753f-11ec-8148-0242ac110005 | 86400 | | | 0 | master_2 | |
+-----------------+------------------+----------------+------------+-----------+---------------+------+---------------+-------------+--------+------------+----------+------------+---------+------------------------+-----------+------+--------------------+--------------------------------------+-------------+---------+-------------+-----------------------+--------------+-------------+
2 rows in set (0.00 sec)
semi-sync
변경사항 : semi-sync의 동작방식이 after_commit -> after_sync로 변경됨
after_commit
- User transaction commit
- Engine prepare
- Binlog flush
- Binlog commit
- Engine commit
- Binlog dump thread send event with ACK Request
- semi-sync wait (AFTER_COMMIT)
- User Commit OK
- 7번 Slave가 data를 받았다는 응답을 기다리는 도중 Master가 down 되면 Master에서는 이미 Engine commit 까지 된 상황이기 때문에 새로 승격될 Slave에는 데이터가 없지만 Old Master에는 데이터가 존재하여 정합성이 깨짐
- 5번 engine commit 이 된 시점부터 다른 세션에서는 변경된 데이터를 읽을 수 있음 (phantom read) SLAVE로의 복제가 실패하면 이 트랜잭션은 Master에서 수동으로 rollback 처리해야함
after_sync
- User transaction commit
- Engine prepare
- Binlog flush
- Binlog commit
- Binlog dump thread send event with ACK Request
- loss-less semisync wait (AFTER_SYNC)
- Engine commit
- User Commit OK
- after_sync에서는 레플리카 서버에 복제되지 않았다면, 소스 서버에서도 engine commit까지 될 수 없기 때문에 after_commit의 phantom read 같은 경우가 발생하지 않음
- engine commit이 늦춰져서 semi-sync에 대한 부담감이 높아질 수 있음
- 아래 파라미터를 적절하게 변경해보자
- rpl_semi_sync_master_timeout (default 10초)
- rpl_semi_sync_master_wait_for_slave_count (default 1)
binary log 트랜잭션 압축
변경사항 : binlog_format = ROW으로 기록되는 트랜잭션에 대해 트랜잭션에서 변경한 데이터를 압축해서 바이너리 로그에 기록하는 기능이 추가도미
- 트랜잭션에서 변경한 데이터를 zstd 알고리즘으로 압축
- transaction_payload_event라는 이벤트로 바이너리 로그에 기록
- 압축된 상태로 레플리카 서버의 relay log에 기록됨
- 압축 해제 후 레플리카 서버에 반영됨
- 마스터 뿐만 아니라 리플리카도 압축 기능을 지원하는 MySQL 버전을 사용해야함
- 효과는 압축률 50%정도, 네트워크 사용량은 1/3 정도, CPU는 조금 더 쓰는 정도
관련 파라미터
- binlog_transaction_compression (default OFF )
- binlog_transaction_compression_level_zstd (default 3)
- performance-schema-instrument=“stage/sql/%compressing_transaction_changes.=ON”
- protocol_compression_algorithms=‘zlib,zstd,uncompressed’;
limitation
- GTID 설정 관련 이벤트
- 복제 구성에서 heartbeat 관련 이벤트
- 복제 실패 / 데이터 불일치를 발생시킬 수 있는 incident 타입의 이벤트(?)
- 트랜잭션을 지원하지 않는 스토리지 엔진에 대한 이벤트
- binlog_format = statement 로 기록되는 이벤트
구성 방법
mysql> change master to
-> master_host='172.17.0.6',
-> master_port=3306,
-> master_user='replUser',
-> master_password='!dlatl00',
-> master_log_file='mysql-bin.000011',
-> master_log_pos=789
-> source_compression_algorithms='zstd',
-> source_zstd_compression_level=7;
delayed replication
변경사항 : binary log에 OCT, ICT timestamp가 추가되었고 특히 ICT는 delayed replication의 기준으로 작용함
original_commit_timestamp (OCT)
- 트랜잭션이 원본 소스 서버에서 커밋된 시각
immediate_commit_timestamp (ICT)
- 트랜잭션이직계 소스 서버에서 커밋된 시각
어디에 쓰이는고
- 체인 복제 구성 + delayed replication의 구조에서 의미가 있는 듯
- 원본 소스 서버에서는 OCT == ICT
- 레플리카 서버(log_slave_updates = ON)에서는 ICT 값이 복제된 트랜잭션이 커밋된 시점으로 기록되기 때문에 OCT != ICT MySQL 8.0 미만의 체인복제 구성에서 delayed replication의 지연 측정 기준이 원본 소스의 시각으로 측정되던 부분이 직계 소스 서버를 기준으로 할 수 있도록 개선되었음
multi-threaded replication
변경사항 : multi-thread-replication의 slave_parallel_type=‘logical_clock’ 방식 중 writeset 방식이 추가됨
관련 파라미터
variable | MySQL 5.7 (default) | MySQL 8.0 (default) | comment |
---|---|---|---|
slave_parallel_type | DATABASE | 8.0.27 >= LOGICAL_CLOCK / 미만 DATABASE | |
slave_parallel_workers | 1 | 8.0.27 >= 4 / 미만 1 | |
slave_pending_jobs_size_max | 16MB | 128MB | max_allowed_packet 보다 클 수 없음 |
binlog_transaction_dependency_tracking | COMMIT_ORDER | COMMIT_ORDER | |
slave_preserve_commit_order | OFF | 8.0.27 >= ON / 미만 OFF | mysql 8.0.18 이하 버전에서 ON 하려면 log_slave_updates =ON 설정도 필요함 |
binlog_order_commits | ON | ON | replication source 서버에 설정 |
binlog_format | ROW | ROW | writeset을 사용하기 위해서는 ROW 포맷 필요 |
## slave_pending_jobs_size_max가 작을 때 발생 가능 에러
Cannot schedule event Update_rows, relay-log relay-bin.0000,position 0000 to Worker thread because its size 21206802 exceeds 16777216 of slave_pending_jobs_size_max
## slave_preserve_commit_order ON 꼬였을 때 발생 가능 에러
ER_SLAVE_WORKER_STOPPED_PREVIOUS_THD_ERROR
slave-preserve-commit-order가 활성화되었을 때 적어도 하나의 이전 작업자에 오류가 발생한 후 슬레이브 작업자가 중지되었습니다. 커밋 순서를 유지하기 위해 이 스레드에서 실행한 마지막 트랜잭션이 커밋되지 않았습니다. 실패한 스레드를 수정한 후 슬레이브를 다시 시작할 때 이 작업자도 수정해야 합니다.
database
- 처음 multi threaded replication이 도입되었을 때 지원하던 방식으로 논리DB 단위로 병렬처리를 수행함
- MySQL 서버에 논리DB가 하나밖에 존재하지 않거나, 각 논리DB별 쓰기 부하가 일정하지 않으면 효과가 없거나 떨어짐
- slave_parallel_type=‘DATABASE’
logical
- 소스 서버에서 트랜잭션들이 binary log로 기록될 때 각 트랜잭션별로 논리적인 순번 값을 부여해 레플리카 서버에서 트랜잭션의 순번 값을 바탕으로 병렬 복제 수행하는 기능
- database type과는 달리 동일 논리DB여도 병렬 복제 가능
- group commit 단위로 할당하기 때문
- commit-parent 기반 logical clock
- MySQL 5.7.2 ~ 5.7.5버전에서 사용됨
- 소스서버에서 커밋 시점이 같은 트랜잭션들을 병렬 복제 처리함
- 커밋 시점이 같은 트랜잭션인지 식별은 commit_seq_no 값을 binary log에 같이 기록해서 식별함
- lock 기반 logical clock
- MySQL 5.7.6 버전 ~
- commit_seq_no 값이 달라도 커밋 처리 시점이 겹친다면 레플리카 서버에서 병렬 복제처리 가능
- 이를 위해 binary log에 sequence_number, last_committed라는 값을 함께 기록함
- sequence_number : 커밋된 트랜잭션에 대한 논리적인 순번 값
- last_committed : 현 트랜잭션 이전의 가장 최근의 트랜잭션의 sequence_number
- 실행하려는 트랜잭션의 last_committed 값 < 현재 실행 중인 트랜잭션들이 가지는 가장 작은 sequence_number 를 만족하는 트랜잭션들을 병렬처리함
- 예시에서는 txn+1의 C < txn 의 S 일때 병렬복제 가능
- 커밋시점이 겹치는 트랜잭션들을 늘려 병렬 복제 트랜잭션을 늘리기 위해 binlog_group_commit_sync_delay / binlog_group_commit_sync_no_delay_count를 같은 파라미터를 적절히 설정하기도함
# at 4485
#220118 13:41:09 server id 1 end_log_pos 4550 CRC32 0x2ad8ee5f Anonymous_GTID last_committed=17 sequence_number=18
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
writeset
logical_clock 의 방식 중 하나
- binlog_transaction_dependency_tracking
- commit_order : 기존 MySQL 5.7의 lock 기반 logical clock으로 동작
- writeset : 서로 다른 데이터를 변경한 트랜잭션들은 모두 병렬로 처리할 수 있음 (base는 commit_order지만 last_committed 부분을 처리하는 부분이 다름 p.536 )
- wrtieset_session : 동일한 세션에서 실행된 트랜잭션들을 제외한 트랜잭션만 병렬 처리
- 소스 서버의 트랜잭션의 커밋 처리 시점이 아닌 트랜잭션이 변경한 데이터를 기준으로 병렬 처리 가능 여부를 결정함
- 변경된 데이터를 hashing해서 writeset 으로 표현함
- table에 존재하는 unique한 key의 개수 만큼 생성됨
- 변경된 데이터를 hashing해서 writeset 으로 표현함
writeset=hash(index_name,db_name,db_name_length,table_name,table_name_length,value,value_length)
mysql> use test;
mysql> show create table jj10 \G
*************************** 1. row ***************************
Table: jj10
Create Table: CREATE TABLE `jj10` (
`id1` int(11) DEFAULT NULL,
`id2` int(11) DEFAULT NULL,
`id3` int(11) NOT NULL,
PRIMARY KEY (`id3`),
UNIQUE KEY `id1` (`id1`),
KEY `id2` (`id2`)
$ insert into jj10 values(36,36,36);
### pk
(gdb) p pke
$1 = "PRIMARY?test?4jj10?40
### UK
(gdb) p pke
$4 = "id1?test?4jj10?436?2"
=> 이거를 해싱하여 writeset으로 변환
- 위에서 생성된 writeset과 해당 데이터를 변경한 트랜잭션의 sequence_number 값이 key-value 형태로 해시맵 테이블에 저장됨
- writeset으로 구성된 새로운 트랜잭션이 실행되면 위의 writeset 히스토리 테이블과 비교하여 충돌되는 wirteset이 있는지 비교하고 last_committed 값을 보정함
- writeset 변환을 위한 추가 리소스, writeset 히스토리 테이블 구성을 위한 추가 메모리가 필요