이번에 Client support를 진행하는 중에 큰 데이터를 사용하는 것 때문에 10분 이상의 timeout 세팅을 사용해야 하는 Client issue 가 발생했다.

일단 Timeout은 Apache의 Timeout에 설정되어 있어서 해당 Config를 증가 시키면 되었는데,
문제는 Client side의 timeout 관련 이슈가 계속 발생하는 것이다.

뭐.. 우리 Google 님에게 문의 했고 결과는 아래와 같이 Timeout property를 증가시켜 주면 되었다.

ServiceFactory factory = ServiceFactory.newInstance ();
Service service = factory.createService (url, qname);
Call call = service.createCall (port, operation);
call.setProperty(org.apache.axis.client.Call.CONNECTION_TIMEOUT_PROPERTY, 1800000);
...


위의 Setting은 Axis 에서 Timeout을 설정해 주는 코드 인데..
결국은 다른 Client를 사용하는 Client에 대해서는 다른 코드를 찾아야 한다는..





'개발자세상 > 자바세상' 카테고리의 다른 글

jboss db pooling timeout  (0) 2014.03.01
ResultSet FetchSize  (0) 2014.02.25
자바 DEBUGGING  (0) 2013.11.20
Spring property  (0) 2013.10.15
human readable 한 json 출력  (0) 2013.03.22
Posted by headiron
,

근간에 Project를 진행하면서 Multi Row로 저장된 데이터를 한 Field로 처리할 방법을 Search하다 알게된 listagg 함수,
GROUP BY 와 함께 사용하면 같은 Key Field 값을 가진 ROW 데이터를 합칠 수 있다.

SELECT KEYFIELD, listagg( field_name, ',') within group (order by field_name)
FROM table
GROUP BY KEYFIELD

워낙 이런 Case가 많아서, 자주 사용하기 시작했는데,
오늘 listagg 함수를 사용한 Query에서 ORA-01489 에러가 발생..

찾아 보니... Oracle에서 문자열 Concatenate를 4000 byte 까지 밖에 지원하지 않는 것이다.
크.. 언제적 제약사항이 아직도 발목을 잡는 건지..

Googling을 해 보았더니.. StackOverflow에 관련 내용도 있고,
여러 내용을 리뷰해 보니, Query Level에서 이 문제를 해결할 방법은 아래와 같이 XML TYPE으로 변경해서 Aggregation 하는 방법 밖에는 없다.
http://stackoverflow.com/questions/14864055/listagg-function-and-ora-01489-result-of-string-concatenation-is-too-long

select tm.product_id, 
       rtrim(extract(xmlagg(xmlelement(e, tm.book_id || '(' || tm.score || '),')), 
               '/E/text()').getclobval(), ',')
  from tl_product_match tm
 where tm.book_id is not null 
 group by tm.product_id;

문제는.. XML로 변환 하고, Aggregation 한후 정규식으로 XML TAG를 제거 하고, 이를 다시 CLOB으로 변경하니, Performance가 엄청 좋지 않다는 점..

지금 Project는 Java Program 단에서 해결해 낼 수 있을 것 같긴 한데..
Oracle도 예전 코드들 때문에 이런 제약사항에 시달리는 걸 보면..
너무 앞장서서 나가는 것도 생각 만큼 좋지는 않은 듯...

'개발자세상 > Database관련' 카테고리의 다른 글

UPSERT ? INSERT ON DUPLICATE KEY UPDATE  (0) 2016.09.24
Open Cursor issue  (0) 2014.10.25
Oracle TEMP 파일 삭제  (0) 2013.09.23
오라클 DB에서 테이블마다 용량 구하기  (0) 2013.08.10
Overlap 데이터 구하기  (0) 2013.08.04
Posted by headiron
,

이번에 프로젝트로 Monitoring System을 개발해 볼까 해서 Eclipse에서는 어찌 DEBUGGING이 되는 건가 했더니.. JVM Level에서 지원되는 거였다는... -.-

몇 년 동안을 자바 개발자라고... DEBUGGING TOOL을 매번 써 왔으면서 왜 이런거에 대한 생각을 해보지 않고 살았을까..

이게 단순 개발자와 Technical Leader의 차이일까..

http://stackoverflow.com/questions/138511/what-are-java-command-line-options-to-set-to-allow-jvm-to-be-remotely-debugged

http://www.eclipsezone.com/eclipse/forums/t53459.html

http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/conninv.html



Posted by headiron
,

이번에 Project를 진행하면서.
Framework에 기본 Property를 넣고..
Project 단위로 Overwrite를 할 수 있는 방법을 찾다 보니 몇 가지 방법이 나왔다.

http://stackoverflow.com/questions/9470551/spring-property-substitution-for-test-and-production

그중에도 context:property-placeholder 에 order 속성을 주어서... property를 읽어 들이는 우선 순위를 정하면 되는데.
order 순서로 파일을 읽어서... 나중에 define 되면 overwrite되는 것을 기대했는데..
overwrite가 되질 않고 처음 읽었던 property가 등록이 된다.

이렇게도 하고 저렇게도 해보고 하다가 하루를 보내고 나니..
Project쪽 order를 낳게 설정하고... Framework에 order를 높게 설정해서..
Project쪽 property를 먼저 읽어 버리게 하면... Project에서 overwrite가 되는 거랑 다를 것이 없지 않은가...

흐.... 아직도 생각이 너무 갇혀 있어서...
쓸데 없는 이슈로 시간을 버린걸 생각하니 너무 어이가 없다.

어쨋든.. 인터넷을 뒤지고 조금 생각을 하게 되면..
해결되지 않는 이슈는 거의 없는듯..

특히나 StackOverflow는 왠만한 질문의 답이 있는 보고이다... :-)


아.. 그리고 overwrite 관련해서 자료를 찾다 보니 context:property-override 도 있는데..
이것은 bean에 설정된 property를 override 하는 기능을 제공한다.
따라서 해당 context에 설정된 bean 이름에 맞추어 property를 설정해 줘야 하지만..
어쨋든 이것도 쓸 수 있는 일이 종종 있을 듯 싶다.




Posted by headiron
,

DB Migration 중에 TEMP 파일을 많이 사용하는 쿼리를 돌리게 되서 TEMP 파일을 늘려 놨더니 , 이젠 서버 공간이 부족해서 파일들을 삭제 해야 할 일이 생겼다.

DB 내렸다 올려야 하나 생각하고 좀 귀찮았는데..
TEMP 파일은 생각 보다 손 쉽게 삭제 할 수 있었다.

SQL> ALTER DATABASE TEMPFILE '/oradata/temp02.dbf' DROP INCLUDING DATAFILES;


출처는 아래 페이지에서..

http://www.orafaq.com/node/2

'개발자세상 > Database관련' 카테고리의 다른 글

Open Cursor issue  (0) 2014.10.25
listagg function and ORA-01489  (0) 2014.01.09
오라클 DB에서 테이블마다 용량 구하기  (0) 2013.08.10
Overlap 데이터 구하기  (0) 2013.08.04
Stored Procedure 개발 / 실행  (0) 2012.12.08
Posted by headiron
,
SELECT SEGMENT_TYPE, SEGMENT_NAME, TABLESPACE_NAME, TRUNC((SUM(BYTES)/1024)/1024,2) as "용량(MB)"
FROM DBA_SEGMENTS   
WHERE SEGMENT_TYPE IN ('TABLE', 'INDEX', 'TABLE PARTITION', 'TABLE SUBPARTITION')
AND OWNER = '사용자명'
GROUP BY SEGMENT_TYPE , SEGMENT_NAME, TABLESPACE_NAME
ORDER BY 1 desc, "용량(MB)" desc;
출처 : http://koreantramp.tistory.com/216

기존에 개발해 놓았던 LOG 분석 시스템에서
동시 요청 정보를 확인해 보고 싶어서 작업을 돌려 봤더니 세월아 .. 내월아...
체크해 보니.. 시간이 Overlap 되는 정보를 확인하려면 시간 정보에 index가 있어야 하는데.. Index가 없어서 실행 계획이 엉망인것이다.

그래서 Index를 생성해 보았더니.. 이 Index가 생성되는데.. 세월아 .. 내월아..
다행이 예전에 back ground로 query 돌리던 script가 있어서 실행해 보았더니,
한참 돌다가.. TEMP 테이블스페이스가 용량이 부족해서 에러 발생...
https://forums.oracle.com/thread/369703
결국 TEMP 테이블 스페이스 용량을 추가 한 후 정상 생성..
그런데.. Index 생성하는데.. 하루 이상 걸렸다...

뭐.. 그래도 Index 생성했더니... 전에 보다는 몇 백배는 빨라 졌다.
근데.. 동시 요청 정보를 Account Level로 Check했더니 특정 User의 동시 사용 정보 때문에 다른 sequential 요청도 동시 요청으로 잡히는 문제 점 확인...

결국 코드를 수정했더니.. 전엔 Index access로만 데이터를 처리할 수 있었던 Query가
테이블 access가 발생하면서 다시 느려지는...

결국 User 정보를 Index가 다시 추가하는데...
속도는 느리고.. 또 Index 생성하다가 용량 부족으로 에러 나고... -.-

주말내내 Index 생성되는 걸 기다려야 할 듯 하다..

근데 Index 테이블 생성하고.. 위 Query로 체크해 보니..
Index가 테이블 사이즈 보다 훨 커져 버렸다.

말로만 듯던.. ( 어찌보면 분석 시스템에서는 필연적인..) 인덱스가 테이블보다 더 커지는 현상...

예전에 여러 회사에서 시스템 운영하면서 한번도 격어 보지 못했던..
대용량 DB 시스템 관련 이슈를 개인용 ( 물론 업무적으로 개발한거지만.. ) 분석툴에서 겪게 될 쭐이야....

좀 중구 난방 으로 개발 운영하여서 누더기 갇기는 하지만..
그동안 겪어 보고 싶던 대용량 데이터를 다루는 기쁨이라고 나 할 까...


'개발자세상 > Database관련' 카테고리의 다른 글

listagg function and ORA-01489  (0) 2014.01.09
Oracle TEMP 파일 삭제  (0) 2013.09.23
Overlap 데이터 구하기  (0) 2013.08.04
Stored Procedure 개발 / 실행  (0) 2012.12.08
오라클 실행계획 보기  (0) 2010.03.03
Posted by headiron
,

그동안에 API에서 CONCURRENT 관련 이슈가 많이 생겨서 RATE CONTROL FEATURE를 개발했다.
개발하고 나니, 어떤 CLIENT가 얼마가 쓰고 있는 지를 현재 모르고 있다는..
그 전에 CLIENT 들 한테 INFORM을 해야 하는데...
다행히 LOG 분석툴에 DATA는 쌓여 있는데... 동시 사용하는 건지 체크를 어떻게 해야 하나 고민이 되었다.

일단 LOG 데이터를 하나씩 읽어서 시간대가 겹치는 LOG가 있는지를 확인한 후 LOG 가 있을 경우 동시 사용자 정보로 넣는 코드를 생각해 보았는데...
내가 생각해 보아도 너무 무식한 방법인 것이다.

MATT하고도 잠시 상의해 보고 했는데.. MATT도 딱히 생각나는 IDEA가 없는 듯 하다.

결국 GOOGLEING을 했더니.. 나랑 비슷한 이슈를 가졌던 사람들이 있고 QUERY로 해결 할 수 있는 방법이 떡하니 있는 것이 아닌가..

http://stackoverflow.com/questions/2037618/overlapping-time-in-sql-server

http://docs.oracle.com/cd/B28359_01/appdev.111/b28396/long_vt.htm#i1007490


내 경우는...  Index가 날짜 FIELD에 맞추어 생성이 안되어 있어서 값이 RETURN되지 않아서
INDEX 생성  시키면서 그냥 데이터 하나씩 읽어서 중복 데이터 CHECK하는 원래 생각대로 개발 하였다.

역시 세계는 넓고 개발자는 많다는 거...
그나저나 이렇게 인터넷 세상이 발달한 때에 개발자로 산다는 게 얼마다 다행인지..


'개발자세상 > Database관련' 카테고리의 다른 글

Oracle TEMP 파일 삭제  (0) 2013.09.23
오라클 DB에서 테이블마다 용량 구하기  (0) 2013.08.10
Stored Procedure 개발 / 실행  (0) 2012.12.08
오라클 실행계획 보기  (0) 2010.03.03
ORACLE 사용자 생성  (0) 2010.03.03
Posted by headiron
,

작년말에 API LOG 분석툴을 개발하여 사용중이 었다.
PRODUCT에서 API를 매일 가져온 후 DB에 넣어서 사용량 추이를 볼 수 있게 한 것 인데,
매일 새벽에 경유서버에서 전체 PRODUCT의 LOG 파일을 가져온 후 분석 서버에서 경유서버의 파일을 가져와서 DB에 넣는 구조로 되어 있다.

헌데 경유서버에 보안 관련 설정을 해 놓아서 인지 대칭 보안키를 설정했는데도 SCP나 RSYNC를 사용할 때 암호를 계속 물어 보는 것이었다.
흠 이 문제를 어떻게 풀어 볼까 하고 찾아보았더니 sshpass 라는 utility가 있다.
password를 입력하기 어려운 shell script에서 password를 입력해 주는 훌륭한(?) Tool인 것이다.
일단은 shell을 실행해서 테스트 해 보니 잘 돌아서, cron에도 등록을 했는데..
cron에서는 계속 문제가 생기는 것이다.
환경 변수 이슈인듯 해서 shell도 바꾸어 보고, 혹시나 파일 다운로드 되기 전에 다음 step이 실행되나 싶어서 sleep도 주고 했는데, 현상은 바뀌지 않는 것이다.

결국 수동으로 계속 실행하고 있었는데..
율이 때문에 출산 휴가 간 사이에 정팀장님이 그 부분을 확인하시고 환경 변수 이슈인것 같다고 하신다. 그러면서 -x를 option으로 주면 debugging 정보를 확인할 수 있을 꺼라는 Hint까지..

일단 script내에 -x를 주고 테스트를 진행해 보니 일단 debug 정보가 나오기에,
cron 실행되는 걸 기다려서 cron log를 봤는데... log에는 정보가 없다.
근데.. shell에서 계속 mail이 왔다는 메시지가 떠서 mail 함을 열어 봤더니.. 거기에 debug 메시지가 포함된 실행 정보가 보이는 것이다.

결국 그 정보를 통해서 원인을 알아내어 이제는 자동으로 메일 작업이 잘 돌게 되었다.
근데.. 원인은... ?
sshpass가 /usr/local/bin 에 설치되어 있는데 해당 경로가 PASS에 안 잡혀서 발생한 것이었다.
sshpass 같은 utility면 당연히 shell에서 사용될 텐데.. 어찌 그게 cron 에서 자동으로 잡히는 경로에 설치가 안 됐는지...

좀더 자세한 정보는 아래 페이지에서 찾을 수 있다.
http://www.cyberciti.biz/tips/debugging-shell-script.html



Posted by headiron
,

API 관련 테스팅 프레임워크를 만들면서 json을 출력하게 하는데..
그냥 출력하려니.. 양심에 찔려서 인터넷을 뒤져 봤더니 gson을 이용하면 깔끔하게 출력해 주는 Tip이 있다.

http://stackoverflow.com/questions/8596161/json-string-tidy-formatter-for-java

JsonParser parser = new JsonParser();
Gson gson = new GsonBuilder().setPrettyPrinting().create();

JsonElement el = parser.parse(jsonString);
jsonString = gson.toJson(el);
위와 같이 간단히 해결하고 한동한 있고 있었는데.
오늘 독일팀이 잘 쓰고 있는데 좀 문제가 있네 하면서 보내준 내용을 보니
json 리턴 값에 HTML 태그랑, JavaScript가 있어서 출력값이 깨져서 나오게 된다.

흐미... 내가 왜 HTML이 포함될 수 있다는 걸 까먹고 있었는감...-.-
어쨋든 뭐...JSON 결과를 HTML escaping하면 간단히 해결되지 않을까 싶었는데..
테스트 해보니. JSON 내의 " 까지도 escaping이 되버리는 바람에 formatting 한게 물거품이 되어 버리고 만다.-.-
( formattting 한후 <pre></pre> 태그를 앞 뒤로 붙여 formatting한 결과를 보여 주어서...)

이런 저런 생각을 계속 하다 보니 결국 방법은 JSON 데이터를 Parsing 한 후 Field 를 Traversing 하며 출력해 주면서 Field 값이 문자열일 경우에 HTML escaping을 하면 될 것 같다.

마침 다른 이슈로 recursive 하게 json traversing하는 로직을 만들어 놓은 게 있어서 사용을 했더니 결국 HTML escaping이 깔끔하게 해결되었다.

public String getPrettyHtmlJson(String content){
try {
Object jsonContent = JSONParser.parseJSON(content);
return "<pre>"+getPrettyHtmlJsonElement(jsonContent, 0,false)+"</pre>";

} catch (JSONException e) {
e.printStackTrace();
return content;
}
}

private String getPrettyHtmlJsonElement(Object object, int indent, boolean indentNeed) throws JSONException{
String content = "";
if ( object instanceof JSONArray){
JSONArray jsonArray = (JSONArray) object;
if ( indentNeed)
for(int i = 0; i < indent; i++) content+=" ";
content+= "[ \n";
for(int j = 0; j < jsonArray.length(); j++){
if ( j > 0 ) {
content+=", \n";
//for(int i = 0; i < indent; i++) content+=" ";
}
content += getPrettyHtmlJsonElement(jsonArray.get(j), indent+1, true);
}
content += "\n";
for(int i = 0; i < indent; i++) content+=" ";
content+= "]";
return content;
}
else if ( object instanceof JSONObject){
if ( indentNeed)
for(int i = 0; i < indent; i++) content+=" ";
content+= "{\n";
JSONObject jsonObject = (JSONObject) object;
String[] names = JSONObject.getNames(jsonObject);
for(int j =0 ; j < names.length; j++){
String name = names[j];
for(int i = 0; i <= indent; i++) content+=" ";
content+= "\""+name+"\" :";
Object fieldObject = jsonObject.get(name);
if ( fieldObject instanceof JSONArray)
content += getPrettyHtmlJsonElement(fieldObject, indent+1, false);
else if ( fieldObject instanceof JSONObject)
content += getPrettyHtmlJsonElement(fieldObject, indent+1, false);
else if ( fieldObject instanceof String){
content += "\""+StringEscapeUtils.escapeHtml4(fieldObject.toString())+"\"";
}
else
content += "\""+fieldObject.toString()+"\"";
if ( j + 1 < names.length )
content += ",";
content +=" \n";
}
for(int i = 0; i < indent; i++) content+=" ";
content+= "}";
return content;
}
else{
for(int i = 0; i < indent; i++) content+=" ";
content+= "\""+object.toString()+"\"";
return content;
}
}

잘 되었네.. 하고 접을 까 싶었더니...
Field 순서가 뒤죽 박죽이다.
구글링을 해보니.. JSON은 순서를 보장하지 않는 필드 List라는 문구가 나온다.
흐... 그래서 field ignore 시킬 때 JSON Parsing을 하면 순서가 뒤바뀌어서 나왔었구나...

뭐.. 순서가 바뀌어 출력되도 스펙 내용에 따르면 별 문제는 없는데..
그래도 개발의 양심이라는 것이...
결국은 좀더 조사해보니...
JSONObject map을 HashMap에서 LinkedHashMap으로 바꾸면 해결 된다고 한다.

http://stackoverflow.com/questions/4515676/keep-the-order-of-the-json-keys-during-json-conversion-to-csv

마침...
J
son Assert가 org.json.* 구조를 이용하는데.. 이 library는 마침 JSON.org에서 다운 받은 jar를 사용하고 있어서..
source를 받아서 위에 얘기한 대로 LinkedHashMap으로 바꾸고 나니 문제점 깔끔하게 해결...

덕분에 field ignore 할 때도 필드 순서 보장하게 되고...
HTML escapaing 문제도 해결하고 ... formatting때문에 사용한 gson library도 빼고...

골치아픈 HTML escaping 이슈가 오히려 전화위복이 되어 더 깔끔한 프레임웤이 완성되었다.


Posted by headiron
,

API로는 처리가 안되는 Client issue로
별도 Job을 작성해서 FTP로 정보를 제공해 주는 서비스가 있는데..
얼마전에 해당 Client의 FTP 서버 이슈로 파일이 전송되지 않는 문제가 발생했다.

그쪽에서 문제 해결 한 다음에 FTP 서버에 수동으로 파일을 넘겨 주어 해당 이슈는 해결이 되었는데..

그 쪽 VP가 FTP Uploading 중 문제가 발생할 경우에 1시간 주기로 여러번 Try 할 수 있도록 Script를 수정해 달라는 요청을 해왔다.

마침 몇 일간 다른 이슈가 있어서 조만간 봐주겠다고 메일만 보내놓고 있었는데..
어제 VP가 수정 요청 어떻게 됐냐고 물어 온다.
흑.... 어물쩡 넘어 갈 까 했었는데...

오늘 마침 시간이 나서.. 자료를 찾아 보다가
Matt한테 이슈를 얘기 해 보니 간단한 solution을 준다.

Shell에서 command를 실행 한 후 exit code를 체크해 보면 될꺼라고 한다.
internet에서 예제까지 찾아서..

http://linuxers.org/howto/how-find-exit-code-last-executed-command-bash-using-environment-variable
$? 값을 체크하면 이전에 실행된 command의 return 값을 확인할 수 있다고 ..

흠.... 이런 좋은 TIP을 하고 생각하며 script를 작성하려니...
다른 article에 ftp는 에러가 발생해도 정상(0) 를 return한다는 내용을 찾아서 바로 알려 준다.

http://stackoverflow.com/questions/4899316/getting-exit-status-code-from-ftp-command-in-linux-shell

결국 아래와 같이 FTP 메시지를 Capture 하여 SUCCESS MESSAGE가 있는 지 수동으로 체크해야 한단다.

FTPLOG=/temp/ftplogfile
ftp -inv <<! > $FTPLOG
open server
user ftp pwd
put filename
close
quit
!

FTP_SUCCESS_MSG="226 Transfer complete"
if fgrep "$FTP_SUCCESS_MSG" $FTPLOG ;then
   echo "ftp OK"
else
   echo "ftp Error: "$OUT
fi
exit 0

결국은 위 내용을 응용하여 에러 발생하면 SLEEP 했다가 다시 FTP 파일 올리는 방법으로 해당 SHELL 수정을 완료 했다.

혼자 끙끙 거리면서 해결할라고 했으면 한 참 뒤져도 해결 못했을 텐데
Matt의 TIP 덕분에 1~2시간 만에 해결하였다.

모르는 문제는 너무 혼자서 해결하려 하기 보다는 함께 공유하면 쉽게 해결 될 수 있다는>>..
그리고 Matt이 정말 좋은 동료라는 걸 새삼스럽게 각인하는 하루 였다.

Thanks , Matt.

Posted by headiron
,