2019년 7월 10일 수요일

grep 사용 예제.

로그 데이터에서 필요한 부분만 추출하려고 하였다.
필요한 부분은 [f1]이라는 부분의 바로위 라인 이다.
처음에는 노트패드++에서 모든 파일을 열고 하나씩 복사 하려고 했는데, 데이터가 어마어마하게 많아서
grep 으로 처리 했다.
윈도우10에서 명령어 창을 열고 bash 라고 커맨드를 입력하면 linux 커맨드를 사용할 수가 있게 된다.


실제 데이터 샘플
...
2019-06-25 오후 1:14:53 [INTERFACE] [310166] [2201] [211.252.80.44:5614] Receive Reqeust ==================================================
2019-06-25 오후 1:14:53 [INTERFACE] [310166] [2201] [211.252.80.44:5614] [02 20 19 06 25 13 14 51 0A 84 02 33 31 30 31 36 36 32 32 30 31 66 31 00 B7 00 05 00 00 00 FF FF FF FF FE 00 00 28 DC 31 30 31 30 30 31 30 31 30 37 33 38 37 30 35 32 00 00 02 A2 01 16 27 00 00 00 00 00 02 20 19 06 25 11 57 53 13 23 45 00 00 07 04 BF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FE 7A 03 ]
2019-06-25 오후 1:14:53 [INTERFACE] [310166] [2201] Thread reqINS [f1]
...


조건
1. [f1]를 찾아서 한줄 위에 있는 부분을 가져온다.
2. 그 중 Send가 들어간 부분을 제외한다.
3. 시간 순서대로 sorting 해야 한다.



최종 명령어
grep -h -r -B1 '\[f1\]' ./  | grep -vE '\[f1\]'  | grep -v '\-\-' | grep -v 'Send' | sed 's/\ \([0-9]\)\:/\ 0\1\:/g' | sort  -k2 -k3.1,3.2 -k3.4,3.5 -k3.7,3.8  > sort_match.txt


--------설명--------
:: << 구분

-h :: 파일이름 없이 출력
-r :: 하위 디렉토리
-B1 :: 검색된 위치 바로 위
'\[f1\]' :: 실제 검색 할 키워드, original keyword : [f1]
./ :: 검색 위치
grep -vE '\[f1\]' :: 바로 위 라인만 필요하고 실제 검색 된 위치는 필요없으므로 제외 시킴
grep -v  :: '\-\-' 검색 라인마다 추가되는 데, 옵션이 따로 있을 것 같지만 급해서 제외 시킴
grep -v 'Send' :: Send 는 제외
sed 's/\ \([0-9]\)\:/\ 0\1\:/g' :: sort 를 해야 하는 데, 데이터의 시간 일자가 '2019-06-25 오후 2:58:06' 이런식으로 시간이 02가 아닌 2이라서 sort가 안됨. 그래서 ' 2:'를 ' 02:'로 변경시킴
sort  -k2 -k3.1,3.2 -k3.4,3.5 -k3.7,3.8 :: '2019-06-25 오후 2:58:06' 의 형태를 sort 시킨다. 일자는 모두 같은 날이여서 포함 시키지 않았다.
k2 는 오전, 오후를 부분,
k3.1,k3.2 는 시(02),
k3.4,3.5는 분(58),
k3.7,3.8는 초(06)를 기준으로 sort 한다.

2019년 6월 20일 목요일

spring boot mybatis 에서 rollback 이 안되는 문제, 해결 한 결과


기본 base가 되는 table이 있고, 그 테이블에 대한 이력을 저장하는 history테이블이 있을 경우, base가 insert가 성공하고, history에서 에러가 발생할 경우 rollback이 되지 않는 문제가 있어서 여러가지 테스트를 해 본 결과이다.


1. 컨트롤러에서 base와 history 두개의 service를 가져와서 처리하는 경우 rollback이 되지 않는다.
서비스단에서 @Transactional 를 주고 처리를 해야 rollback이 된다.

2.Transactional 어노테이션은 클래스에 줘도 적용된다.


3. 이 부분 때문에 고생했다.
아래와 같이 강제로 익셉션을 발생시키면서 try catch로 잡으면 rollback이 안된다.
아래와 같이 메소드에서 throws Exception을 해 줘야 한다.
이 때 강제로 발생시키는 익셉션은 (rollbackFor = Exception.class) 옵션을 줘야 rollback이 된다.

@Transactional(rollbackFor = Exception.class)
public class CompanyRoleService extends GenericService<CompanyRole, CompanyRoleRequest> {

...
    public int saveWithHistory(CompanyRole object) throws Exception {
        AddBaseEntity.addCreatedBy(object);
        object.setUseYn("Y");
        object.setDeleteYn("N");
        int baseSuccessCount = baseMapper.insert(object);
        if(baseSuccessCount>0){
            throw new Exception("test");
        }
...


2019.07.26 추가.
4. try catch로 롤백 하는 방법
https://stackoverflow.com/questions/25738883/spring-transactional-annotation-when-using-try-catch-block


메소드에 선언.
@Transactional(rollbackFor={MyException1.class, MyException2.class, ....})
public Result doStuff(){
   ...
}

or

프로그램 방식으로 rollback
public Result doStuff(){
  try {
    // business logic...
  } catch (Exception ex) {
    // trigger rollback programmatically
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  }
}


2019년 6월 19일 수요일

queryDsl로 groupBy having 사용시 에러 발생.

queryDsl로 groupBy having을 사용할 때 아래와 같은 에러가 발생한다.
nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: having near line 3, column 1 [select count(distinct multiLangInfo.languageCode)\nfrom com.charzin.cems.api.model.multiLang.MultiLangInfo multiLangInfo\nhaving multiLangInfo.languageType = ?1]


문제의 원인은  fetchCount()라는 전체 개수를 가져오는 함수를 사용하는 데, 이 함수가 만들어 주는 sql 쿼리문이 잘못 되었다. 위에 오류내용에 나와 있듯이 그냥 groupby를 없애버리는 쿼리를 만든다.

할 수 없이 전체 개수를 구해오는 쿼리를 따로 만들었다.

보통 group by 카운트를 가져오는 from 절 subquery는 queryDsl에서 지원하지 않는다.
여기서 확인.

할 수 없이 네이티브를 사용했다.

2019년 5월 27일 월요일

spring mongodb Sort시 에러.

spring mongodb Sort시에 아래와 같은 에러가 발생한다.

Query failed with error code 96 and error message 'Executor error during find command :: caused by :: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit.' on server localhost:27017

조회하려는 테이블이 log성 테이블이라 백만건이 넘어간다.
Sort 하려는 필드는 lastUpdated 이다. 해당 필드를 index에 추가 해서 해결했다.
index 추가하는 건 compass로 접속 해서 collection 선택하면 나오는 index 탭에서 쉽게 할 수 있다.

근데, compass에서는 index 설정을 안해도 잘 된다. 어떻게 되는 건지 모르겠다.

2019년 4월 17일 수요일

mysql federated 트래픽 증가 문제.

어느 날 갑자기 트래픽이 약 2배이상 증가한 것을 확인 해 보니 nethogs 로 확인 해 보니
 mysql 프로세스가 문제 였다.

federated 를 사용하여 간단한 상태체크를 하는 테이블을 하나 만들어 사용중이였는 데, 이게 문제 였다.

원인은 federated 테이블을 select 해 올 때 index를 타지 않으면 모든 데이터를 가져온 후 처리 하는 방식이였다.

약 22,000건 정도의 데이터를 가져오는 데, 약 1.5M 정도의 데이터를 사용하고 있었다.


         SELECT
        *
       FROM CHARGER_STATUS
       WHERE send = 'N'
       AND createdAt > @intervalTime

createdAt(timestamp)에 index를 설정하고 실행 하니 2K정도로 줄어든 것을 확인 할 수 있었다.

2019년 4월 15일 월요일

mysql http post json 전송 트리거

mysql http post json 전송 트리거


테이블에 값이 insert 되면 trigger를 이용하여 http post를 전송하도록 한다.
mysql 자체적으로는 해당 기능을 지원하지 않는다.

검색해 보니 mysql의 UDF(user define function)를 이용하여 만들어진 mysql-udf-httpmysql-udf-http lib가 있다.


근데 최근 업데이트 2013년이다. 찜찜한 면이 있지만, 소스를 살펴보니 별 거 없다.
libcurl을 이용하여 http 전송해 주는 c로 짠 플러그인이다.



소스를 서버에 받은 후 압출을 풀고 컴파일 하면 된다.
문서상으로 되어 있는 설치가이드는 mysql을 소스 설치 했을 때 상황으로 보인다.
yum을 이용하여 설치 하였기 때문에 config 설정이 조금 다르다.
config 시 mysql_config 명령어를 사용하는 데, mariadb-devel를 설치해야 한다.


sudo yum install mariadb-devel -y

sudo wget https://github.com/y-ken/mysql-udf-http/archive/master.zip

unzip master.zip


or
(git 명령어가 있으면)
git clone https://github.com/y-ken/mysql-udf-http.git


여기서 소스를 조금 수정 해야 된다.
실제 테스트 해보면, http_post로 json 전송하면 받는 server에서 json 타입으로 인식을 하지 못한다.
json으로 post 전송하기 때문에 header에 "Content-Type: application/json"이 필요하지만 그런 설정 부분이 없다.
워낙 소스가 간단해서 http_post function을 복사해서 http_post_json을 하나 만들고
해더만 아래처럼 추가 했다.
...
  if (curl)
  {
    struct curl_slist *hs=NULL;
hs = curl_slist_append(hs, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hs);
...

소스 수정 파일


재컴파일 후 mysql 재시작 후 function 등록.
create function http_post_json returns string soname 'mysql-udf-http.so';

테스트 해보면 정상적으로 인식 된다.



cd mysql-udf-http-master/

sudo CPPFLAGS="-I/usr/include/mysql" sh ./configure --with-mysql=/etc/my.cnf   --enable-shared --libdir=/usr/lib64/mysql/plugin && sudo make && sudo make install



설치가 정상적으로 완료 되었으면 /usr/lib64/mysql/plugin 디렉토리에 mysql-udf-http.* 파일들이 생긴다.
동적으로 인식이 되기 때문에 mysql 재시작은 안해도 된다. (*** 같은 이름으로 다시 넣으면 인식 안된다. 그럴 때는 재시작하자)

mysql console 상에서 function을 등록해 준다.

create function http_get returns string soname 'mysql-udf-http.so';
create function http_post returns string soname 'mysql-udf-http.so';
create function http_put returns string soname 'mysql-udf-http.so';
create function http_delete returns string soname 'mysql-udf-http.so';


사용법
SELECT http_get('<url>');
SELECT http_post('<url>', '<data>');
SELECT http_put('<url>', '<data>');
SELECT http_delete('<url>');

테스트로 가져오면 잘 가져온다.
select http_get('http://example.com/');



lib_mysqludf_json을 설치해서 json 타입을 리턴 받을 수 있다.


소스를 다운받은 후 so 파일로 만들어 주면 된다.
이건 make를 지원하지 않아 다른 방식으로 만들어야 된다.
같이 다운받아지는 so 파일을 사용하려고 봤는데, 32bit이다.
[root@VM1554776686489 lib_mysqludf_json]# file lib_mysqludf_json.so
lib_mysqludf_json.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped

삭제 하자.

git clone https://github.com/mysqludf/lib_mysqludf_json.git

cd lib_mysqludf_json/

gcc -fPIC -shared -o lib_mysqludf_json.so -I/usr/include/mysql/  lib_mysqludf_json.c


만들어진 lib_mysqludf_json.so 파일을 plugin 폴더로 넣자.
mv lib_mysqludf_json.so /usr/lib64/mysql/plugin/

.sql 파일을 보면 function 만드는 법이 나온다. 복사해서 쓰자.


mariadb 기반으로 설치 하였다.


https://github.com/y-ken/mysql-udf-http
https://github.com/mysqludf/lib_mysqludf_json

워드프레스 서버 날라가다.

워드프레스를 사용하던 서버가 드디어 날라가 버렸다.
한 10개의 글도 같이 날라 갔다.

서버를 다시 맞추기가 어렵다.
구글 블로그로 갈아 타기로 했다.

최초로 설치형 블로그를 시작한 개기도 당시 근무하던 회사에서 외부 블로그 검색 자체를 막아 놨기 때문이였다.

이제 그런 것도 없으니 구글블로그를 써도 무방하다.
도메인 역시 필요없어지게 됐다. 연장 하지 않을 예정이다.