개발 일지

mysql-connector with mariaDB 버전 호환성 이슈

북극곰은콜라 2023. 7. 26. 19:22
반응형


개요

보안 이슈로 인하여, OS 버전업을 하게되면서, DB 버전을 올리는 일이 발생했다.
기존 코드는 mysql jdbc connector를 사용하여 mariaDB에 붙고 있었고
mariaDB의 버전이 올라가는 상황이다.
버전 업 과정에서 Connection 생성을 못하는 상황이 발생했으며, 해당 이슈 해결과정을 기록으로 남긴다.

 


변경 사항

 
mariaDB version 10.1.25 11.0.2
mysql-connector-java version 8.0.21 8.0.21

 


이슈 분석

예외 발생

Caused by: java.sql.SQLException: Unknown system variable 'transaction_isolation'
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
	at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836)
	at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456)
	at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246)
transaction_isolation이란 DB의 variable을 찾을 수 없는 예외 발생
해당 예외로 인하여 connectionImpl 인스턴스 생성 불가

DB variable 확인

transaction_isolation이 아닌 tx_isolation이란 variable로 세팅되어있는 상황 확인

관련 공식 문서 확인

공식 문서에 따르면
MariaDB 11.1 이전에는 tx_isolation 값을 사용하고, 11.1 이후에는 transaction_isolation으로 사용한다.
즉 현재 mysql-connector가 비 정상적인 버전으로 인식하고 있는 상황

원인 파악

// com.mysql.cj.NativeSession 클래스

// public void loadServerVariables(Object syncMutex, String version) 메서드
...
if (!this.versionMeetsMinimum(8, 0, 3) && (!this.versionMeetsMinimum(5, 7, 20) || this.versionMeetsMinimum(8, 0, 0))) {
  queryBuf.append(", @@tx_isolation AS transaction_isolation");
} else {
  queryBuf.append(", @@transaction_isolation AS transaction_isolation");
}
...
mysql-connector:8.0.21 라이브러리의 관련 로직이다
this.versionMeetsMinimum() 메서드의 경우 파라미터보다 낮거나 같으면 true를 반환한다.
런 타임 상 MariaDB의 버전을 11.0.2로 인식을 하기에, mysql의 버전체계와 비교하면 맞지 않게 된다.
최종적으로 구현체에서 transaction_isolation으로 설정 값을 찾아와 한다고 인식
결론적으로 mysql connector 구현체를 통해 mariaDB를 사용하기에 발생한 이슈이다
참고사항: 기존 mariaDB 10.1.25 버전에서는 mariaDB의 버전 추출 값이 5.5.5(MySQL에 대응되는 버전 값)로 파싱이 되기 때문에, 문제가 없었다.

 


해결 방안 모색

2가지 해결방안이 있을 것으로 판단된다.

1. MariaDB 버전을 11.1 버전 이상으로 업그레이드

mariaDB를 11.1 버전으로 올려서 변수를 transaction_isolation으로 변수를 통일하여 이슈 해결하는 방안

2. mysql-connector 라이브러리 mariaDB-connector로 교체

현 시점 최신버전은 8.0.33 버전은 Mysql 버전 기준으로 버전 파싱 및 비교를 한다.
따라서 mysql-connector의 버전 업이 아닌 mariadb connector로 변경해야 한다.
+ jdbc 구현체 라이브러리가 변경되면서 소스의 드라이버 관련 코드를 모두 변경해야 한다.
→ mariadb-java-client:3.1.4 버전으로 교체 및 코드 변경
// org.mariadb.jdbc
// public class Connection implements java.sql.Connection

...

public int getTransactionIsolation() throws SQLException {
    String sql = "SELECT @@tx_isolation";
    if (!this.client.getContext().getVersion().isMariaDBServer() && (this.client.getContext().getVersion().getMajorVersion() >= 8 && this.client.getContext().getVersion().versionGreaterOrEqual(8, 0, 3) || this.client.getContext().getVersion().getMajorVersion() < 8 && this.client.getContext().getVersion().versionGreaterOrEqual(5, 7, 20))) {
      sql = "SELECT @@transaction_isolation";
    }

...
mariaDB에서 제공하는 jdbc를 보면
mariaDB server인지 확인 후, mysql일 경우 버전 비교를 통해 transaction_isolation을 적용하여 기동하도록 되어있다.
connector 라이브러리는 아직 11.1+버전에서 추가된 transaction_isolation에 대한 부분은 반영하지 못한 것으로 추정된다.

결론

DB와 JDBC를 맞추는 방향이, 사이드 이펙트를 최소화 할 수 있는 방안이며
추후 업데이트되는 측면에서 유리하다고 판단된다.
따라서 해당 해결 방안을 채택해서 적용하였다.

 


REFERENCE

https://jira.mariadb.org/browse/MDEV-21921

https://mariadb.com/kb/en/server-system-variables/#transaction_isolation

반응형