• 분류 전체보기 (512)
    • 개발남노씨(Coding Test) (6)
    • 고농축 백엔드 (17)
    • 재귀함수 DFS 총정리 (1)
    • 프론트엔드 날개달기:Vuejs.React (1)
    • 훈훈한 javascript (5)
    • 렛츠기릿 자바스크립트 (18)
    • 나도코딩 (1)
      • 웹 스크래핑 (1)
    • 프로그래머스(자바스크립트) (41)
      • LV.0(자바스크립트) (41)
    • 프로그래머스(자바) (121)
      • LV.0(자바) (56)
      • LV.1(자바) (41)
      • LV.2(자바) (23)
    • 프로그래머스(파이썬) (127)
      • LV.0(파이썬) (46)
      • LV.1(파이썬) (51)
      • LV.2(파이썬) (30)
    • 임시저장소 (31)
    • 프로젝트 (0)
    • 자바 알고리즘 (13)
      • 알고리즘 직빵 자바 문법 (10)
      • String(문자열) (3)
    • 파이썬 알고리즘 (93)
      • 알고리즘 직빵 파이썬 문법 (20)
      • 알고리즘 백준 (2)
      • 파이썬 알고리즘(사고력기르기) (6)
      • 파이썬 탐색 & 시물레이션 (8)
      • 이분탐색 & 그리디 알고리즘 (10)
      • 스택, 큐, 해쉬, 힙 (10)
      • 완전탐색과 DFS기초 (12)
      • DFS, BFS 활용 (19)
      • 동적계획법 (6)
    • 자바 (27)
      • Java TPC(생각하고, 표현하고, 코딩하고) (17)
      • Java (중요하고, 이해 안 되고, 어려운) (10)
    • 스프링 (5)
      • 스프링 MVC 패턴 2편 (5)
hELLO · Designed By 정상우.
@@#@@

기록용 블로그

고농축 백엔드

고농축 벡엔드 15 - Graphql, Transaction - commit, rollback

2023. 2. 17. 15:56
Graphql 장점

1.여러 개의 endpoint가 단일화 → POST /graphql

2.한번에 여러 API요청 가능

3.원하는 결과만 받을 수 있다.

graphql의 내부적인 에러는 항상 200이다.

다만, type에러는 graphql이 잡아준다.



.create( ) : DB로 저장되는 것이 아니라, 해당 데이터를 가진 객체가 만들어 집니다.

.save( ) : save를 통해 만들어진 객체가 DB에 저장됩니다.

.update( ) : 얼만큼 수정이 이루어졌는가의 대한 결과가 return 되며, DB에 저장도 됩니다.


Postman에서 query날리기
{
    "query": "query { fetchBoards { writer, title, contents} }"
}

 

 

 

 

트랜잭션 - commit과 rollback

작업의 단위 


성공!! 1. PointTransaction 테이블에 충전했다고 1줄 작성한다.

실패!! 2. User 테이블에서 철수 데이터를 가져온다.

        3. 기존 500원에 충전 3000원을 더한 3500원으로 업데이트 한다.



1, 2, 3을 하나로 묶음 → 트랜잭션


서로 다른 Transaction을 부분적으로 처리합니다.

모든 Transaction(1, 2, 3)이 정상적으로 완료되면 Commit 합니다.

만약 Transaction 중 하나라도 비정상적으로 처리되면 rollback을 수행합니다.
=========================================================================

ACID

Atomicity(원자성) : 모두 성공할 거 아니면 다 실패하게 해줘!(데이터 오염은 싫어)

Consistency(일관성) : 동일한 쿼리는 조회할 때 마다 동일해야 한다.

Isolation(격리성): 철수 유저꺼를 처리하는 동안 영희는 기다린다.

Durability(지속성): 한 번 성공했으면 장애가 발생해도 살아있어야 된다. 

==========================================================================

try { 시도하세요  }

catch{ 에러가 나면 이쪽으로 }

finally { 에러와 무관하게 항상 실행 }



queryRunner만이 Transaction과 관련이 있다.
queryRunner를 통해서 저장되어야 commit과 rollback이 가능함 
===========================================

sql명령어

show variables;


set global max_connections = 155;


show status;

show processlist;

kill 48;

 

// pointTransaction.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Connection, Repository } from 'typeorm';
import { User } from '../users/entities/user.entity';
import {
  PointTransaction,
  POINT_TRANSACTION_STATUS_ENUM,
} from './entities/pointTransaction.entity';

@Injectable()
export class PointTransactionService {
  constructor(
    @InjectRepository(PointTransaction)
    private readonly pointTransactionRepository: Repository<PointTransaction>,

    @InjectRepository(User)
    private readonly userRepository: Repository<User>,

    private readonly connection: Connection,
  ) {}

  async create({ impUid, amount, currentUser }) {
    const queryRunner = await this.connection.createQueryRunner();
    await queryRunner.connect();

    // ============== transaction 시작!! ==============
    await queryRunner.startTransaction();
    // ===============================================

    try {
      // 1. pointTransaction 테이블에 거래기록 1줄 생성
      const pointTransaction = this.pointTransactionRepository.create({
        impUid: impUid,
        amount: amount,
        user: currentUser,
        status: POINT_TRANSACTION_STATUS_ENUM.PAYMENT,
      });
      // await this.pointTransactionRepository.save(pointTransaction);
      await queryRunner.manager.save(pointTransaction);

      throw new Error('강제로 에러 발생!!!');

      // 2. 유저의 돈 찾아오기
      const user = await this.userRepository.findOne({ id: currentUser.id });

      //3. 유저의 돈 업데이트
      // await this.userRepository.update(
      //   { id: user.id },
      //   { point: user.point + amount },
      // );
      const updatedUser = await this.userRepository.create({
        ...user,
        point: user.point + amount,
      });
      await queryRunner.manager.save(updatedUser);

      // ============== commit 성공 확정!!! ==============
      await queryRunner.commitTransaction();
      // ===============================================

      // 4. 최종결과 프론트엔드에 돌려주기
      return pointTransaction;
    } catch (error) {
      // ============== rollback 되돌리기!!! ==============
      await queryRunner.rollbackTransaction();
      // ===============================================
    } finally {
      // ============== 연결 해제!!! ==============
      await queryRunner.release(); //연결 해제를 하지 않는 경우 connection이 누적되어 최종적으로는 서버 다운
      // ========================================
    }
  }
}

 

 

저작자표시 비영리 변경금지 (새창열림)

'고농축 백엔드' 카테고리의 다른 글

고농축 벡엔드 14 - 구글 인증 후 구글에서 받은 데이터를 DB에 저장  (0) 2023.02.16
고농축 벡엔드 13 - Google 로그인  (0) 2023.02.14
고농축 벡엔드 12 - RefreshToken + Cookie  (0) 2023.02.13
고농축 벡엔드 11 - AccessToken과 Header의 Authorization// fetchUser()  (0) 2023.02.13
고농축 백엔드 docker-bind★★  (0) 2023.01.31
    '고농축 백엔드' 카테고리의 다른 글
    • 고농축 벡엔드 14 - 구글 인증 후 구글에서 받은 데이터를 DB에 저장
    • 고농축 벡엔드 13 - Google 로그인
    • 고농축 벡엔드 12 - RefreshToken + Cookie
    • 고농축 벡엔드 11 - AccessToken과 Header의 Authorization// fetchUser()
    @@#@@
    @@#@@
    자바, 스프링, 알고리즘, 깃허브, 파이썬

    티스토리툴바