반응형

Mysql은 데이터형이 TEXT인 경우 인덱스를 지원하지 않는다.

고객의 요구사항은 테이블의 컬럼을 선언할 때 데이형을 TEXT 정도가 아니면 받기 어렵다. 결국 문자열 검색을 요구하고.. like 검색이 시작되고..

데이터가 늘어나면서 한글 문자열 검색은 like로 슬슬 성능이 떨어지니 다른 대안을 검토 중이다.

 

1.사전요구사항

1) like 검색보다 빨라야 한다.

2). like 검색만큼 정확해야 한다.

 

2. 구글링

1. 기존 mysql 에서 지원하는 FullText 인덱스 사용 (mysql 5.6 이상만 지원)

   FULLTEXT 인덱스, n-gram 파서 인덱스

 

2. 검색엔진도입

   스핑크스, 엘라스틱서치,루씬

 

 

3. 작업시작

1. Mysql 내 지원인덱스 적용

 

#인덱스 적용전

보통 와일드카드 검색을 많이 한다.

seelct * from TB_CM_ADI_xxx

where CONTENTS like '%서비스%';

--> 수행시간 0.5초

--> 결과값 3119건

#Plan

1 SIMPLE TB_CS_xxx TB_CM_ADI_xxx ALL 105344 11.11 Using where

 

# FULLTEXT 인덱스적용

#구분자(Stopword) 기법
전문의 내용을 공백이나 탭(띄어쓰기) 또는 마침표와 같은 문장 기호, 그리고 사용자가 정의한 문자열을 구분자로 등록합니다.
구분자 기법은 이처럼 등록된 구분자를 이용해 키워드를 분석해 내고, 결과 단어를 인덱스로 생성해 두고 검색에 이용하는 방법을 말합니다.
일반적으로 공백이나 쉼표 또는 한국어의 조사 등을 구분자로 많이 사용합니다. MySQL의 내장 전문 검색(FullText search) 엔진은 구분자 방식만으로 인덱싱할 수 있습니다.
구분자 기법은 문서의 본문으로부터 키워드를 추출해 내는 작업이 추가로 필요할 뿐, 내부적으로는 B-Tree 인덱스를 그대로 사용합니다.
전문 검색 인덱스의 많은 부분은 B-Tree의 특성을 따르지만 전문 검색 엔진을 통해 조회되는 레코드는 검색어나 본문 내용으로 정렬되어 조회되지는 않습니다.
전문 검색에서 결과의 정렬을 일치율(Match percent)이 높은 순으로 출력되는 것이 일반적입니다.
구분자 기법으로 전문 검색을 사용할 때는 문장 기호뿐 아니라 특정 단어를 일부러 구분자로 등록할 수도 있습니다.
예를 들어 MySQL 매뉴얼을 페이지 단위로 잘라서 테이블에 저장하고 전문 검색을 구현한다고 해봅시다.
이 경우 테이블의 모든 레코드에는 "MySQL"이라는 단어가 포함돼 있을 것입니다. 이 경우 "MySQL"이라는 단어로 검색하면 테이블의 모든 레코드가 일치하므로 검색의 효과가 없어집니다.
이럴 때는 "MySQL"이라는 단어를 구분자에 등록하고 전문 검색 인덱스에 포함하지 않게 해주는 것이 좋습니다.
많은 인터넷 사이트에서 "Stopword"를 "불용어"로 해석하고 있지만, 이보다는 "구분자"라는 표현이 더 적절한 해석이라고 볼 수 있습니다.
이 기법의 알고리즘에서 "Stopword"는 "검색에 사용할 수 없다"보다는 "검색어를 구분해주는 기준(문장 기호나 특정 문자열)이다"의 의미가 더 강하기 때문입니다.

// TEXT 컬럼 중에 잴 데이터 많은 테이블을 찾는다.
select * from information_schema.COLUMNS
where TABLE_SCHEMA = 'PRIME'
and COLUMN_TYPE = 'TEXT';

//인덱스 생성 전에 mysql parameter 설정값을 확인한다.
//문자열 검색 variable 확인
//MyIsam 은 아래값 수정
mysql> show global variables like 'ft_min%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| ft_min_word_len | 4     |
+-----------------+-------+
1 row in set (0.00 sec)

//Innodb는 이거 수정한다.
mysql> show global variables like 'innodb_ft_min%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_ft_min_token_size | 3     |
+--------------------------+-------+
1 row in set (0.00 sec)

//2글자 검색이다. 다 2로 수정하고 DB를 재시작한다.
vi /etc/my.cnf
---------------------------------------------
ft_min_word_len =2
innodb_ft_min_token_size = 2

//FullText 인덱스 넣어본다.
alter table TB_CM_ADI_SVC
add FULLTEXT index IDX_CM_ADI_SVC_02 (CONTENTS);

 

select * from TB_CM_ADI_xxx
where MATCH(CONTENTS) AGAINST ('서비스');
1 SIMPLE TB_CS_xxx fulltext IDX_CM_ADI_xxx_01 IDX_TB_CS_xxx_01 0 const 1 100 Using where; Ft_hints: sorted

인덱스 타는 것은 확인했지만 와일드카드 검색이 안된다..

 

select * from TB_CS_xxx
where MATCH(CONTENTS) AGAINST ('*서비스*' in boolean mode)

#order by xxx_SEQ;

-->수행시간 30초

-->결과값 2775건

위처럼 와일드 카드 검색을 할 수 있지만 결과값은 like검색과 차이가 있다.

일단 순서정렬이 서비스와 가장가까운 값부터 정렬하도록 해서 만약 seq가 있다면 order by를 따로 써야할 거 같고..

결과값도 2775건이다. like검색과 비교해보니

예를 들어 _서비스 처럼 서비스 문자열 앞에 특수문자가 오면 검색이 안되었다.

그리고 가장 중요한건 성능이 별로다 like가 더 빠르다. 굳이 쓸 이유 없다.

 

# N-gram 파서

N-그램(N-Gram) 기법
하지만 각 국가의 언어는 띄어쓰기가 전혀 없다거나 문장 기호가 전혀 다른 경우가 허다합니다.
이런 다양한 언어에 대해 하나의 규칙을 적용해 키워드를 추출해내기란 쉽지 않습니다. 또한 구분자 방식은 추출된 키워드의 일부(키워드의 뒷부분)만 검색하는 것은 불가능하다는 단점도 있습니다.
이러한 부분을 보완하기 위해 지정된 규칙이 없는 전문도 분석 및 검색을 가능하게 하는 방법이 N-그램이라는 방식입니다.

N-그램이란 본문을 무조건적으로 몇 글자씩 잘라서 인덱싱하는 방법입니다. 구분자에 의한 방법보다는 인덱싱 알고리즘이 복잡하고, 만들어진 인덱스의 크기도 상당히 큰 편입니다.
트리톤(Tritonn)이나 스핑크스(Sphinx)에서는 다른 인덱싱 방법도 제공하지만, 이 알고리즘이 주로 사용됩니다.
N-그램에서 n은 인덱싱할 키워드의 최소 글자(또는 바이트) 수를 의미하는데, 일반적으로는 2글자 단위로 키워드를 쪼개서 인덱싱하는 2-Gram(또는 Bi-Gram이라고도 한다) 방식이 많이 사용됩니다.
2-Gram 인덱싱 기법은 2글자 단위의 최소 키워드에 대한 키를 관리하는 프론트엔드(Front-end) 인덱스와 2글자 이상의 키워드 묶음(n-SubSequence Window)를 관리하는 백엔드(Back-end) 인덱스 2개로 구성됩니다.
인덱스의 생성 과정은 다음과 같이 2가지 단계로 나눠서 처리됩니다.
첫 번째 단계로, 문서의 본문을 2글자보다 큰 크기로 블록을 구분해서 백엔드 인덱스(3)을 생성
두 번째 단계로, 백엔드 인덱스의 키워드들을 2글자씩 잘라서 프론트엔드 인덱스(6)을 생성

n=1: 'a', 'b', 'c', 'd'
n=2: 'ab', 'bc', 'cd'
n=3: 'abc', 'bcd'
n=4: 'abcd'
그리고, 기본적으로 InnoDB에서 제공해주는 ngram의 최소 토큰 사이즈(ngram_token_size)는 2이고, 위에서 “n=2” 부터 토큰을 만들게 됩니다.
당연한 이야기겠지만, n-수치가 낮을수록 토큰 수가 많아질 것이기에,
모든 검색어들이 3글자부터 시작된다면 이 수치를 3으로 상향 조정하는 것도 인덱싱 관리 및 사이즈 안정성에 도움이 되겠습니다.

 

//인덱스 적용
ALTER TABLE TB_CM_ADI_xxx ADD FULLTEXT INDEX IDX_CM_ADI_xxx_01(CONTENTS) WITH PARSER ngram;

//기본이 2다 굳이 수정할 필요없다.
mysql> show global variables like 'ngram_token_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| ngram_token_size | 2     |
+------------------+-------+
1 row in set (0.01 sec)

#테스트

select * from TB_CM_ADI_xxx
where MATCH(CONTENTS) AGAINST ('+서비스+' in boolean mode)

-->수행시간 0.4초

-->결과값 3119건

like %서비스% 성능비슷하고 (와일드카드 검색) 결과값도 일치한다.

대용량테이블로 검색테스트는 해보지 않았지만 이정도면 like검색을 대체해도 될 거 같다.

 

select * from TB_CM_ADI_xxx
where MATCH(CONTENTS) AGAINST ('서비스' in natural language mode)

-->수행시간 0.4초

--> 결과값 8159건
--> 자연어로 와일드카드 검색시 ngram default 값이 2자리라서 서비스 를 검색했지만 '서비' ,'비스'로도 검색되서

3자리지만 각각파싱된 2자리 이상의 단어가 전부 조회되는 것을 확인했다.

정확한 값을 원한다면 사용하지 말아야할 거 같다.

 

to be continue..

반응형
블로그 이미지

dung beetle

취미는 데이터 수집 직업은 MYSQL과 함께 일하는 DBA의 소소한 일상 이야기

,
반응형

소스코드 가독성을 위해 스킨을 찾던중에 syntax highlight라는 것을 알게되었다.

수많은 구글링을 해서 ...

스킨편집기능을 이용해서 html 편집하고 head에 넣고 body에 넣고 별짓 다해도 적용이 안되었다.

답은 여기에 있었다..

https://wonderbout.tistory.com/54

 

highlight.js 코드 하이라이트 티스토리 플러그인 적용

지금까지는 티스토리에서 코드 하이라이트 구문 강조를 사용하려면 스킨에 직접 플러그인을 적용했어야 했지만 새 에디터가 출시되면서 티스토리 플러그인으로 적용할 수 있게 되었습니다. 단, highlight.js만 해..

wonderbout.tistory.com

언제부턴지는 모르지만 기본적으로 플러그인을 제공하게 되었고 이전에 수동으로 넣어서 썼던것은

블로그 타입에 따라서 적용이 안되는 거 같다.

 

관리자 > 플러그인 > highlight 검색 > 설치

기본으로 설치하면 깜장화면을 볼 수 없다.

바로 한단계 아래 걸로 설치

아.. 됐다.

생각보다 힘드네..휴;

 

 

 

<!DOCTYPE html> 
<title>Title</title> 
<style>body {width: 500px;}</style> 
<script type="application/javascript"> 
function $init() {return true;} </script> 
<body> <p checked class="title" id='title'>Title</p> 
<!-- here goes the rest of the page --> 
</body>
반응형
블로그 이미지

dung beetle

취미는 데이터 수집 직업은 MYSQL과 함께 일하는 DBA의 소소한 일상 이야기

,

xtrabackup 장애사례

RDB/mariadb 2019. 11. 26. 16:15
반응형

1) xtrabackup 장애

- 사업팀의 긴급요청으로 테스트기를 구축할 여유없이 바로 상용기에 임시테이블 생성 및 대용량 FILE을 insert 할 수 밖에 없는 상황이 생김

 

xtrabackup은 일단위로 풀백업하는 상황이었고, 여기에 대용량 파일을 insert 하다가

xtrabackup과 충돌하여 행이 걸렸다.

 

추후에 테스트기에서 데이터 insert 성공후 확인한 정보는 해당 파일사이즈는 약 100G, insert시 인덱스까지 생성하다보니 실제 tablespace의 파일사이즈는 150G정도임 수행시간은 약 16시간정도였다.

 

2) Lock관련 로그

MariaDB [(none)]> SELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;
+-----------+-------------------------+---------------+---------------------+--------------+---------------------+
| THREAD_ID | LOCK_MODE               | LOCK_DURATION | LOCK_TYPE           | TABLE_SCHEMA | TABLE_NAME          |
+-----------+-------------------------+---------------+---------------------+--------------+---------------------+
|  20362137 | MDL_INTENTION_EXCLUSIVE | NULL          | Global read lock    |              |                     |
|  20362137 | MDL_SHARED_READ         | NULL          | Table metadata lock | MDLDB        | TB_COM_xxx_xxxx       |
|  20362137 | MDL_SHARED_READ         | NULL          | Table metadata lock | MDLDB        | TB_STA_MC_xxx_xxxx |
|  20310373 | MDL_SHARED_WRITE        | NULL          | Table metadata lock | MDLDB        | TMP_LOAD_xxx_xxxx   |
|  20362137 | MDL_SHARED_READ         | NULL          | Table metadata lock | MDLDB        | TB_MDL_xxx_xxxx     |
|  20362137 | MDL_SHARED_WRITE        | NULL          | Table metadata lock | MDLDB        | TB_STA_SVC_xxx_xxxx  |
+-----------+-------------------------+---------------+---------------------+--------------+---------------------+

 

select * from information_schema.innodb_trx;

MariaDB [(none)]> SELECT * FROM INFORMATION_SCHEMA.METADATA_LOCK_INFO;
+-----------+------------------+---------------+---------------------+--------------+-------------------+
| THREAD_ID | LOCK_MODE        | LOCK_DURATION | LOCK_TYPE           | TABLE_SCHEMA | TABLE_NAME        |
+-----------+------------------+---------------+---------------------+--------------+-------------------+
|  20310373 | MDL_SHARED_WRITE | NULL          | Table metadata lock | MDLDB        | TMP_LOAD_xxx_xxxx |
+-----------+------------------+---------------+---------------------+--------------+-------------------+
1 row in set (0.03 sec)

 

MariaDB [(none)]> select * from information_schema.innodb_trx;

----------+--------------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+------------------+----------------------------+
| trx_id   | trx_state    | trx_started         | trx_requested_lock_id | trx_wait_started | trx_weight | trx_mysql_thread_id | trx_query | trx_operation_state | trx_tables_in_use | trx_tables_locked | trx_lock_structs | trx_lock_memory_bytes | trx_rows_locked | trx_rows_modified | trx_concurrency_tickets | trx_isolation_level | trx_unique_checks | trx_foreign_key_checks | trx_last_foreign_key_error | trx_adaptive_hash_latched | trx_is_read_only | trx_autocommit_non_locking |
+----------+--------------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+------------------+----------------------------+
| 70509851 | ROLLING BACK | 2019-11-09 07:06:36 | NULL                  | NULL             |   52876634 |            20310373 | NULL      | rollback            |                 0 |                 1 |                1 |                  1136 |               0 |          52876633 |                       0 | READ COMMITTED      |                 1 |                      1 | NULL                       |                         0 |                0 |                          0 |
+----------+--------------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+------------------+----------------------------+
1 row in set (0.07 sec)

 

3) 장애원인파악

xtrabackup과 충돌로 행이걸려 제대로 insert가 안되고 innodb에서 자체 롤백중이었다.

 

show processlist; 에서 확인한 결과는 killed 상태였고 여기서 kill 명령어는 제대로 수행되지 않았다.

 

xtrabackup 로그를 확인해보니 apply_log 데이터를 쓰면서 백업물리파일의 sequence를 저장하다가 임시테이블의 트랜젝션이 끝나지 않아 무한대기에 루프를 돌고 있는 상황이었다.

 

xtrabackup apply_log)

InnoDB: Doing recovery: scanned up to log sequence number 7058198598656 (99%)
InnoDB: Doing recovery: scanned up to log sequence number 7058198892824 (100%)
InnoDB: 1 transaction(s) which must be rolled back or cleaned up in total 278336723 row operations to undo
InnoDB: Trx id counter is 70558720
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Progress in percent: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
InnoDB: Apply batch completed
InnoDB: xtrabackup: Last MySQL binlog file position 7587824, file name ./mysql-bin.000001
InnoDB: Starting in background the rollback of uncommitted transactions
InnoDB: Creating shared tablespace for temporary tables
InnoDB: Rolling back trx with id 70509851, 278336723 rows to undo
InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...

InnoDB: Progress in percents: 1InnoDB: File './ibtmp1' size is now 12 MB.
InnoDB: 96 redo rollback segment(s) found. 1 redo rollback segment(s) are active.
InnoDB: 32 non-redo rollback segment(s) are active.
InnoDB: Waiting for purge to start
InnoDB: page_cleaner: 1000ms intended loop took 31280119ms. The settings might not be optimal. (flushed=0 and evicted=0, during the time.)
InnoDB: 5.7.13 started; log sequence number 7058198892824
InnoDB: xtrabackup: Last MySQL binlog file position 7587824, file name ./mysql-bin.000001

xtrabackup: starting shutdown with innodb_fast_shutdown = 1
InnoDB: FTS optimize thread exiting.
InnoDB: Starting shutdown...
InnoDB: Waiting for 1 active transactions to finish
InnoDB: Waiting for 1 active transactions to finish
InnoDB: Waiting for 1 active transactions to finish
InnoDB: Waiting for 1 active transactions to finish
InnoDB: Waiting for 1 active transactions to finish
InnoDB: Waiting for 1 active transactions to finish
InnoDB: Waiting for 1 active transactions to finish

....

 

ps -ef에서 kill -9를 하고 싶었으나.. 구글링 결과 끔찍한 결과를 초래할 수 있다는 경고가 많았다. clean up까지는 최장 72시간이 걸릴수도 있다고 하였고, 시스템이 다운되는 것을 염려하여 일단 innodb 의 자체 롤백을 믿어보기로하고 기다렸다.

 

#주의점 : session을 Kill 하게 되면 SMON에 의해서 Clean-up되는 시간이 필요함

SQL에서 Session Kill 후에 OS에서 kill -9 명령어를 또 다시 날리게 되면 SMON을 Kill하게 되므로 DB가 Shutdown 됨

 

#참조사이트

https://otsteam.tistory.com/58

 

4) 장애해결

기다리고.. 기다렸다. 시스템 성능저하는 어쩔 수 없었고..다행이도 실시간 데이터 merge에는 문제없었다. 

50시간 정도 걸려 rollback이 끝났다. 기다리는 게 맞긴 맞다. ㅠ 살았다...

문제가 된 임시테이블은 Drop하였고, xtrabackup은 apply-log 프로세스는 innodb의 롤백이 완료되었으나 여전히 끝나지않고 행 걸려있어 Kill 시켰다.

 

 

MariaDB [(none)]> show processlist;
+----------+-------------+-----------------------+-------+---------+------+--------------------------+------------------+----------+
| Id       | User        | Host                  | db    | Command | Time | State                    | Info             | Progress |
+----------+-------------+-----------------------+-------+---------+------+--------------------------+------------------+----------+
|        3 | system user |                       | NULL  | Daemon  | NULL | InnoDB purge worker      | NULL             |    0.000 |
|        1 | system user |                       | NULL  | Daemon  | NULL | InnoDB purge coordinator | NULL             |    0.000 |
|        4 | system user |                       | NULL  | Daemon  | NULL | InnoDB purge worker      | NULL             |    0.000 |
|        2 | system user |                       | NULL  | Daemon  | NULL | InnoDB purge worker      | NULL             |    0.000 |
|        5 | system user |                       | NULL  | Daemon  | NULL | InnoDB shutdown handler  | NULL             |    0.000 |
| 18731450 | mdlbat      | 172.31.8.77:36718     | MDLDB | Sleep   |   11 |                          | NULL             |    0.000 |
| 20426479 | mdlbat      | 172.31.8.77:44052     | MDLDB | Sleep   |   84 |                          | NULL             |    0.000 |
20 rows in set (0.00 sec)

.....

 

+----------+-------------+-----------------------+-------+---------+------+--------------------------+------------------+----------+
20 rows in set (0.00 sec)

 

 

--> 장애복구완료

대용량 처리는 웬만하면 상용기에서 하지말자...

 

 

 

반응형
블로그 이미지

dung beetle

취미는 데이터 수집 직업은 MYSQL과 함께 일하는 DBA의 소소한 일상 이야기

,
반응형

#mysql varchar로 선언하면 한글은 몇 글자까지 넣을 수 있을까?

 

개발쪽에서 한글입력관련 이슈를 문의해서

Varchar(50) 으로 선언한 컬럼에 데이터를 넣었을 때 몇 글자에서 too long error가 나서 안 들어갈까 확인해보았다.

 

1.구글링으로 찾아본 정의들

 

[ euc-kr ]  
ascii 코드 + 한글  
영문/숫자/기호는 1바이트. 한글과 한자는 2바이트  
euc-kr 또는 ksc5601  
웹페이지 작성에 사용가능  
특수한 외국어 문자나 일본식/중국식 한자는 표현불가  
   
[ unicode ]  
모든 글자를 2바이트로 표현  
전세계 모든 글자들을 한꺼번에 표현가능  
웹페이지 작성에 사용불가  
   
[ utf-8 ]  
영문/숫자/기호는 1바이트로, 한글과 한자 등은 3바이트로 표현  
전세계 모든 글자들을 한꺼번에 표현가능  
웹페이지 작성에 사용가능

 
•table을 정의할때 varchar(60)처럼 (n)으로 열 타입의 크기를 정하는데, mysql 4.1 이전에는 n이 바이트였다면, 4.1 이후부터는 문자 수다. 
•즉 varcher(60)이면 아스키 문자든 한글이든 60자만큼 입력가능하다는 의미이다. 
charater_length(char_length)는 문자수를 계산하는 연산이지만, octet_length는 바이트 수를 계산하는 연산 이므로 인코딩방식을 주의하여 사용해야합니다.

 

2.결론

 

mysql은 varchar로 선언하면 정말 한글자씩 인식해서 들어간다.

다만 이종 DB로 마이그레이션시 이슈가 될 수 있을 거 같다.

 

실제로 내가 쓴 글자수 = varchar(50) 안에 들어가는지 아닌지는 아래 함수로 확인해보면 된다.

 

length function으로는 mysql에서 정확하게 확인이 안되고,

char_length 함수로 확인하면 된다.

 

ex)
select CHAR_LENGTH('현재 사용중인 요금제와 선택한 요금제가 같음, 선택한 요금제와 현재 요금제의 종류가 다름') from dual;
/* varchar(50)으로 선언한 컬럼이라면 값이 50넘으면  too long error 난다. */

select CHAR_LENGTH('현재 사용중인 요금제와 선택한 요금제가 같음, 선택한 요금제와 현재 요금제의 종류가 다름 하') from dual; 
/*  에러남 ^^ */

 

반응형

'RDB > mysql' 카테고리의 다른 글

[장애] innodb Dead Lock 문제  (0) 2020.03.03
mysql TEXT like 검색 개선 포인트 찾기 1  (0) 2020.02.07
mysql shell script 2  (0) 2019.09.09
Mysql shell script 1  (0) 2019.09.09
Xtrabackup 2.49 설치  (0) 2019.09.06
블로그 이미지

dung beetle

취미는 데이터 수집 직업은 MYSQL과 함께 일하는 DBA의 소소한 일상 이야기

,
반응형

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 116393
Server version: 10.2.15-MariaDB-log MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show processlist;
+--------+-------------+-----------------------+-------+---------+------+--------------------------+------------------+----------+
| Id     | User        | Host                  | db    | Command | Time | State                    | Info             | Progress |
+--------+-------------+-----------------------+-------+---------+------+--------------------------+------------------+----------+
|      1 | system user |                       | NULL  | Daemon  | NULL | InnoDB purge coordinator | NULL             |    0.000 |
|      2 | system user |                       | NULL  | Daemon  | NULL | InnoDB purge worker      | NULL             |    0.000 |
|      4 | system user |                       | NULL  | Daemon  | NULL | InnoDB purge worker      | NULL             |    0.000 |
|      3 | system user |                       | NULL  | Daemon  | NULL | InnoDB purge worker      | NULL             |    0.000 |
|      5 | system user |                       | NULL  | Daemon  | NULL | InnoDB shutdown handler  | NULL             |    0.000 |

| 116393 | root        | localhost             | NULL  | Query   |    0 | init                     | show processlist |    0.000 |
+--------+-------------+-----------------------+-------+---------+------+--------------------------+------------------+----------+
MariaDB [(none)]>

 

mariadb 10.0.14에서 10.2.15로 업그레이드 후 처음 보는 프로세스가 5개가 떠 있다.

저게 뭐하는 걸까 찾아보았다.

1.InnoDB purge coordinator
2.InnoDB purge worker
3.InnoDB shutdown handler

 

1. InnoDB purge coordinator / worker

- InnoDB purge coordinator 및 worker는 InnoDB에서 purge 작업을 진행하기 위해 필요한 프로세스 입니다.
InnoDB의 purge 기능이란 데이터의 변경이 발생하였을 때, 다른 트랜잭션의 읽기 일관성(MVCC)을 위해 변경 전의 데이터를 롤백 세그먼트에 기록해두게 되는데, 이 데이터가 더 이상 필요하지 않게 될 경우 해당 세그먼트를 재사용하기 위해 청소하는 것을 의미합니다.
Purge를 수행하게 되면 쿼리의 성능 저하를 방지할 수 있고, 변경 및 삭제된 자료들이 차지하고 있는 디스크 공간을 확보할 수 있게 됩니다.
InnoDB purge worker 프로세스는 그런 purge 작업을 실제로 수행하는 프로세스이며, InnoDB purge coordinator는 언제 어떤 worker가 purge 작업을 수행할지 관리하는 프로세스입니다.

InnoDB purge coordinator -> rollback segment 재사용(purge) 스케줄러

InnoDB purge worker -> rollback segment 재사용(purge) 수행 프로세스

 

2. InnoDB shutdown handler

InnoDB shutdown handler 프로세스는 InnoDB가 종료 시 안정성을 높이기 위해서 추가된 프로세스입니다.
해당 프로세스는 InnoDB 종료 전 buffer flush와 같이 반드시 수행되어야 하는 일들을 모두 수행 후 shutdown이 될 수 있도록 해줍니다

InnoDB shutdown handler -> InnoDB 종료시 buffer flush 프로세스(데이터 안정성 up)

 

참조사이트

: https://support.s-core.co.kr/hc/ko/articles/360000537081-MariaDB-10-2-%EB%B6%80%ED%84%B0-%EC%83%9D%EA%B8%B4-%EC%83%88%EB%A1%9C%EC%9A%B4-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%93%A4%EC%9D%80-%EB%AD%94%EA%B0%80%EC%9A%94-

반응형
블로그 이미지

dung beetle

취미는 데이터 수집 직업은 MYSQL과 함께 일하는 DBA의 소소한 일상 이야기

,
반응형

1. Mysql 실행계획(explain) 사용

- SQL문 앞에 explain을 붙여주면 된다

 

2. type 컬럼

1) ALL -- 테이블 풀스캔

--> 풀스캔이 무조건 나쁜 것은 아니다 where 조건절을 걸어도 옵티마이저가 검색row수가 적을 때는 풀스캔으로 처리할 경우도 많다.

 

2) index  -- 인덱스 스캔, extra 컬럼 using index 출력시 비용감소 확인

 

3) range -- 래인지 스캔은 제한된 형태의 인덱스 스캔이다. 레인지 스캔의 경우 인덱스의 특정부분에서 시작해서 특정 범위에 있는 값을 가지는 행을 반환한다. 전체 인덱스를 살펴봐야 할 필요는 없으므로 전체 인덱스 스캔보다 더 나은 성능을 보인다. where 절에 Between 이나 >가 있을 경우 범위 검색을 사용하게 되며, in() 이나 OR 리스트와 같이 어떤 값들의 리스트를 찾는 경우에도 인덱스를 사용할 수 있다. 이경우에도 레인지 스캔이라고 표시되지만 접근방법에는 큰자이가 있고, 성능상에도 꽤 차이가 난다.

 

4) ref -- 이방식은 어떤 값 하나에 대해 매치되는 행들을 반환해주는 인덱스 접근방식이다. 이때 같은 값을 가지는 여러 개의 행을 찾게 될 수도 있으므로 탐색과 스캔이 함께 사용되며, 고유하지 않은 값에 대한 인덱스나 고유하지 않은 프리픽스에 대한 인덱스에만 이런식으로 접근할 수 있다. 인덱스를 어떤 참조(reference) 값과 비교하기 때문에 ref라고 불리며, 참조 값은 상수여야하며, 다중-테이블 쿼리의 경우엔 이전 테이블에서 넘어온 값도 참조 값으로 사용될 수 있다.

접근 방식 ref_or_null은 ref방식의 변형으로 Mysql이 초기 탐색을 마친후 NULL 엔트리들을 찾기 위해 두 번째 탐색을 해야만 한다는 것을 의미한다.

ex) select * from ref_table where key_column ='상수' or key_column is null

 

5) eq_ref -- Mysql이 기껏해야 값 하나만을 반환해준다는 것을 알고 있을 때 이런 인덱스 탐색법이 사용되며, Mysql이 쿼리를 실행하기 위해 참조 값을 기본키 혹은 유니크 인덱스에 비교할 떄 이런 접근방법을 사용하는 것을 확인할 수 있다. Mysql에서 값을 하나라도 찾으면 더 이상 매치되는 행들ㄹ의 범위를 평가하거나 매치되는 행을 찾을 필요가 없으므로 이런 접근 방법은 아주 잘 최적화되었다고 볼 수 있다.

 

6) const, system -- 쿼리의 일부를 상수로 대체해서, 쿼리를 최적화할 수 있을 경우 Mysql에서는 이런 접근방법들을 사용하게 된다. where 절에 기본키를 이용해 검색하는 조건을 사용하는 경우 Mysql에서는 이 쿼리를 상수로 바꿔버린 뒤 조인에서 테이블을 사실상 제거해버린다.

 

7) NULL -- 이방법은 Mysql이 최적화 단계에서 쿼리를 처리할 수 있으므로 실행 단계에서 인덱스나 테이블에 접근조차하지 않았다는 것을 의미한다. 예를들어 인덱스가 되어 있는 컬럼에서 최솟값을 선택하려는 경우라면 인덱스만 찾아보면 되므로 실행단계에서 테이블에 접근할 필요가 없다.

 

3. rows 컬럼

이 컬럼은 원하는 행을 찾기 위해 얼마나 많은 행을 읽어야 할지에 대한 예측값을 의미한다. 이 숫자는 중첩루프(Nested-loop) 조인계획에서 루프 한 번당 몇 개의 레코드를 읽어야 할지에 대한 예측값이다. 다시말하면 이 값은 그저 Mysql이 테이블에서 읽어야할 거라고 생각하는 행 수를 의미하는 것만이 아니고, Mysql이 쿼리를 실행 관점에서 어떤 기준 이상으로 효율적으로 실행시킬 떄 읽어야하는 행 수의 평균을 의미한다.(기준은 조인 순서에서 앞쪽에서 나온 테이블에서 넘어온 칼럼뿐 아니라 SQL에서 주어진 상수들에 대한 것도 포함한다)

--> rows 의  전체 행을 곱해주면 얼마나 많은 행을 읽을지 조사할 수 있지만

     실제 행수를 읽는 값과 정확히 일치하지 않는다는 말

 

ex) 테이블 4개 lefe outer join 되어있는 쿼리 실행계획

전체 테이블 row 수 -- 11899, 193, 83, 37606

 = 7721 * 1 * 1 * 195 = 1505595 (예상 rows수)

 

id select_type table partition type possible_keys key key_len ref rows filtered extra
1 SIMPLE NT   ALL IDX_DV_DEVICE_COME_NOTI       7721 9.1 Using where
1 SIMPLE DM   eq_ref PRIMARY PRIMARY 62 NEW.NT.MODEL_CD 1 10 Using where
1 SIMPLE DC   eq_ref PRIMARY PRIMARY 4 NEW.NT.COLOR_SEQ 1 100  
1 SIMPLE DS   ref PRIMARY PRIMARY 66

NEW.NT.MODEL_CD,

NEW.NT.COLOR_SEQ

195 100 Using where; Using index

 

 

4. filtered 컬럼

이 컬럼은 어떤 테이블에 대한 조인 조건이나 where 절에 있는 조건 등을 만족시키는 행이 어느 정도 될지에 대한 비관적 예측을 나타낸다. 이 퍼센트 값을 rows 컬럼에 곱해주면 쿼리 계획에서 이전 테이블과 조인할 때 얼마나 많은 행과 조인하게 될지에 대해 Mysql이 예측한 값을 보여준다.

 

ex) 테이블 4개 lefe outer join 되어있는 쿼리 실행계획

7721 에 필터 9.1 -> 7721 * 9.1 * 0.01 = 702.611 

where 절에 의해 거의 1/10으로 줄었구나..옵티마이져가 풀스캔으로 처리할만 하다.

 

5. Extra 컬럼

이 컬럼은 다른 컬럼에는 적합하지 않은 나머지 정보들을 나타낸다. Mysql 매뉴얼에서는 여기에 나올 수 있는 대부분의 값들이 설명되어 있다.

 

Using index -- 이는 Mysql이 테이블에 접근하지 않도록 커버링 인덱스를 사용한다는 것을 알려준다. 실행 계획상의 Type 컬럼이 index인 것과 혼동하지 않도록 주의하자

 

Using where -- 이 값은 Mysql 서버가 스토리지 엔진에서 값을 가져온 뒤 행을 필더링한다는 것을 의미한다. 인덱스에 포함된 컬럼들이 사용된 where 조건들은 대부분 스토리지 엔진에서 인덱스를 읽을 때 체크되기 때문에 where 절을 가진 쿼리가 모두 실행계획 상에 Using where를 표시하는 것은 아니다. 때로는 Using where가 있다는 사실이 다른 인덱스를 사용하면 쿼리를 더 효율적으로 만들 수 있다는 의미가 되기도 한다.

 

Using temporary -- 이는 Mysql이 쿼리 결과를 정렬하기 위해 임시 테이블을 사용한다는 것을 의미한다.

 

Using filesort -- 이는 Mysql이 결과의 순서를 맞추기 위해 인덱스 순서로 테이블을 읽는 것이 아니라 외부 정렬을 사용해야 한다는 것을 의마한다. Mysql은 두가지 파일 정렬 알고리즘들을 가지고 있는데, 각 방식은 메모리나 디스크에서 수행될 수 있으며 Explain으로는 어떤 파일 정렬이 사용될지나 정렬이 디스크에서 이루어질지 메모리에서 이루어질지 등을 알 수가 없다.

 

Range checked for each record(index map :N)

-- 이 값은 적합한 인덱스가 없으므로 각 레코드의 조인에서 각 인덱스들을 재평가한다는 것을 의미한다. N은 실행계획의 possible_keys 컬럼에 나타나 있는 인덱스들의 비트맵 값이다.

 

 

 

 

 

반응형

'쇠똥굴리기(BOOK) > Mysql 성능최적화' 카테고리의 다른 글

로컬 호스트 전용 연결  (0) 2019.09.17
운영체제 보안  (0) 2019.09.10
localhost와 127.0.0.1로 연결 및 차이점  (0) 2019.09.09
1.Mysql 아키텍처  (0) 2019.09.04
INTRO  (0) 2019.09.04
블로그 이미지

dung beetle

취미는 데이터 수집 직업은 MYSQL과 함께 일하는 DBA의 소소한 일상 이야기

,
반응형

동일한 호스트에 있는 응용 프로그램에 Mysql을 사용하면 Mysql에 네트워크를 통한 접근을 전혀 허용하지 않아도 될 확률이 높다. 외부연결을 허용할 필요를 없애면 공격자가 여러분의 Mysql 서버에 접근하는 방법의 수가 줄어든다.

 

네트워크 접근 비활성화는 관리 변경을 원격에서 하는 기능을 제한하므로, Mysql 서버에 SSH로 로그인하거나, 여러분이 직접 변경하도록 해주는 웹 기반 응용프로그램을 설치해야 한다. 일부 윈도우 시스템에서는 원격 로그인이 어려울 수도 있는데, 그런 경우 원격 접근의 대안이 있다. 해결책 한 가지는 phpMyAdmin을 설치하는 것이다. 하지만 거기에도 보안상의 문제가 있으므로 주의해야한다.

 

skip_networking 옵션은 Mysql이 어떠한 TCP 소켓에 대해서도 접속 대기를 하지 않게 하지만, 유닉스 소켓의 연결은 계속 허용할 것이다. 네트워크 지원없이 Mysql을 시작하기는 간단하다. 다음 옵션을 my.cnf 파일의 [mysqld]절에 넣는다.

 

[mysqld]

skip_networking

 

skip_networking 옵션은 불편한 부작용이 있다. 이옵션은 안전한 원격 연결과 복제에 stunnel 등의 도구를 사용하는 것을 막으며 자바 응용프로그램의 연결을 막는다.( Mysql JDBC 드라이버인 Connector/J는 TCP/IP를 통해서만 연결한다.)

다른 방법으로는 아래와 같이 Mysql을 구성하는 것이 있다.

[mysqld]

bind_address=127.0.0.1

이렇게 하면 TCP 연결이 가능해지지만 로컬 장치에서만 가능하므로 안전하며 편리하다. 잘 알려진 GNIU/리눅스 배포판 일부는 이 구성을 기본으로 포함하도록 바뀌었다.

 

* skip_networking 으로 구성된 Mysql 슬레이브 서버 구성은 흥미롭다. 이것은 마스터에 연결을 시작하므로 슬레이브의 모든 데이터가 갱신되지만 어떠한 TCP  연결도 허용되지 않으므로 원격으로 피해를 입을 수 없는 더욱 안전한 백업 복제를 할 수 있다. 하지만 장애 조치 구성에서는 그러한 슬레이브를 사용할 수 없다.

다른 클라이언트가 거기에 연결할 수 없기 때문이다.

-> 마스터 & 슬레이브 구성할 떄는 들어가면 위험한 옵션이었군

반응형

'쇠똥굴리기(BOOK) > Mysql 성능최적화' 카테고리의 다른 글

실행계획(explain) 사용  (2) 2019.09.25
운영체제 보안  (0) 2019.09.10
localhost와 127.0.0.1로 연결 및 차이점  (0) 2019.09.09
1.Mysql 아키텍처  (0) 2019.09.04
INTRO  (0) 2019.09.04
블로그 이미지

dung beetle

취미는 데이터 수집 직업은 MYSQL과 함께 일하는 DBA의 소소한 일상 이야기

,
반응형

1. 지침

- 여기서 설명하는 일반적인 지침은 운영체제 수준 보안에 관한 포괄적인 지침은 아니다. 보안에 관련해 더 심도있게 공부하려면 simson Carfinkel의 저서인 Practical Unix and Internet Security(O'Reilly 출판사)을 참고하기 바란다. 여기서는 데이터베이스 서버에 적걸한 보안을 유지하는 법에 대해 알아보자.

 

1) 권한이 주어진 계정에 Mysql을 실행하지 말라

- Root가 뚫리면 다 뚫린다. root 계정으로 mysql을 실행하지 말고 mysql과 같은 사용자 계정을 만들어 mysql을 실행해야한다.

 

2) 운영체제를 최신 버전으로 유지하라

- OS의 보안업데이트 반드시 하자

 

3) 데이터베이스 호스트에 로그인 제한하기

- Mysql 기반 응용프로그램 개발자들이 서버계정이 필요한가?

  SE와 DBA만 계정이 필요하다. 개발자들은 TCP/IP를 통해 데이터베이스에 원격으로 쿼리를 실행시킬 수만 있으면 된다.

 

4) 운영 환경 데이터베이스를 다른 것과 분리하라

- 운영기와 테스트기를 분리하라. 물리적으로 아에 별도로 구축하는 것이 좋다.

  이렇게 하면 실수를 방지하고, 보수가 용이해진다.

 

5) 서버를 감시하라.

- 보안 컨설턴트 고용

 

6) 강력한 도구를 사용하라

- 백업 복사본을 다른 서버에 저장하는 것도 중요한 보안 방법이다. DB 서버에 침입해서 공격받았다면 OS부터 다시 설치해고 데이터 복구작업을 진행해야한다.

반응형

'쇠똥굴리기(BOOK) > Mysql 성능최적화' 카테고리의 다른 글

실행계획(explain) 사용  (2) 2019.09.25
로컬 호스트 전용 연결  (0) 2019.09.17
localhost와 127.0.0.1로 연결 및 차이점  (0) 2019.09.09
1.Mysql 아키텍처  (0) 2019.09.04
INTRO  (0) 2019.09.04
블로그 이미지

dung beetle

취미는 데이터 수집 직업은 MYSQL과 함께 일하는 DBA의 소소한 일상 이야기

,