All posts filed under “개발

comment 0

A Successful Git Branching Model (번역)

원문 : http://nvie.com/posts/a-successful-git-branching-model/

잘 하지도 못하는 영어로 낑낑대며 번역을 한번 해보았습니다. 잘못된 부분이나 오역이 있으면 주저하지 말고 댓글 달아주세요.
그리고 중간 중간 이해가 안가는 부분도 있었는데 설명해주시면 정말 감사하겠습니다^^

A Successful Git Branching Model

이 포스트에서 저는 1년전 저의 모든 프로젝트(직장, 개인적인 프로젝트 둘다)에 소개했고 성공적이었다고 드러난 개발 모델을 제시하겠습니다. 저는 이 프로젝트들에 대해 써보려고 했으나, 지금까지 완벽히 쓸 시간이 없었네요. 저는 이 프로젝트에 대한 디테일은 설명하지 않고, 단지 브랜칭 전략과 배포 관리에 대해서만 이야기 하겠습니다.

Git Branching Model

Why Git?

중앙집중 소스코드 관리 시스템과 비교하여 Git 이 가지는 단점과 장점을 심도있게 토론한 내용을 보려면, 이 페이지[]를 확인하세요. 여기에선 아주 뜨거운 논쟁이 오갔습니다. 개발자로써, 저는 오늘날 존재하는 다른 형상관리 시스템 중 Git 을 선호합니다. Git 은 머징과 브랜칭에 대한 개발자의 관념을 통째로 바꿔놨습니다. CVS나 Subversion 과 같은 오래된 형상관리시스템에서 저는 merging 과 branching 은 할때마다 무서웠고 (“merge conflict 를 조심하세요!, 이것들이 당신 발목을 잡을꺼에요”) 아주 가끔씩만 하는걸로 알고 있었어요.

하지만 Git 을 쓰면, 이러한 액션들은 매우 비용이 적게 들고 단순하며, 이러한 것들(merging 과 branching)은 당신의 일상업무에 매우 중요한 부분으로 자리잡을 것입니다. 예를들면, CVS/Subversion을 다룬 책들에서는, branching 과 merging 은 후반부의 챕터(그것도 고급 유저를 위해)에서나 다루어지지만, 모든 Git 관련 서적에서는 한 3장쯤에 매우 빨리 나옵니다.

결과적으로 이 단순함과 자연스러운 반복때문에 branching 과 merging 은 더이상 두려워 할 것이 아니게됩니다. 형상관리도구는 다른 기능들보다도 branching과 merging 을 쉽게 할 수 있어야 합니다.

툴에 대해서는 이것으로 됐고, 개발모델을 봅시다. 제가 여기서 소개하려고 하는 모델은 올바르게 관리되는 소프트웨어 개발 과정을 위해 모든 팀 구성원이 따라야 하는 과정의 집합에 지나지 않습니다.

Decentralized but centralized

우리가 사용하고 이 브랜칭 모델에 잘 맞는 저장소 설정은 중앙의 ‘truth’ repo 입니다. 이 저장소는 오직 하나의 중앙 저장소이여야 한다는 것을 기억하세요. (Git 은 DVCS(Decentralized Version Control System) 이므로 기술적인 측면에서 중앙저장소는 없습니다.). 우리는 이 저장소를 모든 Git 유저에게 익숙한 origin 이라고 하겠습니다.

centralized-decentralized

각 개발자는 origin 을 pull 또는 push 합니다. 하지만 중앙집중식 push-pull 관계는 논외로 하고서라도, 각각의 개발자들은 다른 동료의 변경내역을 pull 해서 sub team 을 만들 수도 있습니다. (잘 모르겠네요;;)But besides the centralized push-pull relationships, each developer may also pull changes from other peers to form sub teams. 예를들면, 두명 이상의 개발자들이 하나의 상당히 큰 새로운 기능을 구현하기 위해 같이 일할때, 아직 완성되지 않은 진행중인 작업내역을 origin에 push 하기 전에는 유용합니다. 위의 그림을 보면, Alice 와 Bob 팀, Alice 와 David, Clair 와 David 로 이루어지는 sub팀이 있습니다.

기술적으로, 이것은 Alice 가 Git remote 저장소 이릅을 bob 으로 짓고, Bob의 저장소를 가르키고 있는 것 뿐이고, 그 반대도 마찬가지입니다.

The main branches

Main Branch

이 개발 모델은 이미 존재하는 모델로부터 떠올렸습니다. 중앙 저장소는 두개의 없어지지 않는(infinite lifetime을 갖는) 메인 브랜치를 가지고 있습니다 :

  • master
  • develop

master 브랜치의 orgin 은 Git 유저들에게 익숙할 것 입니다. master 브랜치와 병렬로 develop 이라는 브랜치가 존재합니다.

orgin/master 는 항상 실서비스에 나갈 수 있는(production-ready) 상태인 HEAD 소스코드를 가지고 있는 메인 브랜치입니다.

origin/develop은 다음 배포를 위해 마지막으로 수정된 사항이 있는 HEAD 소스코드를 가지고 있는 메인브랜치 입니다. 어떤 사람들은 이것을 “integration branch” 라고 부르지요. 이것(origin/develop)은 매일 발생하는 소프트웨어에 대한 수정사항을 포함하고 있는 소프트웨어 배포버전(nighly build) 가 build 되는 곳입니다.

develop 브랜치에 있는 소스코드가 안정적인 시점에 도달하여 배포할 준비가 되면, 모든 변경사항들은 master로 merge되어야 하고 그때 배포번호(release number)로 tag 를 매깁니다. 이것이 어떤식으로 이루어지는지는 계속해서 이야기 할것입니다.

그러므로, 변경사항들이 master로 머지될때마다, 이것은 하나의 실서비스 배포 인 것입니다. (변경사항들이 master로 머지될 때를, 실서비스 배포로 정의한다) 이론적인 이 사항을 엄격히 적용하기 위해서, 우리는 master 에 커밋이 발생할때마다 자동으로 빌드하고 production server 에 자동으로 배포하는 Git 의 hook script 를 사용할 수 있습니다.

Supporting branches

masterdevelop 브랜치에 이어, 우리의 개발모델은 팀 구성원 간에 병렬적인 개발, 기능들에 대한 쉬운 트래킹, production 배포 준비, 그리고 현재 서비스되고 있는 실서비스에 생긴 문제를 빠르게 고칠 수 있도록 도움을 주기 위해 다른 supporting 브랜치들을 사용합니다.

우리가 사용할 이 브랜치들의 종류는 다음과 같습니다.

  • Feature branches
  • Release branches
  • Hotfix branches

이 각각의 브랜치들은 특정한 목적을 가지고 있고 어떤 브랜치들은 이 브랜치들의 originating 브랜치가 될 수도 있고 어떤 브랜치는 반드시 이 브랜치의 merge target 이 되어야 하기 때문에 엄격한 규칙에 묶여 있습니다. 이것들에 대해서는 곧 살펴보도록 하죠.

이 브랜치들을 기술적 관점에서 결코 “특별한” 것들이 아닙니다. 브랜치 타입은 우리가 어떻게 사용 하느냐에 따라 분류되는 것이고 이것들을 단순한 Git 브랜치일 뿐입니다.

Feature branches

  • May branch off from: develop
  • Must merge back into : develop
  • Branch naming convention : master, develop, release-*, hotfix-* 를 제외한 이름

Feature Branches

Feature 브랜치(아니면 때때로 topic 브랜치라고 불리는)는 추후 배포를 위하여 새롭게 추가되는 기능을 개발할때 사용됩니다. 하나의 feature의 개발을 시작할때는 이 feature 가 합쳐질 target release 가 무엇인지 모릅니다. feature 브랜치의 핵심은 그 기능이 개발 중에는 계속해서 존재하지만, 결국에는 develop 브랜치에 merge 되거나(그 기능이 다음 배포에 확실히 추가될것이라면) 제거(그 기능을 개발해놓고 테스트 해보니 기대에 못미칠 경우)된다는 것입니다.

Feature 브랜치는 기본적으로 developer 의 저장소에만 존재하며, origin 에는 존재하지 않습니다. (즉 로컬저장소에만 존재하는 브랜치이며, 리모트에는 존재하는 경우가 없다는 말!)

Creating a feature branch

새로운 feature 에 대한 개발을 시작할때는, develop브랜치에서 브랜치를 땁니다.

$ git checkout -b myfeature develop
> Switched to a new branch "myfeature"

Incorporating a finished feature on develop

완료된 feature 들은 develop브랜치로 merge하고 다음 배포에 확실히 반영합니다.

$ git checkout develop
Switched to branch 'develop`
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

--no–ff 플래그는 merge 작업이 fast-forward 로 동작할지라도 항상 새로운 커밋객체를 만들도록 합니다. 이것은 예전에 존재했던 feature branch 가 정보를 잃지 않게 해주며 feature branch 에 커밋됐던 모든 내용을 하나로 묶어 줍니다.
비교 :
Merge without Fast Forward

위 그림에서 오른쪽 그림의 경우(In the latter case), 커밋 객체들이 함께 기능을 구현했기 때문에 git 의 history 를 볼 수가 없습니다. 일일이 하나씩 모든 로그메시지를 봐야하죠. 오른쪽 그림과 같은 상황에서 merge했던 feature(i.e. group of commits) 을 원복시키려면 이건 정말 골치 아픈 일입니다. 하지만 –no-ff flag 와 함께 merge 됐던 왼쪽 그림과 같은 경우에는 쉽게 원복 시킬 수 있죠.

네, 이것은 몇몇 (텅빈) commit object들을 생성할 수 있습니다, 하지만 실보단 득이 훨씬 더 크죠.

안타깝게도 저는 –no-ff 를 git merge 의 기본값으로 바꾸는 방법을 찾지 못했네요. 하지만 git merge 는 정말 –no-ff 와 함께 쓰여야 합니다.

Release branches

  • May branch off from: develop
  • Must merge back into : develop 과 master
  • Branch naming convention : release-*

Release branch 들은 새로운 production 릴리즈를 준비하는데 도움을 줍니다. Relase branch 들은 마지막순간에 실수를 저지르지 않도록 도와줍니다. 게다가, 릴리즈를 위한 자잘한 버그의 수정이나 메타데이터(version number, build dates, etc)를 준비하는 것을 가능하게 해줍니다. 이러한 것들을 release branch 에서 수행함으로써, develop 브랜치는 다음번의 큰 릴리즈를 위한 기능들을 받아들이기가 매우 용이해집니다.

develop 브랜치로부터 새로운 브랜치를 따는 결정적인 순간은 새로운 릴리즈를 위해 개발하던 것이 안정적인 상태에 도달 했을 때입니다. build될 release(release-to-be-built)를 위한 모든 기능들은 이시점에 develop 브랜치로 반드시 적절한 시기에 merge 되어야 합니다. future 릴리즈에 반영될 기능들은 develop 브랜치로 merge 되면 안됩니다. 이것들은 새로운 릴리즈 브랜치가 새롭게 브랜치가 따질때까지 기다려야 합니다.

이것은 정확히 버전번호를 부여받는 다음 배포를 위한 release branch 가 시작될 순간입니다. 그때까지는, develop branch 가 “next release”를 위한 변경사항들을 반영하지만, release branch 가 시작되기 전까지는 이 “next release”가 확실히 0.3버전 이나 1.0 버전이 될지는 알 수 없습니다. 이러한 결정은 release branch 의 시작에서 이루어지며 버전 번호를 매기는 프로젝트 룰에 따릅니다. (이 문단은 이해가 잘 안가네요. 밑에 원문을 달아둡니다.)

It is exactly at the start of a release branch that the upcoming release gets assigned a version number—not any earlier. Up until that moment, the develop branch reflected changes for the “next release”, but it is unclear whether that “next release” will eventually become 0.3 or 1.0, until the release branch is started. That decision is made on the start of the release branch and is carried out by the project’s rules on version number bumping.

Creating a release branch

Release branch들은 develop branch 로부터 만들어집니다. 예를 들면, 버전 1.1.5가 현재의 production release 버전이고 우리는 큰 release 를 앞두고 있습니다. develop의 상태는 “next release”를 위한 준비가 되어 있고 우리는 이것이 버전 1.2로 하기로 결정(1.1.6이나 2.0으로 하지않고) 했습니다. 그래서 우리는 브랜치를 따고 새로운 버전번호를 반영하는 이름을 release branch에 주었습니다.

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

새로운 브랜치를 만든 후에 그걸로 전환하고, 우리는 그 버전번호로 bump 합니다. 여기에서, bumt-version.sh는 working copy 의 파일들에 새로운 버전을 반영시키는 (가상의) 쉘 스크립트 입니다. (이것은 물론 일일히 손으로 바꿀 수 있습니다.–the point being that some files change.) 그다음에, bumped 버전번호는 commit 됩니다.

이 새로운 브랜치는 그 release 가 확실히 출시될때까지 한동안 존재할 수 있습니다. 그 동안에, 버그픽스들이 이 브랜치(release branch)에 반영될 수 있습니다. (develop 브랜치에 하는게 아니고). 여기에 크나큰 새로운 기능을 추가하는것은 엄격히 금지됩니다. 이런 큰 기능들은 반드시 develop 브랜치에 merge되어야 하므로 다음 big release 까지 기다립니다.

Finishing a release branch

release branch 가 real release 할 상태가 되면, 몇가지 작업이 수행되어야 합니다. 첫째, 이 release branch는 master로 merge 되어야 합니다. (master의 모든 커밋은 새로운 release 가 된다는 정의를 기억하세요). 그 다음, master에 커밋된 것은 나중에 쉽게 참조되기 위해 반드시 tag 되어야 합니다. 마지막으로, release branch 에 생긴 버그fix들은 미래의 release 에도 포함되도어야 하므로 develop 브랜치로 머지합니다.

The first two steps in Git:

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2

이 release 는 이제 끝나고, 나중에 참조하기 위해 태그도 만들었습니다.
Edit : -s or -u 플래그를 써서 태그를 암호화할 수도 있습니다.

release branch 의 변경내역들을 보존하기 위해서, develop으로 머지해야 합니다.
In Git:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

여기서 merge 를 하는 동안 conflict 가 날 수도 있습니다. (아마도 버전넘버를 바꿔서..) 만약 그렇다면 고치고 커밋하세요.

이제 정말 끝났고 release branch는 더이상 필요 없으니 제거해도 됩니다.

$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).

Hotfix branches

  • May branch off from : master
  • Must merge back into : develop and master
  • Branch naming convention : hotfix-*

Hotfix Branches

Hotfix 브랜치들은 계획되지 않았던 것만 빼고 새로운 production release 를 위한 것이라는 점에서 release 브랜치와 닮았습니다. 이 hotfix 브랜치들은 실서비스 중인 production 버전의 의도치 않은 상태에 즉각적으로 대응하기 위해 만들어졌습니다. production 버전에서 심각한 버그가 발견되어 즉각적으로 고쳐야 할때, hotfix 브랜치들은 해당 버그가 존재하는 master 브랜치에서 브랜치를 따서 만들어집니다.

이 hotfix branch 의 핵심은 한 사람이 production 을 고치고 있을때 다른 팀 구성원들이 지속적으로 일을 할 수 있다는 점입니다.

Create the hotfix branch

hotfix 브랜치들은 master브랜치로부터 만들어집니다. 예를 들면, version 1.2 가 현재 실서비스중인 production release 인데 심각한 버그가 문제를 일으키고 있다고 합시다. 그러나 develop 브랜치의 변경내역들은 아직 안정적이지 못합니다. 우리는 그때 (master브랜치로부터) hotfix 브랜치를 따서 문제를 고칠 수 있습니다.

$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)

브랜치를 딴 다음에 버전번호를 bump 하는 것을 잊지 맙시다!

그러면, 버그를 고치고 이 내용을 하나나 여러개의 분리된 커밋으로 commit 합니다.

$ git commit -m "Fixed severe production problem"
[hotfix-1.2.1 abbe5d6] Fixed severe production problem
5 files changed, 32 insertions(+), 17 deletions(-)

Finishing a hotfix branch

버그픽스를 모두 마쳤으면, 이 버그픽스는 master브랜치로 다시 머지되어고, 또한! 다음번 release 에도 반영될 수 있도록 develop브랜치로도 머지되어야 합니다. 이것은 완벽히 release 브랜치가 끝났을때랑 비슷한 작업입니다.

첫째, master에 머지하고 태그를 땁니다.

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2.1

Edit : -s or -u 플래그를 써서 태그를 암호화할 수도 있습니다.

다음으로, 버그픽스를 develop에도 반영합니다.

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)

이 규칙에 대해서 한가지 예외는 release branch 가 현재 존재할때는, hotfix change 들은 develop branch 가 아닌 그 release branch 에 merge 되어야 한다는 것입니다. 버그픽스를 release 브랜치에 backmerging 하는것은 결과적으로 release 브랜치가 끝날때 버그픽스들이 develop에 머지 될 것입니다. (만약 develop의 작업들이 이 버그픽스를 즉각적으로 반영되어야하고 release 브랜치가 finish 될때까지 기다릴 수 없다면, 당신이 버그픽스를 안적하게 develop으로 머지할 수 있습니다.)

마지막으로, 이 임시 브랜치(hotfix 브랜치)를 제거합니다.

$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbe5d6).

Summary

지금까지 살펴본 이 branching model 이 딱히 놀랍거나 특별해보이지 않을지 몰라도, 이 포스트의 처음 부분에 첨부된 “큰 그림”은 우리의 프로젝트에서 정말 엄청나게 유용했었습니다. 이것은 이해하기 쉬운 우아한 mental model(?)을 만들어주었고 팀구성원들이 모두가 branching과 releasing process에 대해 동일한 수준의 이해를 할 수 있도록 해주었습니다.

high-quality PDF 버전이 여기 있습니다. 가서 벽에 붙여놓고 언제나 참조하세요.

Update : 그리고 요청한 사람들을 위해: 여기 gitflow-model.src.key 메인 다이어그램 이미지 입니다.

comment 0

페이스북 페이지 앱 추가 방법

페이스북은 페이지에 앱을 추가 할 수 있다.
그런데 예전에는 페이지 관리 탭에서 앱을 추가 할 수 있었던 것 같은데 그 기능이 사라져 버렸다.
그래서 어떻게 해야하나 한참 찾다가 방법을 알아냈다.

주소창에 다음 url 을 적어준다.

http://www.facebook.com/add.php?api_key=XXXXXXXXX&pages

XXXXXXXXX 부분에 추가하고자 하는 앱 ID 이다.
그럼 다음과 같은 화면이 나온다.

위 화면에서 콤보 박스를 누르면 자신이 좋아요 한 페이지들이 나타나는데, 앱을 추가하고자 하는 페이지를 선택하면 된다.

comment 1

데이터베이스 Isolation Level

Isolation Level 의 필요성

데이터베이스의 무엇보도 중요한 기능은 데이터를 정확하고 안전하게 저장하며 데이터의 변경이나 수정시 제한을 두어 안정성을 저해하는 요소를 막아 데이터 상태들을 항상 옳게 유지하는 것을 의미한다. 즉, 흔히 말하는 무결성을 보장하는 것이다.

데이터의 무결성 보장과 관련된 트랜잭션의 ACID 보장이라고 할 수 있다.

ACID는 Atomicity, Consistency, Isolation, Durability의 약자인데 트랜잭션 보장을 위해 갖추어야 할 속성들을 나타낸다. 이를 위해서는 DB는 ACID가 의미하는 바와 같이 트랜잭션이 원자적이면서도 독립적인 수행을 하도록해야 한다. 그래서 등장하는 개념이 Locking 이다.

Locking 은 트랜잭션이 DB를 다루는 동안 다른 트랜잭션이 관여하지 못하게 막는 것이다. 하지만 단순하게 무조건적인 Locking으로 동시에 수행되는 많은 트랜잭션들을 일렬로 죽 세워서 순서대로 처리하는 방식으로 구현된다면 DB의 성능은 현저하게 떨어지게 된다. 반대로 응답성을 높이기 위해 Locking 범위를 줄인다면 잘못된 값이 처리 될 여지가 있다. 그래서 최대한 효율적인 Locking 방법이 필요하다.

이와 관련된 Locking 방법이 Isolation Level이라고 생각하면 된다.

Isolation Level 의 종류

  1. Read Uncommitted

    • SELECT 문장을 수행하는 경우 해당 데이터에 Shared Lock이 걸리지 않는 Level입니다. 따라서, 어떤 사용자가 A라는 데이터를 B라는 데이터로 변경하는 동안 다른 사용자는 B라는 아직 완료되지 않은(Uncommitted 혹은 Dirty) 데이터 B를 읽을 수 있습니다.
  2. Read Committed

    • SQL Server가 Default로 사용하는 Isolation Level입니다. 이 Level에선 SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸립니다. 그러므로, 어떠한 사용자가 A라는 데이터를 B라는 데이터로 변경하는 동안 다른 사용자는 해당 데이터에 접근할 수 없습니다.
  3. Repeatable Read

    • 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정이 불가능합니다. 가령, Select col1 from A where col1 between 1 and 10을 수행하였고 이 범위에 해당하는 데이터가 2건이 있는 경우(col1=1과 5) 다른 사용자가 col1이 1이나 5인 Row에 대한 UPDATE이 불가능합니다. 하지만, col1이 1과 5를 제외한 나머지 이 범위에 해당하는 Row를 INSERT하는 것이 가능합니다.
  4. Serializable

    • 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정 및 입력이 불가능합니다. 예를 들어, Repeatable Read의 경우 1에서 10 사이에 해당되는 데이터에 대한 UPADTE이 가능하였습니다. 하지만 이 Level에서는 UPDATE 작업도 허용하지 않습니다.

출처 : http://support.microsoft.com/kb/601430/ko

위의 Transaction Isolation Level 은 Read Uncommited 에서 Serializable  순으로 Concurrency 는 높아지고 속도는 높아진다. 따라서 이 둘의 균형을 잘 맞추는 것이 중요하다.

위 네가지 Isolation Level  에 따라 나타나는 현상이 세가지가 있다.

  • Dirty Read
  • Repeatable Read
  • Phantom Read

각각의 의미는 다음과 같다.

  • Dirty Read

    • 어떤 트랜잭션에서 아직 실행이 끝난지 않은 다른 트랜잭션에 의한 변경 사항을 보게 되는 되는 경우를 dirty read 라고 한다. 만약 원래 트랜잭션에서 그 변경 사항을 롤백하면 그 데이터를 읽은 트랜잭션은 dirty 데이터를 가지고 있다고 말한다.
  • Repeatable Read

    • 어떤 트랜잭션에서 같은 질의를 사용했을 때 질의를 아무리 여러번 해도 그리고 다른 트랜잭션에서 아무리 여러 번 그 행을 변경해도 항상 같은 데이터만 읽어드리는 경우를 repeatable read 라고 한다. 즉 repeatable read 가 요구되는 트랜잭션에서는 다른 트랜잭션에 의한 변경 사항을 볼 수가 없다. 그러한 변경 사항을 보고 싶으면 어플리케이션에서 트랜잭션을 새로 시작해야 한다.
  • Phantom read

    • phantom read 는 다른 트랜잭션에 의한 변경 사항으로 인해 현재 사용 중인 트랜잭션의 WHERE 절의 조건에 맞는 새로운 행이 생길 수 있는 경우에 관한 것이다. 예를 들어, 잔고가 $100 미만인 계좌를 모두 찾아내는 트랜잭션에 있고, 이 트랜잭션에서 그 데이터를 두 번 읽는다고 가정하자. 처음 데이터를 읽어들이고 난 후에 다른 트랜잭션에서 잔고가 $0인 계좌를 새로 만들면 이 계좌도 잔고가 $100 이하라는 조건에 맞게 된다. 트랜잭션 격리 수준(Transaction Isolation Level)에서 phantom read 를 지원하면 새로운 “유령(phantom)”행이 나오지만 지원하지 않으면 새로 생긴 행을 볼 수 없다.
Isolation Level Dirty Read Nonrepeatable Read Phantom Read
READ UNCOMMITTED Permitted Permitted Permitted
READ COMMITTED Permitted Permitted
REPEATABLE READ Permitted
SERIALIZABLE

Tabel1. Ansi Isolation Levels

Mysql 의 InnoDB 스토리지 엔진의 기본 Isolation Level이 REPEATABLE-READ 이고 Oracle 은 READ-COMMITED 이다. 각 DBMS별 isolation level 에 자세한 내용은 다음 링크에서 참조할 수 있다.

  • mysql : http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html
  • oracle : http://www.oracle.com/technetwork/issue-archive/2005/05-nov/o65asktom-082389.html

Oracle 은 READ-COMMITED 와 SERIALIZABLE 만 지원하며 나머지 두가지 isolation level  은 지원하지 않는다.