2020년 9월 29일 화요일

Replication filter에 대하여

MySQL에서는 데이터를 복제할 때 필터 할 수 있는 기능을 제공한다.

MySQL 5.7부터는 서버 재기동 없이 온라인으로 설정할 수 있게 되었다.

Replication filter options

1. replicate-do-db=dbname # 복제할 데이터베이스 지정
2. replicate-ignore-db=dbname # 복제 대상에서 제외할 데이터베이스 지정 3. replicate-do-table=dbname.table # 복제할 테이블 지정 4. replicate-ignore-table=dbname.table # 복제 대상에서 제외할 테이블 지정 5. replicate-rewrite-db=from_name->to_name # from_name 데이터베이스를 to_name 데이터베이스로 바꿔서 복제하도록 지정 6. replicate-wild-do-table=dbname.% # 복제할 테이블을 '%' 또는 '_' 와일드카드 문자로 설정 7. replicate-wild-ignore-table=dbname.% #
제외할 테이블을 '%' 또는 '_' 와일드카드 문자로 설정

주의점
SBR(statement-based replication)에서 replicate-do-db를 이용할 경우 cross-database statements는 복제되지 않는다.
SQL thread가 default database를 기준으로 제한하고 있기 때문이다.

# On slave
mysql> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.18.0.2
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 6025
               Relay_Log_File: mysql-relay-bin.000015
                Relay_Log_Pos: 395
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: test_db_01 # Slave에서 test_db_01만을 복제하도록 설정
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:

# On master
mysql> USE mysql;
Database changed
mysql> INSERT INTO test_db_01.test_table (id) VALUES (1111);
Query OK, 1 row affected (0.02 sec)

# On Slave
mysql> SELECT * FROM test_db_01.test_table;
Empty set (0.00 sec)

cross-database갱신도 복제를 하기 위해서는 replicate-wild-do-table를 이용해야한다.

# On slave
mysql> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.18.0.2
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 6408
               Relay_Log_File: mysql-relay-bin.000017
                Relay_Log_Pos: 283
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table: test_db_01.%

# On master
mysql> USE mysql;
Database changed
mysql> INSERT INTO test_db_01.test_table (id) VALUES (2222);
Query OK, 1 row affected (0.02 sec)

# On slave
mysql> SELECT * FROM test_db_01.test_table;
+------+
| id   |
+------+
| 2222 |
+------+
1 row in set (0.00 sec)

# Refer
https://dev.mysql.com/doc/refman/5.6/en/replication-options-replica.html

2020년 9월 25일 금요일

rpl_semi_sync_master_enabled에 대하여

Semi-sync replication에서 사용되는 rpl_semi_sync_master_enabled 시스템 변수를 변경하면 MySQL이 다운되는 버그를 발견했다.

해당 현상이 일어난 버전은 MySQL 5.7.14로 마스터와 슬레이브 모두 동일하다.

서버 상황
Semi-sync replication이 활성화 되어 있었으며 문제 없이 동기가 이루어지고 있었다.
시스템 변수를 변경하기 전의 Semi-sync replication관련 설정은 다음과 같았다.

+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 500 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
| rpl_stop_slave_timeout | 31536000 |
+-------------------------------------------+------------+

시나리오

admin@localhost:(none) 18:35:33>SET GLOBAL rpl_semi_sync_master_enabled = 0;
ERROR 2013 (HY000): Lost connection to MySQL server during query
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql
ERROR: 
Can't connect to the server

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql

rpl_semi_sync_master_enabled를 OFF로 변경하니 갑자기 서버가 다운되었다.
해당 변수는 다이나믹으로 변경 가능하다고 공식문서에 나와있다.
https://dev.mysql.com/doc/refman/5.7/en/replication-options-master.html#sysvar_rpl_semi_sync_master_enabled

에러 로그

[Note] Semi-sync replication switched OFF.
[Note] Semi-sync replication disabled on the master.
[Note] Stopping ack receiver thread
mysqld got signal 11 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
Attempting to collect some information that could help diagnose the problem.
As this is a crash and something is definitely wrong, the information
collection process might fail.
key_buffer_size=33554432
read_buffer_size=2097152
max_used_connections=3455
max_threads=12000
thread_count=2493
connection_count=2493
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 123072893 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.
Thread pointer: 0x0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 0 thread_stack 0x40000
/app/bin/mysqld(my_print_stacktrace+0x35)[0xf27295]
/app/bin/mysqld(handle_fatal_signal+0x4a4)[0x7b90d4]
/lib64/libpthread.so.0(+0xf5d0)[0x7f8fda9cb5d0]
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
mysqld_safe Number of processes running now: 0
mysqld_safe mysqld restarted

원인 조사
결론부터 말하자면, 버그인 것 같다.
검색을 해보니 비슷한 현상의 글들을 몇가지 찾을 수 있었다.
https://bugs.mysql.com/bug.php?id=65711
https://jira.percona.com/browse/PS-7113
https://jira.percona.com/browse/PS-3311

2020년 9월 20일 일요일

Sort 처리에 대하여

쿼리 결과를 정렬하기 위해서는 ORDER BY 구문을 사용한다.

mysql> SELECT * FROM article ORDER BY created_at DESC LIMIT 10;

created_at 컬럼이 인덱스로 존재하는 경우는 추가적인 처리가 필요하지 않다.
인덱스는 정렬된 데이터가 격납되어 있기 때문에 선두부터 차례대로 읽기만 하면 되기 때문이다.

MySQL에서는 인덱스가 아닌 컬럼의 정렬을 몇가지 최적화 하고 있다.
어떠한 최적화를 하고 있는 지 알아보기로 하자.

Sort 처리 동작
MySQL은 ORDER BY 구문의 조건이 인덱스로 해결될 수 있는 지 확인한다.
인덱스로 해결 되었는 지 확인하는 방법은 EXPLAIN 으로 가능하다.
Extra열에 Using filesort가 기술되어 있지 않으면 인덱스로 해결된 것이고, 기술 되어 있는 경우는 후술 정렬 처리가 실행되고 있는 것이다.

해당 정렬 처리는 2종류가 있다. 
  • 종래의 방식: 정렬하는 컬럼과 row ID를 이용해 quick sort처리를 한 후, 정렬된 순서를 유지하면서 row ID로 부터 해당 row를 읽어 들인다.
  • 새로운 방식: MySQL 5.6에서 추가되었다. row ID가 아니라 SELECT로 지정한 컬럼들을 소트버퍼에 채우면서 sort처리를 한다. 정렬이 완료되면 순서대로 읽기만 하면 된다. 필요한 컬럼을 row ID를 이용해서 습득하지 않아도 소트버퍼에 해당 컬럼들이 존재하기 때문에 직접 읽어들일 수 있기 때문이다.
선택방법
어떤 방식을 옵티마이저가 선택할지는 max_length_for_sort_data 시스템 변수에 따라 바뀐다.
소트버퍼에 채우는 소트 키 및 SELECT로 지정된 컬럼의 합계 사이즈가 이 변수보다 작으면 새로운 방식을 채용한다.
* MySQL 8.0.20 에서 해당 변수가 deprecated 되었고, 항상 새로운 방식을 사용하고 있는 거 같다.

확인방법
어떤 방식이 선택 되었는 지 확인하기 위해서는 optimizer_trace의 file_summary에서 알 수 있다.
- 종래의 방식: sort_mode키의 값이 <sort_key, rowid>
"filesort_summary": {
    "rows": 16777217,
    "examined_rows": 16777217,
    "number_of_tmp_files": 11268,
    "sort_buffer_size": 32760,
    "sort_mode": "<sort_key, rowid>"
}

- 새로운 방식: sort_mode키의 값이 <sort_key, additional_fields>
"filesort_summary": {
    "rows": 16777217,
    "examined_rows": 16777217,
    "number_of_tmp_files": 16385,
    "sort_buffer_size": 32768,
    "sort_mode": "<sort_key, additional_fields>"
}

# Refer

결혼이민비자 신청방법(F-6-1 국민의 배우자)

 제가 일본인 여자친구와 결혼 후, 한국에 귀국하기 위해 신청한 결혼이민비자에 대하여 작성해보도록 하겠습니다. 필자는 일본에서 근무하고 있었으며, 한국에서의 소득은 없었습니다. 결혼이민비자를 신청한 날짜는 2021-04-21 이며, 사증이 발급된 날짜...