Data Base

MySQL DDL(Alter Table) 실행 시, Connection Lost 발생 대응

sincerely10 2020. 12. 6. 21:05
반응형

안녕하세요!
한 달이 지나서야 포스트를 올리게 되었습니다..

꾸준히 올리고자 하는 마음을 다 잡고 이번 포스트를 작성해보겠습니다.

이번 포스트 제목과 같이 MySQL에서 'ALTER TABLE'과 같은 특정 테이블에 대해 변형을 일으키는 DDL(Data Definiton Language)이 적용되지 않는 상황에 대해 두 가지로 접근해보겠습니다.

포스트의 방향은 이슈를 처리하는 과정으로 봐주시면 될 것 같습니다.

1. ALTER TABLE이 적용되지 않는 것을 확인

먼저 처음에 언급한 것과 같이 ALTER TABLE이 적용되지 않았습니다.

저의 경우 MySQL Workbench의 EER Diagram을 활용하여 변경한 다이어그램에 대해 적용을 하거나 마찬가지로 Workbench에서 스키마에서 수정버튼을 눌러 수정 하였습니다.

한 마디로 툴을 사용해 ALTER TABLE과 같은 쿼리문을 수행하던 것이죠.

개발이 어느정도 진행되고 나서 컬럼 수정을 하려 했으나, 컬럼이 정상적으로 수정되지 않는 이슈가 발생했습니다.

다음과 같은 에러가 발생했죠.

Operation failed: There was an error while applying the SQL script to the database.
ERROR 2013: Lost connection to MySQL server during query
SQL Statement:
ALTER TABLE ...

한 동안 SQL 이슈를 잘 대응하지 않다가 오랜만에 맞닥들여 어려움을 겪었습니다.

2. 'SHOW FULL processlist' 쿼리를 먼저 확인하기

팀장님의 가이드를 받아 소제목과 같이 SHOW FULL processlist 쿼리로 현재 SQL에서 비정상으로 처리된 프로세스가 막힌 것은 아닌지 확인해보았습니다.

SHOW FULL processlist\G;

(\G는 각 ROW별로 나눠서 볼 수 있게 해주는 역할입니다.

확인한 결과 다음과 같이 쿼리를 막고 있는 프로세스의 정체를 확인할 수 있었습니다.

Id: 2525
User: admin
Host:
db:
Command: Query
Time: 775
State: Waiting for table metadata lock

프로세스의 ID를 확인했으면 이 ID를 직접 kill 할 수 있는 MySQL 명령어로 kill 해줍니다.

kill 2525;

 

다시 한 번, SHOW FULL processlist; 로 확인 해보면 비정상적인 쿼리가 프로세스 리스트에서 사라진 것을 볼 수 있습니다.

3. TRANSACTION(트랜잭션) 확인하기

사실 여기까지는 조금만 찾아보면 확인할 수 있었습니다.
문제는 다시 발생 하였는데, processlist에서 아무런 이상 없어 보이는 상태의 프로세스만 있다는 것 입니다.

조금 이상해보인다 할지라도 수행중인 프로세스가 정확히 파악 되지 않아 무조건 kill을 할 수 없는 상태였습니다.

구글링을 아무리 해보아도 MySQL의 connection lost time을 60 -> 600으로 조절 하라는 내용이 거의 다 였습니다.

개인적으로 위 방법이 크게 영향이 없는 것으로 간주되는 이유는 현재 아주 작은 규모이기 때문에 수정이 1초 정도면 수행되는 DDL 쿼리이기 때문입니다.

 잘 파악되지 않아 RDS MySQL을 사용하는데 재기동 함으로써 해결하는 안 좋은 방법을 사용했습니다.

비슷한 키워드를 입력해서 그런지 검색의 결과가 다 비슷비슷 했고, 해결이 되지 않았습니다.

hang이라는 단어를 통해 재접근 한 결과, Transaction(트랜잭션)에 문제가 있음을 확인 하였습니다.

SELECT * FROM information_schema.INNODB_TRX\G;

바로 위의 쿼리를 통해 확인할 수 있었습니다.

제가 서버(백엔드) 코드에서 무언가 트랜잭션을 만들었고, 해당 트랜잭션이 정상적으로 종료되지 않았기 때문에 발생 또는 다른 원인에 의해 발생된 것임을 확인 하였습니다.

트랜잭션과 ALTER TABLE(즉 테이블의 형태를 변경하는 DDL을 포함합니다.)과의 관계는 다음과 같습니다.
트랜잭션은 어떠한 일련의 처리를 위한 논리적 단위 입니다.
하나의 트랜잭션이 여러 테이블을 거쳐 작성이 되는 것 입니다.(장바구니, 결제하기 등등)

문제는 이 트랜잭션이 처리되는 동안 즉, 끝나기 전에는 테이블의 변형이 없어야만 한다는 것이죠.
처리 중인데 갑자기 테이블의 구조가 바뀌는 것은 상식적으로 불가 할 것 입니다.

다시 이어서 진행을 하자면 위의 퀴리를 실행할 때, 현재 트랜잭션이 없는 경우인데 결과가 나온다면 비정상을 의심해봐야 합니다. 현재 그 트랜잭션으로 원할한 DB 환경이 아닐 확률이 높기 때입니다.

저의 경우 다음과 같은 결과가 나왔습니다.

*************************** 1. row ***************************
trx_id: 329324018275336
trx_state: RUNNING
trx_started: 2020-12-06 11:38:49
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 0
trx_mysql_thread_id: 2537
trx_query: NULL
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 0
trx_lock_structs: 0
trx_lock_memory_bytes: 1136
trx_rows_locked: 0
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
trx_is_read_only: 0
trx_autocommit_non_locking: 0
trx_schedule_weight: NULL

trx_mysql_thread_id를 확인 합니다. 이 id 값이 mysql의 프로세스 id 이기 때문입니다.
다시 SHOW FULL processlist로 확인 해보겠습니다.

*************************** 7. row ***************************
Id: 2537
User: admin
Host: 172.31.13.75:51470
db: dev-admin-gql
Command: Sleep
Time: 914
State: Info: NULL

위와 같이 정체를 몰랐던 프로세스의 id를 확인할 수 있게 되었습니다.

그리고 다시 이 프로세스 ID에 대해서 kill을 해줍니다.
저의 경우 이 과정을 통해 비로소 DDL이 정상 작동 하는 것을 보았습니다.

한 가지 말씀드리고 싶은 것은 저 Command: Sleep은 실제 명령어가 아니라는 것 입니다. idle 상태의 MySQL Connection의 상태 입니다.
이 경우도 어떠한 트랜잭션이 Sleep status라고 보시면 되겠습니다.

다시 한 번 결론을 말씀 드리자면, 먼저 현재의 상태를 파악하는 것이 중요하다는 것과 트랜잭션 처리가 깔끔하게 된 코드를 구성하는 것이 정말 중요하다는 것입니다.

더 좋은 포스트로 찾아 뵙겠습니다.

반응형

'Data Base' 카테고리의 다른 글

MySQL Total Row Count를 한 줄에 만드는 FOUND_ROWS  (4) 2020.09.06