Tag Archives: 데이터베이스

[JOTM+Xapool] xapool 이용 시 Null Pointer Exception 문제 해결

사용자 삽입 이미지서로 다른 데이터 소스를 하나로 묶어 트랜젝션을 이용할 수 있게 해주는 멋진 라이브러리로 JOTM이라는 것이 있습니다.

보통은 JOTM + Xapool 조합으로 사용하게 됩니다. 하지만 사실 이 둘의 라이브러리는 시대에 많이 뒤떨어지는 것이 아닐까 하는 생각이 듭니다.

둘다 업데이트가 2년이 넘게 없어왔기 때문입니다. 이쯤 되면 이 오픈소스 프로젝트들은 사실상 더이상 이어지지 않는다고 봐도 되겠죠.

그 예로 Xapool의 마지막 stable 버젼인 1.5.0에는 치명적인 문제가 한가지 있습니다. 물론 1.6.0beta 버젼에서 해결은 되었긴 하지만 beta버젼보다는 안전한 stable버젼을 이용하고픈 마음이 들기 마련이죠.

[code]java.lang.NullPointerException


at org.enhydra.jdbc.pool.GenericPool.getFromPool(GenericPool.java:200)
at org.enhydra.jdbc.pool.GenericPool.checkOut(GenericPool.java:351)
at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:194)
at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:164)
at my.jotm.test.Client.getConnection(Client.java:63)


java.sql.SQLException: SQLException in StandardPoolDataSource:getConnection exception: java.sql.SQLException: SQLException in
StandardPoolDataSource:getConnection no connection available java.lang.NullPointerException


at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:213)


at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:164)[/code]
위의 에러 어떠십니까? 마음에 들어 보이십니까? 이와 같은 Null Pointer Exception 에러를 내뿜는 에러를 만날 수 있습니다.

위의 에러는 Xapool에서 내는 에러인데요. [이곳]에 관련 패치가 등록 되어있습니다.

1290343559.patch


이 패치의 내용은 다음과 같습니다. 커넥션을 얻어올때 특정한 상황에 따라 Null을 받아오게 되면 다음의 보관된 논리적인 커넥션을 얻어오도록 넘어가는 처리만 추가되었습니다.

[code]— xapool/org/enhydra/jdbc/pool/GenericPool.java-1.13 2005-06-14 21:57:10.756790600 -0500
+++ xapool/org/enhydra/jdbc/pool/GenericPool.java 2005-06-15 13:11:09.601072300 -0500
@@ -189,6 +189,12 @@
   
       o = (GenerationObject) e.nextElement();
       life = (Long) unlocked.get(o);
+      if (life == null) {
+   // Fix for #303462; note that this fixes the problem, but Enumeration’s on Hashtable’s
+   // are by definition somewhat unpredictable; a more robust fix may be in order
+   log.debug(“GenericPool:getFromPool fix for #303462 encountered”);
+   continue;
+      }
       unlocked.remove(o);
       // In any case the object will be removed.
       // Prevents others accessing the object while we are
[/code]
실제로 해당 패치를 적용한 후에는 관련 문제점이 발견되지 않았습니다. 혹시 귀찮으신 분들을 위해 패치된 버젼을 올려둡니다.
1000564104.jar

[MySQL] Replication 환경 싱크 깨지는것 회피하기

MySQL의 리플리케이션 환경을 운영하다 보면 유난히도 싱크가 어긋나는 일이 많이 일어나는 것을 알 수 있습니다.

확실히 MySQL은 아직 엔터프라이즈 환경에서의 도입에 무리가 있는 제품이 아닐까 생각이 드는군요.

하지만 리플리케이션 기능이 추가된지 얼마 되지 않았고 저장프로시저도 생겼고 나날이 발전하는 모습을 보면 더더욱 좋아질것이라고 기대해 봅니다.

그러면 이미 MySQL을 이용한 리플리케이션 상황을 운영중이고 또 관련 오류가 많이 나는 상황이라면 어떻게 해야 할까요?

다음의 방법을 시도해볼만합니다.

MySQL의 경우 리플리케이션 환경 중 에러가 나면 그 Slave 서버는 리플리케이션이 중단됩니다.

갑자기 좀비 서버가 되어 버리는 것이죠. 에러를 확인해 봅시다.

[code][root@SLAVE ~]# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2060
Server version: 5.0.51

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.

mysql> show slave status\G
*************************** 1. row ***************************
             Slave_IO_State: Waiting for master to send event
                Master_Host: MASTER
                Master_User: replicator
                Master_Port: 3306
              Connect_Retry: 60
            Master_Log_File: mysql-bin.000005
        Read_Master_Log_Pos: 96305365
             Relay_Log_File: slave-relay-bin.000006
              Relay_Log_Pos: 73184178
      Relay_Master_Log_File: mysql-bin.000005
           Slave_IO_Running: Yes
          Slave_SQL_Running: No
            Replicate_Do_DB: THEEYE
        Replicate_Ignore_DB:
         Replicate_Do_Table:
     Replicate_Ignore_Table:
    Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
                 Last_Errno: 1062
                 Last_Error: Error ‘Duplicate entry ‘116069-10002826′ for key 1’ on query. Default database: ‘THEEYE’. Query: ‘INSERT INTO    THEEYE_INFO_LOG    ( IDX, NAME, REG_DATE    )    VALUES ( 3, “GOOD”, NOW() )’
               Skip_Counter: 0
        Exec_Master_Log_Pos: 73184876
            Relay_Log_Space: 96304951
            Until_Condition: None
             Until_Log_File:
              Until_Log_Pos: 0
         Master_SSL_Allowed: No
         Master_SSL_CA_File:
         Master_SSL_CA_Path:
            Master_SSL_Cert:
          Master_SSL_Cipher:
             Master_SSL_Key:
      Seconds_Behind_Master: NULL
1 row in set (0.00 sec)


mysql> exit[/code]

show slave status\G 명령으로 현재 슬레이브의 상태를 확인할 수 있습니다.

상태를 보니 Last_Errno 가 1062이고 Last_Error에는 어떤 에러인지 표시가 됩니다.

근데 에러를 확인해 보니 같은 똑같은 Entry가 존재한다는군요. 위의 디비 설계상 같은 키값을 가진 값이 두개가 들어갈 필요가 없다는것을 알았습니다.

그런데 저런 사소한 문제로 리플리케이션이 중단된다는것도 억울한 일이죠. 위와 같은 사소한 에러는 무시하도록 해보겠습니다.

–slave-skip-errors 라는 옵션이 있는데요. 에러코드값을 지정해 주거나 all로 모든 에러를 무시할 수 있습니다.
[code]–slave-skip-errors=[err_code1,err_code2,…|all][/code]

서버측 에러 코드는 [ 이곳 ] 에서 확인 하실 수 있습니다.

1062번 에러의 경우 사소한 문제이기 때문에 서버 설정에 추가해 보도록 하겠습니다.

저같은 경우에는 /etc/my.cnf 파일에 다음의 내용을 추가하였습니다.
[code][mysqld]

slave-skip-errors = 1062[/code]

앞으로는 위의 코드에 해당하는 에러가 발생할 경우 에러를 건너뛰고 Master의 Log Position에 강제적으로 맞춰질 것입니다.