잠시만 기다려 주세요

     '입만 나불거리고 행동하지 않는 야당을 규탄한다.'
전체검색 :  
이번주 로또 및 연금번호 발생!!   |  HOME   |  여기는?   |  바다물때표   |  알림 (16)  |  여러가지 팁 (1059)  |  추천 및 재미 (156)  |  자료실 (22)  |  
시사, 이슈, 칼럼, 평론, 비평 (613)  |  끄적거림 (136)  |  문예 창작 (716)  |  바람 따라 (75)  |  시나리오 (760)  |  드라마 대본 (248)  |  
살인!


    mariadb, mysql

mariadb, mysql - 동시성, 트랜잭션 문제를 해결하기 위한 MySQL, mariadb 잠금, 락 두가지
이 름 : 바다아이   |   조회수 : 10345         짧은 주소 : https://www.bada-ie.com/su/?261591859913
InnoDB를 사용하면서 동시성(Concurrency)을 고려하지 않고 개발을 하면 큰 문제가 생길 수 있다. 아래에 게임 속 플레이어 간 골드를 넘기는 간단한 로직을 살펴보자.

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'bookworm', '');

try {
    $pdo->beginTransaction();
    foreach ($pdo->query('SELECT gold FROM players WHERE id = 1') as $row) {
        if ($row['gold'] < 1000) {
            echo "Not enough gold.n";
            exit;
        }
    }
    $pdo->query('UPDATE players SET gold = gold - 1000 WHERE id = 1');
    $pdo->query('UPDATE players SET gold = gold + 1000 WHERE id = 2');
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
}

$pdo = null;
?>

 

위 예제 코드는 한 플레이어의 골드를 다른 플레이어에게 주는 로직을 간략하게 한 것이다. 이 코드가 동시에 하나씩 실행되면 문제가 없지만, 그렇지 않은 경우 버그가 발생한다. 우선 한 플레이어의 골드가 옮기려는 1000 골드 이상인지 확인 후 1000 골드를 차감한다. 그 후 받을 플레이어의 골드를 1000 증가시킨 후 트랜잭션을 커밋한다. 만약 커밋이나 롤백을 하기 전에 다른 프로세스가 플레이어 1번의 골드를 조회하는 경우 차감 전의 원래 골드 값을 돌려받아 버그가 생기게 된다.

이를 방지하기 위해서는 InnoDB의 기본 Isolation Level를 변경 할 수 있겠지만, 전체 쿼리 중 동시성을 고려해야 하는 경우가 많지 않다면 간단한 잠금 쿼리를 이용해서 처리 할 수 있다.

InnoDB의 잠금은 두가지로 나눌 수 있다. 하나는 LOCK IN SHARE MODE와 다른 하나는 FOR UPDATE다. 이 둘의 용도는 약간 다르기 때문에 자신의 용도에 따라 신중히 선택을 해야 한다.

LOCK IN SHARE MODE는 SELECT를 한 후에 트랜잭션이 끝날 때까지 해당 ROW 값이 변경되지 않을 것을 보장한다. 바꿔 말하면 해당 ROW를 UPDATE 하거나 DELETE 하려는 쿼리는 잠김 상태가 되어 트랜잭션이 끝날 때까지 대기하게 된다. 하지만, SELECT는 얼마든지 여러 세션이 동시에 수행하는 것이 가능하다.

기존 SELECT 쿼리문 맨 뒤에 LOCK IN SHARE MODE 문장을 추가하는 것만으로 사용이 가능하지만, 트랜잭션이 끝나기 전까지만 유효하므로 auto_commit을 꺼야 한다.


SELECT gold FROM players WHERE id = 1 LOCK IN SHARE MODE;


FOR UPDATE는 SELECT로 가져 온 데이터를 변경을 하려고 할 때 사용한다.


SELECT gold FROM players WHERE id = 1 FOR UPDATE;

 

FOR UPDATE를 SELECT를 가져온 이후로 해당 ROW에 대해 다른 세션의 SELECT, UPDATE, DELETE 등의 쿼리가 모두 잠김 상태가 된다. 즉, FOR UPDATE를 한 세션 외에 다른 세션들은 모두 해당 ROW에 접근을 할 수 없게 되고, 모두 대기 상태가 된다. FOR UPDATE도 LOCK IN SHARE MODE처럼 트랜잭션이 끝나는 시점에서 풀린다. 예로 든 플레이어 간 골드 이전과 같은 경우에 알맞는 잠금이다.

웹 프로그래밍에서는 쓰레드 프로그래밍처럼 세밀히 동시성을 고민 할 필요는 없지만, 웹이 기본적으로 다수 사용자가 동시에 같은 데이터에 접근을 하는 환경이므로 이로 인해 주의가 필요하다. 이 외에 이런 문제를 해결하기 위해 트리거나 저장 프로시저 등을 이용 할 수 있지만, 최근 웹서비스 초기에는 MySQL을 단순 key-value 저장소처럼 사용하다 추후 서비스 성장에 맞춰 noSQL을 도입하는 경우가 종종 보이므로, RDBMS의 기능을 너무 적극적으로 활용하지 않는 것이 낫지 않을까 싶다.


출처 : https://sangheon.com/2013/01/01/2642

| |





      1 page / 2 page
번 호 카테고리 제 목 이름 조회수
33 mariadb, mysql Mysql, mariadb The table '' is full 바다아이 1748
32 mariadb, mysql Mariadb MySQL , mysql mariadb ... , mariadb mysql ... , mariadb , mysql ... 바다아이 1926
31 mariadb, mysql MariaDB , ... 바다아이 2153
30 mariadb, mysql MYSQL Locked , , 바다아이 6324
29 mariadb, mysql MySQL - LOCK , MyISAM , , 바다아이 5013
28 mariadb, mysql mysql Index , 바다아이 7509
27 mariadb, mysql MySQL DB , 바다아이 12450
26 mariadb, mysql mysql, mariadb , , , , left, substring, right, concat 바다아이 10735
25 mariadb, mysql mysql, mariadb DISTINCT GROUP BY 바다아이 10899
24 mariadb, mysql mysql 5.x my.cnf 바다아이 9387
23 mariadb, mysql mysql lock , 바다아이 10203
현재글 mariadb, mysql , MySQL, mariadb , 바다아이 10346
21 mariadb, mysql mysql , , , unixtime 바다아이 13436
20 mariadb, mysql Mysql , Join (Left, Right, Outer, Inner Join) 바다아이 8998
19 mariadb, mysql mariadb, MySQL 17 바다아이 11312
18 mariadb, mysql mysql, mariadb 바다아이 9339
17 mariadb, mysql mysql .. time 바다아이 8894
16 mariadb, mysql Mysql(MariaDB) ? 바다아이 9880
15 mariadb, mysql [MySQL] ,insert 바다아이 10116
14 mariadb, mysql [MySQL] - SQL 바다아이 9641
13 mariadb, mysql MySQL JOIN UPDATE 바다아이 9276
12 mariadb, mysql mysql update 바다아이 9863
11 mariadb, mysql mysql storage engine myisam vs innodb 바다아이 9282
10 mariadb, mysql Mysql Replication Master DB Slave DB 바다아이 9935
9 mariadb, mysql Mysql 바다아이 9053
8 mariadb, mysql MySQL Partition , 바다아이 11612
7 mariadb, mysql MySQL Session() ( ) 바다아이 9711
6 mariadb, mysql mysql ... 바다아이 9110
5 mariadb, mysql UNION (Mysql table ) 바다아이 9284
4 mariadb, mysql mysql 바다아이 8978
| |









Copyright ⓒ 2001.12. bada-ie.com. All rights reserved.
이 사이트는 리눅스에서 firefox 기준으로 작성되었습니다. 기타 브라우저에서는 다르게 보일 수 있습니다.
[ Ubuntu + GoLang + PostgreSQL + Mariadb ]
서버위치 : 오라클 클라우드 춘천  실행시간 : 0.05754
to webmaster... gogo sea. gogo sea.