본문 바로가기
배달앱 개발일지

20210708 mysql transaction 이걸 이제 알다니;; (php 5.5이상)

by 우딬 2021. 7. 8.

아니 개발자 1년만에 이걸 알았다니;;

역시 혼자서 일하는건 이런 정보를 습득하는데 엄청난 제약을 받는다는걸 알았다.

진짜 알고 나니 신세계인 것이였던것

 

이게 항상 문제였다. "완료"시 돈 왔다갔다 하는거

달에 2~3건 오류가 있었고 그걸 잡기 위해 많은

에러로그 코드 넣기

UNIQUE KEY 추가 등등 열심히 했으나 오류 로그가 뜨긴 떳다.

 

그러다 이번에 가상계좌 도입하면서 걔네들 코드를 보니 transaction이라는걸 쓰는걸보고

이거다 싶었다.

 

1. Transaction 이란?

말 그대로 거래라는 용어 인데, 

돈이 왔다갔다 할때 중간에 오류가 나서 전체 쿼리가 작동을 안하고,
일부만 작동하고 오류가 나면 진짜 곤란하다.

 

돈을 이체할때도 A > B 로 백만원 보냈는데

오류나서 A돈이 안까지면 ?? 진짜 무서운 일이다.

 

내 쿼리도 항상 그런 위험을 안고 갔었다 ㄷㄷ ㅁㅊ

 

오류가 발생하면 그 오류 전 실행 된 쿼리가 취소 되는 형태이다.

 

2. 예제 

<?php
$mysqli = require_once("conn.php");

if(mysqli_connect_errno($mysqli)){
  echo "Failed to connect to MySQL";
}
/* Tell mysqli to throw an exception if an error occurs */
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);


/* Start transaction */
$mysqli->begin_transaction();

try {
    /* 1번 쿼리 */
    $mysqli->query("UPDATE Rider_money RM SET RM.rider_money = RM.rider_money + '3000' WHERE RM.rider_num='202009070005'");

    /* 2번 쿼리 (무조건 오류)*/

    $mysqli->query("INSERT INTO Rider_money_log(rider_num,rider_log_day,rider_log,rider_money_change,rider_money,order_num)
                        VALUES('202009070005',NOW(),'배달 완료','3000','3000','145172')");

    /* If code reaches this point without errors then commit the data in the database */
    $mysqli->commit();
    echo 'commit';
} catch (mysqli_sql_exception $exception) {
    $mysqli->rollback();
    echo 'rollback';
}

?>

 

공식 홈페이지에 있는 코드이긴한데 

두 개의 코드를 실행하고 에러가 없으면 commit으로 두 쿼리가 적용이 되며,
지금 내 코드는 무조건 오류나는 코드로 오류 나면 rollback 다 취소 되버린다.

이걸로 많은 쿼리를 동시에 넣고 오류 없을때만 적용이 되도록!!

 

3. 몇가지 옵션 공부

 

transaction을 찾아보면 몇가지 옵션을 확인할 수 있다.

 

1. autocommit 

누구는 autocommit = true/false  ;  0/1

이렇게 설정해서 transaction기능을 사용할 수 있다고 한다.

 

이 기능 자동으로 커밋을 시키는 기능으로 우리가 평소에 쿼리 날리면 

바로 적용되는 것 그걸 말한다

 

그래서 그 기능을 죽여 버려서 커밋을 못하게 하고 일정 조건이 맞으면
자동 커밋으로 변경한다는것 같다.

 

옛날 버전에서는 이렇게 해야하는거 같다.

 

2. transaction isolation level

transaction이 발생하면 일단 쿼리가 실행은 되니 그 정보가 당연히 어딘가에 남게된다.

그 때 그 정보를 바로바로 갱신해서 보여주느냐?
아니면 막아놓느냐? 이런 의미로 해석할 수 있다.

 

A > B 로 돈을 이동하면 A는 돈이 빠졌고 B는 돈이 늘었다.

 

그리고 난 다음 해당 로그를 작성하려고한다.

하지만 그 로그가 무조건 오류가 생긴다고 가정하면,

돈은 원래 대로 돌아갈것이다.

 

그런데 그 사이에 누군가 select로 현재 A,B의 금액을 확인하려고 한다.

 

그때 어떤식으로 보여줄것인가?

 

아직 커밋이 안됐으니 이동 전 금액을 보여줄것인가?

아니면 이동 된 돈을 보여줄것인가?

 

무조건 오류가 생긴다면 전자이지만,

오류가 안생긴다면 후자도 나쁘지 않다.

왜? 어짜피 올라갈 돈이니까.

 

그런 프로그램의 설정에 필요한게 isolation level이다.

 

아래 블로그에서 자세히 다뤄놨다.

 

https://jupiny.com/2018/11/30/mysql-transaction-isolation-levels/

 

MySQL의 Transaction Isolation Levels

사실 이 글의 목적은 데이터베이스의 Transaction Isolation Levels에 대해 공부한 내용을 쓰기 위함이었는데, MySQL을 예로 사용하며 여러가지 실습해보며 MySQL에서만 적용되는 몇가지 특성이 있음을 알

jupiny.com

 

나는 READ UNCOMMITTED 내 프로그램에 적합하다고 생각하여 그렇게 설정해 놓았다.

 

3. 테이블 ENGINE

 

아니 ;; 실컷 열심히 만들었는데 rollback이 안되서 보니 이런 문제도 있었네

 

mysql 테이블 별 engine에 따라 transcation을 지원하는 엔진과 지원하지 않는 엔진이 있다.

 

테이블 만들때 이게 뭐지하고 무시했던 거였는데;;

 

engine은 innoDB 만 transcation을 지원한다.

 

그래서 관련 테이블을 전부 변경하였다.

 

설명은 아래 블로그에 

 

http://asuraiv.blogspot.com/2017/07/mysql-storage-engine.html

 

[MySQL] 주요 스토리지 엔진(Storage Engine) 간단 비교

MySQL은 크게 아래의 2가지 구조로 되어 있다. 서버 엔진 : 클라이언트(또는 사용자)가 Query를 요청했을때, Query Parsing과, 스토리지 엔진에 데이터를 요청하는 작업을 수행. 스토리지 엔진 : 물리적

asuraiv.blogspot.com

 

댓글