분류

레이블이 MYSQL인 게시물을 표시합니다. 모든 게시물 표시
레이블이 MYSQL인 게시물을 표시합니다. 모든 게시물 표시

2022년 5월 2일 월요일

DA# MARIADB, MYSQL 한글 깨짐 해결

개요 

개인적으로 공모전 준비나 DAP 시험 준비를 위해 'ENCORE-DA#'을 사용 하던 중 UTF-8 인코딩 타입의 한글이 깨지는 현상이 발견되었고, 이에 관한 기술 지원을 받기 위해 문의했으나, 상당한 시일이 걸리기도 하고, 자료를 찾는데 애먹기도 해서 정리를 해 보았습니다. 

먼저 mysql 이나 mariadb의 데이터베이스와 테이블에서 모두 utf-8로 설정이 되어있는지 확인 하신 이후에도 안될 경우에 대한 이야기 입니다. 해당 부분이 설정되지 않은 분들은 타 블로거의 글을 참조 하시기 바랍니다. 

저의 경우 utf-8을 모두 맞췄으나 da#에서 한글이 깨지는 케이스에 대한 설명 입니다. 설정이 잘 되어있기에 dbeaver 나 콘솔에선 한글이 정상으로 보이지만 da#만 깨집니다. 

utf-8 설정 참조 블로그 글


1. DA#에서 필요한 MARIADB(MYSQL) DRIVER 

WINDOWS 기반의 DA#에서 MYSQL이나 MARIADB에 접속하려면 우선 ODBC 드라이버를 설치해야 합니다. 설치하지 않은 경우 다음과 같이 데이터베이스를 선택하는 항목이 비어져 있습니다. 

DA# 리버스> DB리버스 > 데이터베이스 접속 화면

1) odbc 드라이버 선택

직접 테스트를 수행해본 결과 mysql 5.3.14(32bit) 이상의 버전이 설치 되어있어야 합니다. 처음 3.x 버전을 사용했을 경우 UTF-8 인코딩으로 테이블과 데이터베이스가 모두 설정이 되어 있어도 한글이 깨지는 현상이 발생 합니다. 또한 os가 64bit 버전이어도 da#프로그램이 32bit 버전이므로 32bit버전을 받는 것을 추천합니다. 

드라이버 다운로드 버전

MYSQL DRIVER DOWNLOAD 링크  <--- 이 부분을 클릭하셔서 정식 MYSQL ODBC 드라이버를 다운로드 받습니다. 

2) 드라이버 설치 

8. 대역의 32bit 드라이버 설치는 별다른 선택이나 옵션 없이 이루어집니다. 하지만 5.x버전 드라이버는 visual studio 패치가 이루어져야 합니다. 
visual studio 2013 x86 redistributable 설치 안내
visual studio 2013 x86 다운로드 페이지


visual-studio 다운로드 사이트
2013 x86을 선택하고 다운로드 후 설치는 그냥 다음만 누르면 되므로, 드라이버와 visual studio를 모두 설치해줍니다. 

3) odbc 설정하기 

windows 시작 버튼을 누르고 odbc를 입력하면 odbc 드라이버 설정을 수행하는 화면이 등장 합니다.  DA#에서는 32bit 버전이 필요하기에 32bit 환경 설정을 수행해 주세요 
odbc 드라이버 연결 창
ODBC 드라이버 설치 시 3.x 버전에서는 한글이 깨지는 이유는 딱 봐도 알 수 있습니다. 5.x버전 드라이버에서는 ANSI와 UNICODE 형식의 드라이버를 구분해서 지원하는 반면 3.x버전 드라이버에서는 구분이 없는 것으로 보아 둘 중 하나의 형식만을 지원 합니다. 

DA#에서는 Unicode 드라이버 형식만을 지원하는 것 같습니다? 그렇다면 3.x 버전은 ansi 만 지원 하겠네요 . 테스트를 해보면 알 일입니다. 


본인의 프로젝트 정보에 맞춰 접속 정보를 입력합니다. 여기서 Data Soruce Name 이라는 부분이 있는데 이 부분은 사용자가 사용하기 위한 명칭을 정의하는 부분입니다. 실제 db와 달라도 괜찮습니다.  IP, PORT, USER, PASSWORD를 넣고 TEST를 누르면 DATABASE 목록이 조회 됩니다. 여기서 접속할 데이터베이스를 선택하고 ok를 누르시면 환경이 저장 됩니다. 

4) da#에서 테스트 


da# 모델러를 실행 후 리버스 -> db리버스 를 누르면 생성되는 팝업창에서 mysql과 접속정보를 입력해줍니다. 데이터 소스는 사전에 odbc를 등록한 목록의 명칭이 선택창으로 나타나게 됩니다. oracle 을 리버스 할 경우 테이블을 선택하는 기능이 있는데 mysql은 이상하게 해당 기능이 보이질 않습니다. 


3.x 버전 odbc설치시 한글 깨짐 상태


mariadb odbc 5.3 windows 32bit 설치시 정상


결론 

mysql odbc는 3.x 버전에서는 한글 깨짐,

5.x 이상 버전의 windows 64bit 용 드라이버는 da#에서 인식되지 않음.

5.x 버전의 windows 32bit 용 드라이버는 unicode와 ansi 모두 한글 정상 지원 

이상입니다. 읽어주셔서 감사합니다. 


2021년 5월 24일 월요일

spring boot기반 batch 프로젝트 생성부터 mybatis 연동 단순하게.

 개요 

회사에서 배치 프로세스를 분리해야 하는 일이 생겼습니다. 인터넷으로 이런 저런 조사를 해보는데 정상적인 문서를 찾기 힘든 것이 현실이고, 구했다 하더라도 입맛에 맞는 구조가 아닌 경우가 많아 최소한의 soruce를 통해 mybatis 연동(MariaDB)까지 정리 해보려 합니다. 

본문의 순서는 다음과 같이 진행 하겠습니다.

1. Eclipse spring Boot 설치 

2. Project 생성 

3. Project 환경 설정 

4. application.properties 설정 

5. Source 코드 생성 

6. 발생할 수 있는 오류

순으로 정리되어있습니다. 캡처를 할 경우 너무 여러 장을 찍어야 하기에 설치 순서는 동영상으로 대체하였습니다. 

그럼 시작하겠습니다. 


1. Eclipse spring Boot 설치 

일단 spring boot 프로젝트를 생성하기 위해서는 Eclipse의 Spring Tool이 필요합니다. Eclipse의 Help 버튼을 눌러 Market Place에 들어가서  Spring Tool을 검색해서 Install 하고 Eclipse를 다시 시작 합니다. 

Spring Tool 인스톨 영상 

2. Project 생성 

Project의 생성은 create a new project -> spring 검색 -> Spring Starter Project -> java 버전 선택 -> project 및 package 명 변경 -> spring batch 선택 -> Mybatis Framework 선택 -> finish 순으로 진행하였습니다. 

project 생성 영상 


3. Project 환경 설정


환경설정에 연관된 파일
환경설정에 연관된 파일은 2가지입니다. 
1) pom.xml을 통한 라이브러리 환경 설정과 
2) 프로젝트 환경 설정의 application.properties 파일입니다. 

1) 라이브러리 환경설정 

우선 저는 mariadb를 연결해야 하기에 mariadb의 maven 라이브러리를 pom.xml에 추가하겠습니다. maven을 통한 라이브러리 추가는 google 에서 maven +라이브러리 를 검색하거나 
메이븐 사이트 https://mvnrepository.com/

위 링크로 접속하셔서 해당 라이브러리를 검색하시면 쉽게 dependency 정보를 찾을 수 있습니다. 

mysql 드라이버 정보


검색된 메이븐 라이브러리중 자신에게 해당하는 버전을 클릭하면 이렇게 하단에 디팬던시 정보가 표기되어 해당 정보를 pom.xml에 붙여넣기 하면 됩니다.

pom.xml에 붙여넣기



4. application.properties 설정 

application.properties에 프로젝트에 사용할 환경 설정을 추가해줍니다. application.properties 는 spring toole에서 자동 완성을 지원합니다. 구동 화면은 아래와 같습니다. 
application.property 설정 영상

실제 application.properties에 수록된 내용은 다음과 같습니다. 
#데이터 베이스 연결에 사용할 드라이버 
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#데이터베이스 url 
spring.datasource.url=jdbc:mysql://192.168.0.1:6330/test?serverTimezone=UTC&characterEncoding=UTF-8
#계정 
spring.datasource.username=testUser
#비밀번호
spring.datasource.password=testUser

#mapper 파일이 적재될 위치 sql mapper 파일과 동일하게 맞춰준다.
mybatis.mapper-locations=com/springBatchTest/mapper/*.xml
#커스텀 환경변수 
custom.test=test-value


5. Source 코드 생성 

우선 application.properties에 설정한 위치에 mapper xml파일을 만들어줍니다. 
환경설정 순서(클릭시 커짐)
현재 프로젝트의 application 설정이 마이바티스 까지 연동되는 구조는 다음 순서에 따라 이루어집니다. 
application에서 모델을 연결해주는 것은 mapper location.
모델과 컨트롤러의 연결은 xml 파일내의 namespace가 classPath로 역할을 하게 되더군요. 

수정 및 생성한 소스프로그램은 총 4개의 파일입니다. 
1) testMapper.xml 
2) TestDataMapper.java
3) TestDataService.java
4) SpringBatchTestApplication.java
차례대로 기술하겠습니다. 

1) testMapper.xml 

mysql DB에서 데이터를 조회할 sql 문을 입력합니다. 또한 namespace에 java에서 연동할 인터페이스의 패키지 경로와 파일명을 입력합니다. 
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 인터페이스의 패키지 경로와 클래스명 -->
<mapper namespace="com.springBatchTest.mapper.TestDataMapper">

<!-- 수행할 sql -->
    <select id="getTestDataList" resultType="java.util.Map">
<![CDATA[
SELECT 1 AS COL1 
UNION ALL 
SELECT 2 AS COL1
]]>
    </select>
</mapper>
sql은 간단하게 테스트를 수행할 수 있게 정의하였습니다. 

2) TestDataMapper.java

mapper.xml 에 정의된 위치에 정의된 명칭으로 생성해줍니다. 인터페이스 내부에는 xml에 정의된 sql과 동일한 명칭 그리고 동일한 데이터 형식을 갖고 있는 함수가 있어야 합니다. 
package com.springBatchTest.mapper;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface TestDataMapper {
List<Map<String, Object>> getTestDataList();
}
mybatis framework과 java Application간의 인터페이스 역할만 해주므로 정말 내용이 없습니다. SQL이 늘어나는 만큼 증가합니다. 

3) TestDataService.java

서비스에는 인터페이스에 정의된 형식과 동일한 서비스를 구성해줍니다. 이 파일 역시 자동 연결을 위한 선언 ,  서비스 선언 이외에 특별한 내용이 없습니다. 
package com.springBatchTest.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;

import com.springBatchTest.mapper.TestDataMapper;

@Service
public class TestDataService {
    @Autowired
    TestDataMapper testData

    public List<Map<String, Object>> getTestDataList() {
        return testData.getTestDataList(); 
    }
}


4) SpringBatchTestApplication.java

package  com.springBatchTest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.List;
import  java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import  com.springBatchTest.service.TestDataService;

@SpringBootApplication
public class SpringBatchTestApplication {
public static void main(String[] args) {
try (ConfigurableApplicationContext ctx = SpringApplication.run(SpringBatchTestApplication.class , args)) {
SpringBatchTestApplication m = ctx.getBean(SpringBatchTestApplication.class );
m.selectDataf(); 
}catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
}
  @Autowired
  TestDataService  testDataService;
    public void selectDataf() {
    List<Map<String, Object>> tmp = testDataService.getTestDataList();
    System.out.println(tmp.size());
    }
}


자 이제 테스트용 코드 생성은 끝났습니다. 

6. 발생할 수 있는 오류

1) 정상 처리 시 디버깅 콘솔 내용 


2021-05-24 19:28:03.528  INFO 10964 --- [           main] c.s.SpringBatchTestApplication           : Starting SpringBatchTestApplication using Java 15.0.1 on DESKTOP-3QN7REN with PID 10964 (D:\blogger\springBatchTest\target\classes started by jinyboys in D:\blogger\springBatchTest)
2021-05-24 19:28:03.533  INFO 10964 --- [           main] c.s.SpringBatchTestApplication           : No active profile set, falling back to default profiles: default
2021-05-24 19:28:06.259  INFO 10964 --- [           main] c.s.SpringBatchTestApplication           : Started SpringBatchTestApplication in 3.553 seconds (JVM running for 4.553)
2021-05-24 19:28:06.277  INFO 10964 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...

2021-05-24 19:28:06.771  INFO 10964 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2
2021-05-24 19:28:06.897  INFO 10964 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
945  INFO 10964 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

수행할 로직이 없기 때문에 약 3,4초만에 수행되고 종료되며 임시로 생성된 sql에서 받는 데이터 2건에 대한 사이즈 정보가 표기됩니다. 

2) application.properties내의 mapper 경로가 잘못 된 경우  

빨간색 글자처럼 파일을 찾을 수 없다는 메시지가 나옵니다. 
2021-05-24 19:31:39.543  INFO 7172 --- [           main] c.s.SpringBatchTestApplication           : Starting SpringBatchTestApplication using Java 15.0.1 on DESKTOP-3QN7REN with PID 7172 (D:\blogger\springBatchTest\target\classes started by jinyboys in D:\blogger\springBatchTest)
2021-05-24 19:31:39.553  INFO 7172 --- [           main] c.s.SpringBatchTestApplication           : No active profile set, falling back to default profiles: default
2021-05-24 19:31:42.462  INFO 7172 --- [           main] c.s.SpringBatchTestApplication           : Started SpringBatchTestApplication in 3.802 seconds (JVM running for 5.327)
2021-05-24 19:31:42.479  INFO 7172 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...

2021-05-24 19:31:42.987  INFO 7172 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2021-05-24 19:31:43.074  INFO 7172 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2021-05-24 19:31:43.086  INFO 7172 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
Invalid bound statement (not found): com.springBatchTest.mapper.TestDataMapper.getTestDataList

3) mapper.xml 파일 내부 SQL구문의 ID와 mapper.java 인터페이스가 불일치 할 경우

위와 동일한 오류가 발생합니다. 
 Invalid bound statement (not found): com.springBatchTest.mapper.TestDataMapper.getTestDataList

4) service.java 클래스 내에 @Autowired 설정이 없는 경우

Cannot invoke "com.springBatchTest.mapper.TestDataMapper.getTestDataList()" because "this.testData" is null

5) mapper.java 클래스가 없거나 비정상 , @mapper 설정이  없는 경우

Description:

Field testData in com.springBatchTest.service.TestDataService required a bean of type 'com.springBatchTest.mapper.TestDataMapper' that could not be found.

The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.springBatchTest.mapper.TestDataMapper' in your configuration.

Error creating bean with name 'springBatchTestApplication': Unsatisfied dependency expressed through field 'testService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testDataService': Unsatisfied dependency expressed through field 'testData'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.springBatchTest.mapper.TestDataMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}


이상 스프링 배치 프로젝트 생성부터 mybatis 연동까지 그리고  발생할 수 있는 오류까지 알아봤습니다. 

이렇게 쉽게 4개의 파일만 설정하면 연동할 수 있는 기본적인 형태를 이해하지 못하고 엉뚱하게 정리 해 놓은 글들이 너무 많아 직접 정리를 해 보았습니다. 누군가에게 도움이 되면 좋겠네요 ㅎㅎ. 

2020년 9월 20일 일요일

mariadb CONNECT BY, 시간계산, 프로시저 만들기 요약.

개요 

오픈소스 기반 프로젝트를 수행하면서 MARIADB라는 녀석을 접하게 되었습니다. 기존의 ORACLE환경과는 다르기에 프로시저를 짜는데 애를 먹는 바람에 정리를 하려 합니다. 

그리고 프로그램 설정의 오류 때문인지 LOOP 문을 돌릴 경우 발생되는 데이터가 초당 20건밖에 되지 않는 기이한 현상이 있었는데 이런 건 PGA 메모리가 부족하든 CPU를 프로그램에 할당한 것이 없든 여러 환경적 문제가 있는 것 같습니다. 하지만 이런 문제를 모두 정리하기엔 시간이 부족하기에 루프문을 최소화해서 처리하는 해법을 찾아보았습니다. 


1. CONNECT BY LEVEL 문을 통한 여러 행 생성하기 

마땅히 CONNECT BY 문이 없어 애를 먹는 과정에서 RECURSIVE 관계를 WITH문을 통해 만들 수 있는 것을 발견하였습니다. 

저는 임의의 행 데이터 집합을 가상의 형태로 만들어야 하는 프로시저를 만들어야 합니다. 따라서 기존 작성했던 쿼리와 비교하며 검색을 해보았습니다. 

ORACLE : 

SELECT * FROM 
   임의테이블 A
   , (SELECT LEVEL AS LV FROM DUAL CONNECT BY LEVEL <=10)  B

위와 같은 쿼리를 통해 단일 데이터를 10배 뻥튀기 하는 과정이 필요했습니다. 해당 쿼리는 아래와 같이 변경됩니다. 

MARIADB : 


WITH RECURSIVE a(n) AS (
  SELECT
    UNION ALL 
   SELECT  n+1 
   FROM a
   WHERE n < 10  /*최대 레벨에 해당하는 수치 입력*/
)
SELECT  n, b.* 
FROM  
   a
  ,  임의테이블 b

재귀 호출에 대한 자세한 스펙은 아래 문서를 참조하시면 됩니다. 

간단하게 말하자면 WITH RECURSIVE 뒤편에 들어있는 a(n)
a <--테이블이름 (n) 컬럼이름의 형태로 활용할 수 있으며 해당 리커시브 내에서도 재귀를 사용할 수 있습니다. a(n)은 재귀명(컬럼명1,컬럼명2) 처럼 다중 행과 컬럼을 포함할 수 있는 구조가 됩니다. 


2. 시간에 대한 계산하기 

가. 시간 차 계산 

시간의 차이에 대한 계산은 TIMESTAMPDIFF 함수를 사용합니다. 

ORACLE : 
SELECT  TO_DATE('날자','YYYY-MM-DD') - SYSDATE FROM  DUAL; 
같은 함수를 이용하여 시간은 *24 분은 *24*60 초는 *24*60*60을 해서 구했던 것 과 다릅니다. MARIADB 쪽이 조금 더 명시성이 확보되어 좋다는 생각이 듭니다. 

MARIADB : 
SELECT  TIMESTAMPDIFF(SECOND, '시작일자', '종료일자') ; 
위와 같은 구문을 이용하면 두 날짜 차이의 초단위 차를 계산을 수행해줍니다. 
참고로 SECOND는 YEARMONTH, DAYHOUR, MINUTE 등으로 변경하여 해당 단위에 대한 차를 구할 수 있습니다. 

나. 시간의 증감 계산 

TIMESTAMPADD 함수를 통해 시간에 대한 증가와 감소를 계산할 수 있습니다. 

사용문법은 이렇습니다. 
SELECT  TIMESTAMPADD (단위, 증감수치, '날짜') 
ex) SELECT  TIMESTAMPADD (SECOND, 60, '2020-01-01 20:11:25') 
단위에 들어갈 수 있는 수치는 위와 동일하게 
YEARMONTHDAYHOURMINUTE, SECOND 입니다. 

3. 프로시저 

저장 프로시저, 실행 프로시저를 만드는 방법은 오라클과 약간 다릅니다. 

가. 저장 프로시저 

ORACLE :
CREATE OR REPLACE PROCEDURE 프로시저명(변수1 IN 타입, ...)
IS 
커서, 변수 선언 
변수명 데이터타입; 
/*예:) DECLARE TMPVAL VARCHAR(10);  */
BEGIN 
수행내용 .. 
       /*변수에 값을 넣을 경우 */
       변수명 := 값; 

       /*루프유형1*/
       FOR 커서명 IN  1..9 
       LOOP  
           처리내용  ; 
       END LOOP
       /*루프유형2*/             
       FOR  커서2 IN (SELECT COL1,COL2 FROM 테이블  ...)
       LOOP  
           INSERT INTO 테이블3
           (커서2.COL1, 커서2.COL2); 
       END LOOP; 
END
 
MARIADB : 
CREATE OR REPLACE PROCEDURE 프로시저명(변수1 IN 타입, ...)
BEGIN 
   DECLARE  변수명 타입; 
   /*예:) DECLARE TMPVAL VARCHAR(10);  */
   /*  위의 변수 선언이 기본 형식이나 임의 값을 사용할 수 있다. */
   /*예 ) SET @tmp = '';  등의 형태로 활용할 경우 변수의 선언이 필요 없음*/ 
   수행내용 .. 
     /*변수에 값을 넣는 경우 */
      SET 변수명 = 값; 
   /*루프유형1*/
       FOR 커서명 IN  1..9 
       DO
           처리내용  ; 
       END FOR; 
       /*루프유형2*/             
       FOR  커서2 IN (SELECT COL1,COL2 FROM 테이블  ...)
       DO
           INSERT INTO 테이블3
           (커서2.COL1, 커서2.COL2); 
       END FOR;     
END 
ORACLE과 큰 차이 없이 사용할 수 있다. 
LOOP와 DO의 차이 정도, 그리고 변수를 임의로 지정할 수 있는 부분, 그리고 변수에 값을 넣는 것이 ORACLE 의 변수 := 값  -> MYSQL SET 변수 = 값; 정도의 차이만 있을 뿐 기본적인 부분이 같다. 

LOOP문 : 
LOOP문에서는 간혹 ORACLE 에서 LOOPEXIT 를 활용하는 부분이 다르다. 
ORACLE : 
LOOP
   수행로직 ;
   EXIT WHEN 탈출조건
END LOOP

MARIADB  : 
REPEAT 
   수행로직 ;
    UNTIL 탈출조건 
END  REPEAT ; 

다. 임의 실행 프로시저 

보편적으로 저장 프로시저와 임의 수행을 위해 (개발, 테스트시) 사용하는 프로시저는 다음과 같은 차이가 있다. 

ORACLE : 
DECLARE  
    변수선언 
BEGIN 
    로직 
END

MARIADB : 
DELIMITER|
   BEGIN NOT ATOMIC
     변수선언
     로직수행 
   END
DELIMITER; 
이 부분 역시 문법 이외에 별 차이가 없다. 
ORACLE에서는 DECLARE  나 BEGIN 만으로 수행 프로시저를 즉시 실행 시킬 수 있는 것과 MARIADB에서는 DELIMITER라는 명령어로 수행하는 것 만 다르다. 다만 ORACLE 프로시저와 MARIADB 프로시저에서는 눈에 띄게 다른 점이 LOOP 문을 활용할 경우 초당 처리 건수의 치이가 난다. ORACLE에서는 프로시저에서 LOOP를 돌려 수천 건의 임의데이터를 생성할 수 있었던 반면 MARIADB는 초당 20건밖에 데이터가 생성되지 않았으며, 아직 원인 규명이 되지 않은 상태다. 

다. 프로시저 만들기 

임의의 기간에 해당하는 데이터를 자동 생성하는 프로시저를 만들 경우 샘플을 만들어보자면 아래와 같다. 

/*테이블 생성 */

CREATE TABLE TMPTBL(
  STIME timestamp
  , ETIME timestamp
  , VALUE int
); 

/*임의 값 생성  현재시간 + 60초 1 +60초 2*/

INSERT INTO TMPTBL
VALUES(NOW()TIMESTAMPADD (SECOND, 60, NOW(), 1)
, (TIMESTAMPADD (SECOND, 60, NOW()), TIMESTAMPADD (SECOND, 60, TIMESTAMPADD (SECOND, 60, NOW())), 2); 


/*기간만큼 데이터를 늘리는 저장 프로시저 생성 * /

CREATE OR REPLACE PROCEDURE testProcedure(in prTime timestamp)  
BEGIN
  for rec IN  (SELECT  STIME, ETIME, VALUE FROM TMPTBL)
  do 
SET @itv = TIMESTAMPDIFF(SECOND, rec.STIME, rec.ETIME); /*기간차를 초로*/
INSERT INTO TMPTBL(STIME, ETIME, VALUE) 
WITH 
RECURSIVE  list(n) 
AS (
SELECT  1
UNION ALL
SELECT  n+1 FROM  list
WHERE n < @itv /*초만큼 LEVEL생성*/
)
SELECT  
 TIMESTAMPADD(SECOND, list.n, rec.STIME) 
TIMESTAMPADD(SECOND, list.n, rec.ETIME)
, rec.VALUE*n 
FROM  list
  END for; 
END;

/*기간만큼 데이터를 늘리는 즉시 수행 프로시저 */

DELIMITER |
BEGIN NOT ATOMIC
for rec IN  (SELECT  STIME, ETIME, VALUE FROM TMPTBL)
  do 
SET @itv = TIMESTAMPDIFF(SECOND, rec.STIME, rec.ETIME); /*기간차를 초로*/
INSERT INTO TMPTBL(STIME, ETIME, VALUE) 
WITH 
RECURSIVE  list(n) 
AS (
SELECT  1
UNION ALL
SELECT  n+1 FROM  list
WHERE n < @itv /*초만큼 LEVEL생성*/
)
SELECT  
 TIMESTAMPADD(SECOND, list.n, rec.STIME) 
TIMESTAMPADD(SECOND, list.n, rec.ETIME)
, rec.VALUE*n 
FROM  list 
  END for; 
END|
DELIMITER ;  

수행결과 




이번은 MYSQL이나 MARIADB에서 CONNECTION BY 구문, 시간계산과 프로시저를 생성하는 방법 , 그리고 PLSQL을 이용한 임의 데이터 생성하는 방법등 여러가지를 한꺼번에 정리해보았습니다. 개인적으로는 연계되어 사용까지가 한쿨이라고 생각하기에 이런 정리 방식이 좋은 것 같네요. 

실무에 조금이라도 도움이 되었으면 좋겠네요. 이상입니다. 

기타 

mariadb 의 실행 프로시저 begin not atomic 프로시저 내에서 여러 테이블을 호출하고 사용할 경우 다수의 트랜잭션이 동시 처리되는 환경에서 dead lock 오류가 발생하는 것을 확인 하였습니다. 또한 동일 프로그램을 spring 환경에서 개별 SQL MAPPER로 분리할 경우 해당 문제가 해결되는 것도 확인하였습니다.