SSISO Community

시소당

MySQL 트랜잭션 Isolation Level로 인한 장애 사전 예방 법

Overview

MySQL에서 전체 데이터를 Scan 하는 쿼리를 질의하여 서비스에 큰 영향이 발생할 수 있습니다.

InnoDB 스토리지 엔진의 기본 Isolation Level이 REPEATABLE-READ이기 때문에 발생하는 현상인데, 이것은 세션 변수 일부를 변경하여 문제를 사전에 해결할 수 있습니다.

얼마 전 이와 비슷한 장애가 발생하여 원인 분석 및 해결 방안을 포스팅합니다.

Symptoms

Transaction Isolation Level이 REPEATABLE-READ(MySQL Default) 상태에서 Insert into Select 혹은 Create Table As Select 로 전체 테이블 참조 쿼리 실행 시 참조 테이블에 데이터 변경 작업이 “대기” 상태에 빠지는 현상이 있습니다.

mysql> show variables like 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)

Insert Into Select

세션1

mysql> insert into activity_test_stat2
    -> select
    ->     act_type,
    ->     to_uid,
    ->     act_time,
    ->     to_user_name,
    ->     before_user_name,
    ->     count(*) cnt
    -> from activity_test
    -> group by act_type, to_uid, act_time,
    ->     to_user_name, before_user_name;

세션2 – 테이블에 데이터 변경

mysql> update activity_test set ACT_TYPE = 105 limit 10;

세션3 – update SQL는 “Updating” 상태

mysql> show processlist\G
************************* 1. row *************************
     Id: 255867
   User: root
   Host: localhost
     db: snsfeed
Command: Query
   Time: 1
  State: Updating
   Info: update activity_test set ACT_TYPE = 105 limit 10
************************* 2. row *************************
     Id: 255962
   User: root
   Host: localhost
     db: snsfeed
Command: Query
   Time: 2
  State: Copying to tmp table
   Info: insert into activity_test_stat2 select act_type,

Delete 작업 시 Update와 같이 대기 현상 또는 Dead Lock 오류 발생합니다.

mysql> delete from activity_test limit 10;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

Create Table As Select

세션1

mysql> create table activity_test_stat as
    -> select
    ->     act_type,
    ->     to_uid,
    ->     act_time,
    ->     to_user_name,
    ->     before_user_name,
    ->     count(*) cnt
    -> from activity_test
    -> group by act_type, to_uid, act_time,
    ->     to_user_name, before_user_name;

세션2 – 테이블에 데이터 변경

mysql> update activity_test set ACT_TYPE = 105 limit 10;

세션3 – update SQL는 “Updating” 상태

mysql> show processlist\G
************************* 1. row *************************
     Id: 255867
   User: root
   Host: localhost
     db: snsfeed
Command: Query
   Time: 2
  State: Updating
   Info: update activity_test set ACT_TYPE = 105 limit 10
************************* 2. row *************************
     Id: 255962
   User: root
   Host: localhost
     db: snsfeed
Command: Query
   Time: 4
  State: Copying to tmp table
   Info: create table activity_test_stat as select act_type,

Delete 작업 시 Update와 같이 대기 현상 또는 Dead Lock 오류 발생합니다.

mysql> delete from activity_test limit 10;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

Cause

MySQL InnoDB 스토리지 엔진의 기본 Isolation Level이 REPEATABLE-READ로 설정되어 있기 때문에 발생합니다.

REPEATABLE-READ에서는 현재 Select 버전을 보장하기 위해 Snapshot을 이용하는데, 이 경우 해당 데이터에 관해서 암묵적으로 Lock과 비슷한 효과가 나타납니다.

즉, Select 작업이 종료될 때까지 해당 데이터 변경 작업이 불가합니다.

Transaction Isolation Level

  • READ UNCOMMITTED
    다른 트랜잭션이 Commit 전 상태를 볼 수 있음
    Binary Log가 자동으로 Row Based로 기록됨 (Statement설정 불가, Mixed 설정 시 자동 변환)
  • READ-COMMITTED
    Commit된 내역을 읽을 수 있는 상태로, 트랜잭션이 다르더라도 특정 타 트랜잭션이 Commit을 수행하면 해당 데이터를 Read할 수 있음
    Binary Log가 자동으로 Row Based로 기록됨 (Statement설정 불가, Mixed 설정 시 자동 변환)
  • REPEATABLE READ
    MySQL InnoDB 스토리지 엔진의 Default Isolation Level
    Select 시 현재 데이터 버전의 Snapshot을 만들고, 그 Snapshot으로부터 데이터를 조회
    동일 트랜잭션 내에서 데이터 일관성을 보장하고 데이터를 다시 읽기 위해서는 트랜잭션을 다시 시작해야 함
  • SERIALIZABLE
    가장 높은 Isolation Level로 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸림
    다른 트랜잭션에서는 해당 영역에 관한 데이터 변경 뿐만 아니라 입력도 불가

Isolation Level에 관한 자세한 정보는 하단 MySQL 매뉴얼을 참조하세요.
http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html

Solution

Insert into Select 경우 Isolation Level을 READ-COMMITED나 READ-UNCOMMITED로 변경하여 해결할 수 있습니다.
다음과 같이 세션 설정을 변경 후 Create Table As Select, Insert into Select를 수행하면 문제가 없습니다.

mysql> set tx_isolation = 'READ-COMMITTED';

설정 파일에 영구적으로 transaction isolation 변경 적용하고자 한다면 다음과 같이 설정 후 DB를 재시작 합니다.

$ vi /etc/my.cnf
## [mysqld] 설정에 추가
transaction-isolation           = READ-COMMITTED

비슷한 설정으로 다음과 같이 Isolation을 변경할 수 있습니다.

mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

모든 것은 Isolation Level이 REPEATABLE READ 이상인 경우 발생하오니, 주의하여 사용하시기 바랍니다.

(설정 자체가 READ COMMITTED에서는 발생하지 않음)

※ 주의사항 ※
커넥션 풀을 사용하는 경우 변경된 세션 값은 해당 커넥션이 재 시작되기 전까지 유지되므로, 반드시 사용 후 원래 설정 값으로 돌려놓아야 합니다.

Conclusion

조금은 어려운 주제일 수 있습니다. 그러나 유독 MySQL에만 국한되는 내용이 아닌, 트랜잭션을 지원하는 DB 사용 시 반드시 알아야할 사항이라고 생각됩니다.

그러나 MySQL 에만 국한되는 내용이 아닐 뿐더러, 대용량 분석 시스템을 구상 중이라면 반드시 알아야할 사항이라고 생각합니다.^^

0 view

4.0 stars

시소당

GLSL 셰이더 형식한정자, 정밀한정자

http://dalbom.tistory.com/category/OpenGL%20ES

 

형식 한정자

 

Uniform 

  Application에서 OpenGL ES API를 통해 Shader로 전달 되는 읽기 전용 값을 저장하는 변수.

Uniform 변수는 Vertex Shader와 Fragment Shader에서 공유되며 주로 Matrix, Lighting Parameter, Color 등의 값을 저장하는데 사용된다.

 

Attribute

  Vertex Shader에서만 사용가능한 타입으로 Vertex 각각의 정보를 전달하기 위해 사용된다.

일반적으로 Position, Normal, Texture Coordinate, Color 등의 정보가 전달된다.

 

Varying

  Vertex Shader의 Output이자 Fragment Shader의 Input 으로 사용될 변수를 지정하는 데 사용된다.

Application 쪽에선 건드릴 수 없는 변수이므로 관련 API 또한 존재하지 않는다.

 

http://blog.naver.com/mssixx?Redirect=Log&logNo=150161814632

 

정밀 한정자

 

highp - full 32 비트의 부동소수 포맷입니다. 정점변환에 적합하지만 가장 느립니다.

mediump - 16 비트의 부동소수 포맷입니다. 질감 UV 좌표에 적합합니다. 대략 highp보다 2배 빠릅니다.

lowp - 10비트의 부동소수 포맷입니다. 색상과 빛 연산, 그리고 고성능 연산에 적합합니다. highp보다는 4배 정도 빠릅니다.

 

GLSL에서 사용되는 변수와 C언어에서 사용되는 변수의 가증 큰 차이점은 변수가 담을 수 있는 데이터 크기를 정하는 부분입니다.

C언어에서는 정의된 변수 타입에 고정적으로 데이터 크기가 정의 되어있지만, GLSL 변수는 필요에 의해 똑같은 변수 타입이라도 서로 다른 데이터 사이즈를 가질 수 있습니다.

이를 통해 정확한 정보가 필요할 때 연산량이 많은 highp 정밀 한정자를 이용하고 높은 속도를 필요로 할 때 lowp를 이용하여 정확한 데이터를 얻을 수 없지만 높은 속도를 보장 받을 수 있습니다.

987 view

4.0 stars

시소당

OpenGL:: varying, in, out, uniform qualifier

여러 가지 종류의 한정자가 있는데 각각의 차이를 잘 모르겠어서
알아보는 시간을 가지고자...



Vertex shader, Fragment shader와 코드가 있을 때,
varying을 사용하면 Vertex shader와 Fragment shader에서 그 값이 공유된다.
Vertex shader에서 Fragment shader로 데이터를 넘길 때 사용한다.

Ex.

//Vertex shader 
#version 130 
varying vec3 v_color; 
void main(){ 
 v_color = (1.01.01.0); 
}

//Fragment shader 
#version 130 
varying vec3 v_color; 
void main(){ 
 gl_FragColor = vec4(v_color, 1.0); 
}

+) gl_FragColor는 vec4(1.0, 1.0, 1.0, 1.0)을 가지게 된다.




inout은 인풋의 역할을 하는 오른쪽 변수에게 in,
아웃풋의 역할을 하는 왼쪽 변수에게 out을 선언한다고 생각하면 될 거 같다.
역할은 varying과 같다.
Vertex shader에서 사용한 out을 Fragment shader에서 in으로 접근할 수 있다.

Ex.

//Vertex shader 
#version 130 
in vec4 a_position; 
in vec3 a_color; 
out vec3 v_color; //pass!
void main() { 
 v_color = a_color; 
 gl_Position = a_position; 
}


//Fragment shader 
#version 130 
in vec3 v_color; //access!
void main() { 
 gl_FragColor = vec4(v_color, 1.0); 
}

+) gl_Position이나 gl_FragColor 등의 global 변수는 out을 사용하면 중복 선언이다.



uniform 한정자도 varying과 같이 vertex shader와 fragment shader 사이의 정보를 공유하게 해준다. 하지만 항상 같아야하는(uniform) read-only 변수로, shader 내에서 정의되거나 값이 변할 수 없다. uniform으로 전달되는 예로는 매질, 광원, 시간 변수 등이 있다.

66 view

4.0 stars