-
Glue에서 mySQL로 write시 encoding option주기 (feat. 한글깨짐) - 2부Data Engineering/AWS, Spark 2023. 5. 15. 22:03728x90반응형
이전에 mySQL로 dynamicFrame을 쓰는데 한글이 깨져서 url로 인코딩 옵션을 주는 방법을 찾았으나 Glue에서 아무리해도 먹지 않았던 포스팅을 쓴 적이 있다. 그래서 spark세션으로 삽입하는 방법으로 작업했고, 포스팅도 그렇게 마무리했는데 (링크) 원인이 너무 궁금해서 re:Post에 질문을 남겨뒀었다. 지나가던 친절한 분이 jdbc driver 버전 문제일 수 있다는 힌트를 주었고, 비록 그분이 달아준 링크는 관련이 없었으나 이를 키워드로 해당 문서를 뒤져보았다.
일단 Glue에서 MySQL jdbc 연결시 default로 사용하는 driver 버전은 8.0.23으로, 굉장히 특이한 위치에 명시되어있다. 찾는데 한참 걸림;; (링크된 문서의 jdbc connectionType 값에 적혀있음). Glue 3.0과 4.0 동일하다.
이제 MySQL 문서를 보면, Using Character Sets and Unicode라는 탭의 Setting the Character Encoding부분에 이전에 시도했던 것이 틀리지 않음이 나와있다.
- Connector/j 8.0.25 이전 버전까지는 Connector/j의 연결속성 characterEncoding 및 connectionCollation이 지정되지 않은 경우
character_set_server
시스템변수를 사용해 연결됨 - 그리고 characterEncoding 부분의 문서를 들어가보면
- 세션 시스템 변수인
character_set_client
와character_set_connection
을 MySQL에서 지원하는 문자집합으로 설정하도록 지원하며,collation_connection
을 문자집합의 기본 정렬로 사용하도록 한다. 이 속성 또는connectionCollation
속성이 설정되지 않은 경우:- Connector/j 8.0.25 이전 버전까지는 서버의 default 문자 집합 값을따름
- Connector/j 8.0.26 이후 버전부터는 utf8mb4를 사용위의 두 문서를 조합해보면, JDBC driver 버전이 8.0.25이전 버전에서 utf8mb4인코딩을 사용하고 싶다면
- MySQL서버 셋팅값에
character_set_server=utfmb4
를 지정해주거나, - jdbc 연결 속성으로
characterEncoding
값을 지정해주거나 - jdbc 연결 속성으로
connectionCollation
을 지정해주면 된다
는 뜻이다. 근데 문제는 1번은 서버를 reboot해야하니 어차피 나는 못하는 옵션이었고, 2, 3은 모두 시도해봤는데 Glue에서 안됐다는 거다 (설마 connection_collation이라는 값으로 넘겨줘야하나..). 아무튼 공식문서에서 하라는 대로 했는데도 안됐으니 조금은 덜 덜 후련하게 pass했다 (Glue에서 안 된 원인을 못찾았으니 후련하진 않음).
Pass한 이유는 위에서 8.0.25 이전 버전까지 라고 했으니 이후 버전은 뭔가 다른게 있겠거니해서였다. 이후 버전에 대한 설명을 보면 인증 이전, 이후로 나뉘어져 있긴 한데 결국 connectionCollection, passwordCharacterEncoding, characterEncoding 등등의 값이 서버에 설정되어져 있지 않은 경우 자동으로 utf8mb4로 연결된다는 뜻이었다. 우리 DB는 아무 값도 설정되어있지 않으므로 그냥 jdbc driver만 업데이트 하면 되는 거였다.
불행 중 다행으로 Glue는 custom driver를 지원했다. 하는 방법은 문서에 나와있지만 또 영어로 나와있으니 한국어로 번역해보자면
- mySQL 공식 사이트에서 (최신 이전 버전을 받고싶다면 여기) operationg system을 Platform Independent로 선택 후 driver 파일을 다운 받은 뒤 (zip이나 tar이나 상관없다)
- 압축 파일을 해제하면 그 안에 .jar파일이 있는데 그 파일을 s3에 올려준 후 해당 파일의 s3 uri를 copy한다.
- glue에서 write할 때
connection options
에customJdbcDriverClassName
의 값으로 해당 uri를,customJdbcDriverClassName
으로 "com.mysql.cj.jdbc.Driver"를 넘겨주면 된다.
코드는 다음과 같다.
dyf_writer = glueContext.write_dynamic_frame.from_jdbc_conf( frame = <dynamic frame>, catalog_connection = <Glue connection 이름>, connection_options = { "url": "jdbc:mysql://<mysql host url>:3306/<database>", "database": <database>, "dbtable": <table>, "customJdbcDriverS3Path": <driver의 s3 uri> "customJdbcDriverClassName": "com.mysql.cj.jdbc.Driver", } )
돌려봤는데 DB에 한글로 잘 입력된 것을 확인할 수 있었다.
하지만 중요한 것은 mySQL의 jdbc connection은 preactions를 사용할 수 없어 어차피 이 코드로 truncate table을 하고 dynamicTable을 insert하려면 pymysql이나 awswrangler로 connection을 한번 더 해야되고, DB에 connection 두 번 날리느니 그냥 spark로 처리하는게 나을 것 같아 이 방법은 안 쓰기로 했다는 것..^^... preactions 내놔... (참고로 preactions는 redshift만 지원하는 듯 하다)
728x90반응형'Data Engineering > AWS, Spark' 카테고리의 다른 글
Ubuntu EC2의 메모리 사용량 모니터링하기 (0) 2023.08.23 [Trouble shooting] Glue에서 string index out of range: 0 에러 발생할 경우 (0) 2023.08.07 RDS MySQL DB 트랜잭션 binary log 보기 (0) 2023.05.11 Glue에서 mySQL로 write시 encoding option 주기 (feat. 한글깨짐) (0) 2023.05.10 Lamda로 서로 다른 vpc에 있는 redshift에서 rds로 reverse ETL하기 (VPC peering) (0) 2023.05.09 - Connector/j 8.0.25 이전 버전까지는 Connector/j의 연결속성 characterEncoding 및 connectionCollation이 지정되지 않은 경우