여러명의 사용자가 동시다발적으로 데이터를 수정하는 경우 발생하는 문제점에 대해서 설명합니다.

 

1.예시

예시1) 상품 판매단가 등록 시

예를 들어 상품관리 페이지에서 관리자Aitem1의 판매단가를 1300원으로 수정하였고,

동시에 관리자Bitem1의 판매단가를 2000원으로 수정하였습니다.

item1의 단가를 1000원이라고 가정하였을 때,

관리자A는 판매이익을 300원으로 책정하여 계산하였고,

관리자B는 판매이익을 1000원이라고 책정하여 계산하였습니다.

이때 판매이익의 갭은 700원이 발생합니다. 

 

2.해결방법

작업순서 : Data 조회 - 작업 - 저장 

Data 저장시 기존 Data 조회한 최종 수정날짜현재 조회한 최종 수정날짜가 일치할 경우 update 하고 불일치할 경우 "Data 재조회 한 후 적용하세요." 라는 메세지를 출력할 수 있도록 합니다.

 

이때 발생하는 문제점이 있습니다.

신규 데이터 입력시 최종 수정날짜 데이터가 null 이므로 insert는 되지않고, 메세지만 출력하는 동작만 발생하여 신규 데이터를 등록할 수 없게 되는 문제점이 발생합니다.

이때 MERGE INTO 구문을 사용하여 해결할 수 있습니다.

key 가 있는 경우 update, key 가 없는 경우 insert 처리하여 기존 데이터 수정 또는 신규데이터 등록을 할 수 있습니다.

 

3.MERGE INTO(Oracle)

MERGE INTO [1.테이블명] -- UPDATE 또는 INSERT 할 테이블명
USING [2.조건 테이블명] -- 같은 테이블을 사용한다면 DUAL 
ON [1과 2의 조건문] -- KEY 일치 여부
WHEN MATCHED THEN -- 일치하는 경우 UPDATE 
WHEN NOT MATCHED THEN -- 일치하지 않는 경우 INSERT

3-1) 사용하는 경우

Key가 이미 할당되어 있는 경우 사용합니다..

 

3-2) 예시 : 달력 스케줄 관리

달력을 보면 스케줄 데이터가 없는 경우에도 날짜를 확인 할 수 있습니다.

달력에는 날짜별 Key가 할당되어 나타나는 형태입니다.

즉, 날짜를 선택(09/06)하여 스케줄을 입력하는 경우 key 값이 '20200906'이 되어 insert가 됩니다.

-- 달력
SELECT ym 
     , MIN(CASE dw WHEN 1 THEN d END) Sun
     , MIN(CASE dw WHEN 2 THEN d END) Mon
     , MIN(CASE dw WHEN 3 THEN d END) Tue
     , MIN(CASE dw WHEN 4 THEN d END) Wed
     , MIN(CASE dw WHEN 5 THEN d END) Thu
     , MIN(CASE dw WHEN 6 THEN d END) Fri
     , MIN(CASE dw WHEN 7 THEN d END) Sat
  FROM (SELECT date_format(dt,'%Y%m') ym
             , Week(dt) w
             , Day(dt) d
             , DayofWeek(dt) dw
          FROM (SELECT CONCAT(y, '0101') + INTERVAL a*100 + b*10 + c DAY dt
                  FROM (SELECT 0 a
                        UNION ALL SELECT 1
                        UNION ALL SELECT 2
                        UNION ALL SELECT 3
                        ) a
                     , (SELECT 0 b
                        UNION ALL SELECT 1
                        UNION ALL SELECT 2
                        UNION ALL SELECT 3
                        UNION ALL SELECT 4
                        UNION ALL SELECT 5
                        UNION ALL SELECT 6
                        UNION ALL SELECT 7
                        UNION ALL SELECT 8
                        UNION ALL SELECT 9
                        ) b
                     , (SELECT 0 c
                        UNION ALL SELECT 1
                        UNION ALL SELECT 2
                        UNION ALL SELECT 3
                        UNION ALL SELECT 4
                        UNION ALL SELECT 5
                        UNION ALL SELECT 6
                        UNION ALL SELECT 7
                        UNION ALL SELECT 8
                        UNION ALL SELECT 9
                        ) c
                     , (SELECT '2020' y) d
                 WHERE a*100 + b*10 + c < DayOfYear(CONCAT(y, '1231'))
                ) a
        ) a
 GROUP BY ym, w
;
-- 스케줄
CREATE TABLE SCHEDULE 
(
	WORK_KEY CHAR(8)
, 	CONTENT VARCHAR(100)
, 	PRIMARY KEY(WORK_KEY)
)

-- TEST DATA 입력
INSERT INTO SCHEDULE
(WORK_KEY, CONTENT)
VALUES('20200906', 'TEST');
-- join
SELECT ym
     , MIN(CASE dw WHEN 1 THEN d END) Sun
     , MIN(CASE dw WHEN 2 THEN d END) Mon
     , MIN(CASE dw WHEN 3 THEN d END) Tue
     , MIN(CASE dw WHEN 4 THEN d END) Wed
     , MIN(CASE dw WHEN 5 THEN d END) Thu
     , MIN(CASE dw WHEN 6 THEN d END) Fri
     , MIN(CASE dw WHEN 7 THEN d END) Sat
     , CONTENT
  FROM (SELECT date_format(dt,'%Y%m') ym
             , Week(dt) w
             , Day(dt) d
             , DayofWeek(dt) dw
             , CONTENT 
          FROM (SELECT CONCAT(y, '0101') + INTERVAL a*100 + b*10 + c DAY dt
                  FROM (SELECT 0 a
                        UNION ALL SELECT 1
                        UNION ALL SELECT 2
                        UNION ALL SELECT 3
                        ) a
                     , (SELECT 0 b
                        UNION ALL SELECT 1
                        UNION ALL SELECT 2
                        UNION ALL SELECT 3
                        UNION ALL SELECT 4
                        UNION ALL SELECT 5
                        UNION ALL SELECT 6
                        UNION ALL SELECT 7
                        UNION ALL SELECT 8
                        UNION ALL SELECT 9
                        ) b
                     , (SELECT 0 c
                        UNION ALL SELECT 1
                        UNION ALL SELECT 2
                        UNION ALL SELECT 3
                        UNION ALL SELECT 4
                        UNION ALL SELECT 5
                        UNION ALL SELECT 6
                        UNION ALL SELECT 7
                        UNION ALL SELECT 8
                        UNION ALL SELECT 9
                        ) c
                     , (SELECT '2020' y) d
                 WHERE a*100 + b*10 + c < DayOfYear(CONCAT(y, '1231'))
                ) a
                LEFT OUTER JOIN SCHEDULE s
        		ON  date_format(s.WORK_KEY, '%Y-%m-%d') = a.dt
        ) a        
 GROUP BY ym, w;

결과

력쿼리 : www.gurubee.net/article/65315

 

3-3) 단점

- 오라클에서만 사용가능합니다. : java에서 처리하거나 대체 SQL 문으로 처리

- 메모리 사용

 

4.MyBatis 사용예제

- MyBatis에서는 update 또는 insert 시 int 값으로 return 할 수 있습니다.

  0일 경우 false, 0 초과인 경우 true를 적용하여 처리할 수 있습니다.

 

- select [컬럼명] from dual 사용 : 조건에 맞는 데이터만 select 하여 insert 하는 경우, java에서 조건처리하는 로직이 복잡할때 쿼리에서 간단하게 해결할 수 있습니다.

 

5.주의할점

업무 프로세스 계획을 잘 세워서 각 상황에 맞게 service 에서 처리할 지 SQL 로 처리할 지 판단해서 적용해야 합니다.

 

728x90

'Development' 카테고리의 다른 글

[Development] 프로그램 개발 순서  (0) 2020.08.30

프로그램 계획시 아래와 같은 순서대로 계획하면 개발할 때 좀 더 편합니다.

var num; // 전역변수
$(document).ready(function() { // onload
    $('#btn-test').on('click', test); // 이벤트 바인딩 된 함수
    init();
});

function init() { // 전역함수
    num = []; // 초기화
}

function test() { // 전역함수
    console.log('test');
}

1.전역실행 (변수, 함수) : 선언부

화면이 그려지는 경우 참조되는 것이 없는 변수 또는 함수를 선언해야 합니다. 

화면이 그려지기도 전에 참조하는 경우 undefined가 나올 수가 있습니다.

즉, 화면과 관련성이 없어야 합니다.

주의점 : 초기화하기 전 전역변수 사용하는 경우, 즉 변수가 할당되지 않은 상태에서 자료형 method를 사용하려고 할 때 undefined error 가 발생합니다.

 

2.onload : 화면이 호출된 이후 사용하는 경우

1)자주 재사용되는지 고려해야 합니다.

  자주 재사용되는 경우 전역함수(공통) 또는 사용자 함수로 선언하여 사용하는 경우가 많습니다.

  여러 함수에서 호출하는 함수들은 전역함수로 선언하여 사용합니다.

2)공통코드를 호출합니다.

- 공통코드는 한번 호출 하면 세팅이 완료되므로 재호출 되는 경우가 거의 없습니다.

3)이벤트 바인딩 된 함수를 사용합니다.

4)초기화 함수를 호출합니다. 

- 첫 화면 로드 시 초기화되면서 설정값들이 없는 상태에서 초기값으로 설정하기 위해 사용합니다.

 

3.초기화 (init)

1) Empty : 값을 완전히 지우는 경우

2) 초기 세팅(reset) : 최초 값으로 보여지는 경우

3) clear 

3-1) 전체 clear : 전체 값 비우기

3-2) 부분 clear : 부분 값 비우기

 

4.이벤트 (이벤트 바인딩 된 함수)

- 조회, 저장, 삭제, 수정, 엑셀, 그리드, 버튼, 데이터...

 

5.Utill (사용자 함수)

 

6.callback (콜백함수) : 서버에서 데이터 요청 후 처리하는 함수

 

 

 

728x90

'Development' 카테고리의 다른 글

[Development] Data 동시성 적용  (0) 2020.09.06

+ Recent posts