admin write
blogblogblogbloglocation loglocation logtag listtag listguest bookguest book
rss feed

PHPFest 2013

2013.09.26 09:50

 

 

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

MyISAM과 달리 InnoDB 테이블들은 매우 안정적이며, 왠만해서는 데이터 파일이 깨어지는 경우는 거의 경험하지 못했다.
하지만, 데이터 파일이 깨어진다면 어떻게 해야 할까 ?. DBMS 벤더를 불문하고 손상된(깨어진) 데이터 파일을 복구한다는 것은 쉽지 않은 문제이며 위험도 크다.
이런 비 정상적인 현상은 어느 DBMS에서나 발생할 수 있는 현상이며, 이를 위해서 우리는 데이터베이스를 그렇게 열심히 백업하고 있었던 것이다.
만약, 백업마저도 복구가 안 된다면, 결국 지금의 깨어진 데이터 파일이라도 어떻게든 복구를 해야 한다.
하지만, InnoDB myisamchk와 같은 별도의 복구 도구를 제공하지 않는다.
손상된 InnoDB 테이블의 복구는 우선 MySQL을 기동시켜서 데이터를 덤프(mysqldump, SELECT INTO OUTFILE…)를 받는 것이 유일한 방법이다.
하지만, InnoDB Boot-up 과정에서 여러 가지 체크 및 정리 작업들을 하게 되는데, 이 중에서 하나라도 문제가 있을 경우 시작이 되지 않는다. (MySQL이 시작도 안 되는데 어떻게 덤프를 받지? ㅠㅠ)
그래서 MySQL의 설정 옵션 중에서 "innodb_force_recovery" 라는 설정 변수를 제공하고 있다
아래와 같이 MySQL의 설정 파일(my.cnf, my.ini)에 설정하면, 이 설정 값에 의해서 InnoDB에게 어떤 체크나 정리 작업을 건너뛰어야 할지를 알려 줄 수 잇다.

## 0 ~ 6까지의 값 중에서 하나를 설정 (0은 정상 상태인 경우이며 그 이상의 경우 강제 복구모드에 해당됨)
innodb_force_recovery = 1


기본 설정 값은 "0" 인데, 이는 InnoDB에게 모든 체크와 정리 작업을 정상적으로 실행하도록 명령하는 것이다.

그 이외의 설정 값은 모두 비 정상적인 상황을 위한 설정 값이며, 일반적인 서비스 환경에서는 사용하면 안 된다.
또한 "0"이 아닌 그 이외의 값을 설정하게 되면, InnoDB는 복구 모드라고 가정하고 SELECT 이외의 데이터를 변경하는 SQL들은 모두 처리를 거절해 버린다.


각 설정값별 복구 내용과 방식을 간단히 살펴보자. 

·         1 ( SRV_FORCE_IGNORE_CORRUPT )
데이터 파일의 손상된 페이지가 발견되어도 무시하고 MySQL을 기동시킨다.  일단 MySQL이 기동되면, SELECT * FROM tbl_name; 명령문을 실행하여 데이터를 덤프하여 다시 적재하거나 다른 데이터베이스로 이전하는 것이 좋다. 이 때, 손상된 인덱스 레코드와 페이지는 모두 건너뛰게 된다. (, 무시해 버리므로 데이터를 잃게 된다.)
에러 로그 파일에 "Database page corruption on disk or a failed "라고 출력되는 경우, 대부분 이 케이스인데 이는 테이블 스페이스의 페이지가 손상되어서 발생하는 문제이다. 이 경우에는 이 모드로 MySQL의 기동 후, mysqldump SELECT INTO OUTFILE...을 이용하여 덤프 및 재 적재가 가능하다.

·         2 ( SRV_FORCE_NO_BACKGROUND )
InnoDB의 여러 가지 Background thread들 중에서 Main thread를 시작하지 않고 MySQL을 기동시킨다. InnoDB의 경우 트랜잭션과 동시성 향상(MVCC)을 위해서 Undo 정보를 보존하게 되는데, Undo 정보는 변경되기 전 데이터를 가지게 된다. 이러한 Undo 정보는 여러 가지 상황에 맞춰서 적절한 시점에 삭제가 되어야 하는데 이 작업을 Main thread가 처리한다 (이 작업을 Purge라고도 부른다.). 그런데 만약 MySQL 의 시작 과정에서 InnoDB가 이러한 Purge 작업 중 오류를 발생시킨다면, MySQL의 기동 시에 Main thread를 시작시키지 않기 때문에 Purge 작업 중의 오류를 피할 수 있게 되므로, 일단 MySQL을 시작시킬 수는 있게 된다. Undo 정보는 InnoDB의 시스템 테이블 스페이스에 관리되기 때문에, 이 경우에는 전체 데이터베이스를 덤프 받은 후 다시 MySQL 서버를 구성해야 한다.

·         3 ( SRV_FORCE_NO_TRX_UNDO )
MySQL을 종료하던 시점에 만약 진행 중인 트랜잭션이 있었다면, MySQL은 그냥 단순히 그 Connection을 강제로 끊어 버리게 된다. 그 이후 별도의 정리 작업은 진행하지 않게 된다. MySQL은 종료되었지만, 진행 중이던 트랜잭션의 정리 작업은 하지 않게 되는 것이다. MySQL이 다시 시작하게 되면, InnoDB 엔진은 트랜잭션 로그(Redo log라고도 함)를 읽어서 다시 처리 해주고(이 작업을  Roll forward라고 함), 최종적으로 어떤 트랜잭션이 완료되지 않고 Connection이 종료되었는지 판단 후, 그 트랜잭션들은 InnoDB 엔진이 Rollback을 시키게 되는데, 만약 Undo 영역이나 다른 관련된 데이터들이 손상된 경우에는 Rollback 처리를 해줄 수 없게 되는데, 이 경우에 사용하는 복구 모드이다. 이 경우에는 사실은 Rollback되어야 하지만, 실제 데이터 파일에는 그 데이터가 남아 있을 수 있다. (이 부분은 Binary log Application의 로그를 통해서 수동으로 보완해 주거나 무시하는 방법밖에 없다.)

·         4 ( SRV_FORCE_NO_IBUF_MERGE )
MySQL InnoDBINSERT, UPDATE, DELETE 등의 데이터 변경 작업으로 발생하는 인덱스 변경 작업들을 상황에 따라서 즉시 실행할 수도 또는 나중에 처리하도록 지연시킬 수 도 있다. 이렇게 나중에 처리하도록 지연시키기 위해서는 변경 내용을 어딘가에 기록해 두어야 하는데, 그 용도로 사용되는 버퍼가 "Insert Buffer"이다. Insert Buffer의 내용은 언제 데이터 파일에 병합(Merge)될지 알 수 없다. MySQL을 종료해도 병합되지 않을 수 있는데, 만약 MySQL이 재 시작 되면서 Insert Buffer의 손상을 감지하게 되면 Insert Buffer의 병합 작업이 실패하고 MySQL이 기동하지 못하게 된다. 이 경우 사용할 수 있는 강제 복구 모드이다. (이 경우에는 테이블 통계 정보 갱신을 유발하는 작업들을 해서는 안 된다. 주로 DDL이나 ANALYZE 명령 등). Insert Buffer는 실제 데이터와 관련된 부분이 아니라 인덱스에 관련된 부분이라 테이블을 덤프 후 다시 적재하면 처리될 수도 있고, 아니면 단순히 "ALTER TABLE tbl_name ENGINE=InnoDB;" 명령만으로 해결될 수도 있다.

·         5 ( SRV_FORCE_NO_UNDO_LOG_SCAN )
복구 모드 3 ( SRV_FORCE_NO_TRX_UNDO )의 처리와 비슷하며, 이 모드에서는 Undo 로그를 완전히 무시하고 완전히 종료되지 않은 트랜잭션(COMMIT/ROLLBACK되지 않은)을 모두 COMMIT된 것으로 처리해 버린다.  또한 이 모드에서는 Undo 로그를 전혀 참조하지 않는 형태로 강제 복구 시킨다.

·         6 ( SRV_FORCE_NO_LOG_REDO )
이것은 MySQL 서버가 재 시작되기 전 가장 뒤에 발생한 체크 포인트 이후의 모든 트랜잭션을 버리고 복구 시키는 모드이다. 당연히 Redo 로그를 참조하지 않으므로 Roll forward라는 작업도 하지 않고 강제 복구시키게 된다. Redo 로그가 손상된 경우 이 모드로 강제 복구가 가능하다.

여기서 설명된 강제 복구 모드는 그 설정 값이 높아질수록 손실되는 데이터가 많아지기(복구 가능한 데이터가 적어지기) 때문에, 가능한 강제 복구 모드를 낮은 것(1 -> 2 -> 3 -> 4 -> 5 -> 6)부터 시도해 볼 것을 추천한다.

아래 내용은 HighPerformanceMySQL 블로그에서 발췌한 내용을 번역한 것인데, 같이 참조하면 좋을 듯 하다.
InnoDB 테이블이 손상되는 경우는 상당히 희박
Double write, Checksum 그리고 기타 Validation 로직들과 버그 보완으로 인해서, 실제로 MyISAM에 비해서 InnoDB 테이블 스페이스 및 데이터 파일은 상당히 안정적이다.

대부분의 손상은 인덱스에서 발생
많은 사람들이 경험하는 InnoDB 데이터 파일의 손상은 80~90% 정도가 InnoDB 인덱스 (Secondary index)에 발생한 손상인 경우이며, 이 경우에는 단순히 ALTER TABLE 또는 데이터 덤프 및 재 적재만으로 해결된다. 복구 모드 "1 ( SRV_FORCE_IGNORE_CORRUPT )" 참조.

이 이외의 InnoDB 테이블의 문제점들의 경우는 덤프 및 적재
이 이외의 복잡한 형태의 장애에 대해서는, (아주 심한 경우가 아니라면)데이터베이스 전체를 덤프하고 다시 적재하는 것으로 해결될 수 있다. 하지만, 가장 최근의 백업에 Binary log Replay (재 실행)해주는 것보다 빠를지는 상황을 적절히 판단해서 결정하는 것이 좋을 듯 하다.


이래도 저래도 안 되는 경우에는(대표적으로 InnoDB의 시스템 테이블 스페이스가 손상된 경우) 아래 URL의 도구를 참조하는 것도 도움이 될 수 있을 듯 하다.
(사용해 본 경험이 없어서, 얼마나 작동할지는 잘 모르겠다.)

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

PHPFest 2011

2011.05.17 20:14

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. 2012.01.31 17:03
    댓글 주소 수정/삭제 댓글
    수고...

한국의 많은 소프트웨어 업체들이 개발자를 제대로 관리하지 못하고(또는 안하고) 있다. 소프트웨어 개발은 정신에 의한 작업이다. 누가 하는 가에 따라서, 어떤 동기부여를 하는 가에 따라서, 어떤 환경에서 하는 가에 따라서, 어떻게 관리하는 가에 따라서 엄청나게 다른 결과를 만들어낸다.

하지만 관리라는 이름 하에 개발자에게 모욕적인 대우를 하는 경우도 많다. 작업에 지장이 있을 정도의 저사양 개발장비를 제공하고, 좁아터진 공간에, 계속 울리는 전화벨과 시끄러운 대화 소리, 휴식공간이라고는 전혀 없는 조직도 많다. 직원들의 일거수일투족을 감시하고, 심지어는 복장 검사를 하는 경우도 있다.

또한 프로젝트 데드라인을 맞추기 위해 새벽에야 겨우 집에 들어갔음에도 불구하고, 출근시간에 몇 분 늦었다고 해서 지각을 체크하고 전체 직원이 모인 회의에서 실명을 거론하는 회사도 있다. 그런 회사일수록 야근수당이 없고 교통비도 지급하지 않으며 사소한 비용을 아낀다. 한마디로 작은 비용을 절약함으로써, 신뢰 상실이라는 큰 비용을 지불하는 것이다.

그런 회사에서 만들어지는 소프트웨어는 품질이 나쁘다. 불행한 개발자들은 품질이 나쁜 소프트웨어를 만들어 낸다. 어쩌면 잠을 못 자고 피로에 지친 개발자들이 내쉬는 서글픈 한숨이 소프트웨어의 영혼에 스며들어 가는 것은 아닐까? 저주받은 소프트웨어. 마치 호러영화의 한 장면처럼 느껴진다.

회사는 직원들을 사랑하지 않으면서, 직원들에게 애사심을 강요하는 회사를 보고 있자면 실소가 나온다. 물론 회사로서는 직원들에게 사랑을 보여줄 수 없는 가장 큰 이유가, 열악한 비즈니스 환경으로 인한 비용적 압박 때문이라고 얘기할 것이다. 백분 양보하여 그것을 인정한다고 할 지라도, 그렇다면 도대체 왜 부적절한 관리자에게 관리를 맡기고 있는 것일까?

나쁜 관리자가 프로젝트를 망치고 있다!
업계를 보면 관리자의 자격이 전혀 없는 사람이 관리를 맡고 있는 경우가 무척 많다. 나쁜 관리의 비용은 엄청나다. 단지 팀 구성원들의 작업에 지장을 주는 정도가 아니라, 조직의 목표 달성에 해악을 미치며 결국 상당한 대가를 치르게 만들고 프로젝트를 완전히 망치는 경우가 빈번하다.

필자는 단지 관리자를 잘못 배정했기 때문에 수백억 원의 손해를 본 어느 대기업의 프로젝트를 경험한 적이 있다. 팀원들은 모두 유능했고 각자의 마음 속에 일을 잘하고자 하는 열정이 있었지만, 관리자의 무능과 변덕과 학대로 인해 팀원들은 모두 좀비가 되어갔다. 일부는 떠났고 일부는 일을 하지 않았고 일부는 하는 척을 했다. 결국 수년간 프로젝트를 진행했으나 결과는 나오지 않았고 프로젝트는 취소됐다. 몇 가지 추가적인 원인이 없었던 것은 아니지만, 가장 주요한 요인은 ‘나쁜 관리자의 존재’ 그 자체였다.

나쁜 관리자는 팀원들이 무엇을 하고 있는지 알지 못하며(또는 관심이 없으며), 팀원들의 능력을 제대로 파악하지 못한 채로, 원칙 없이 업무를 지시하며, 부적절한 인력을 배치하고, 팀원들과 제대로 대화를 나누지 않으며, 펫프로젝트(pet project, 고위층 또는 자신의 개인적인 관심으로 만들어낸 프로젝트)로 인해 업무 우선순위를 마구 바꾸고, 결과가 나와도 잘했는지 못했는지 제대로 판단하지 못한 채 자신의 기호에 따라 결과를 재단한다. 한마디로 그들은 조직의 목표와 팀원의 성장에는 아무런 관심이 없으며 단지 자신의 안위만 생각하는 사람들이다.

그러한 나쁜 관리자의 존재가 지극히 예외적인 경우라고 생각하는가? 만일 그렇다면 당신은 조직 생활의 경험이 많지 않든가, 아니면 억세게 운이 좋은 경우일 것이다. 그런 나쁜 관리자로 인하여 젊은 시절의 소중한 경험을 빼앗기는 팀원들이 몹시 많다. 나쁜 관리자의 해악은 단지 프로젝트의 실패로 나타나는 것뿐만 아니라, 사람들의 인생에서 그 시기에 필히 겪어야 할 소중한 경험까지 앗아가 버리는 것에 있다. 좋은 관리를 받아보지 못한 사람은 좋은 관리를 할 수가 없다.

좋은 관리자가 되기 위한 지침
그렇다면 좋은 관리란 어떻게 관리하는 것인가? 하단과 같이 몇 가지 지침을 제시할 수 있을 것이다.

첫째, 바라는 결과를 명확히 알려주어야 한다. 어떤 관리자들은 자신이 무엇을 원하는지 자기 스스로도 정확히 모르는 채 작업을 지시하고, 팀원의 작업 결과를 그날그날의 기분에 따라 자신의 기호대로 판단하곤 한다. 그런 관리자는 관리자로서의 자격이 없다.

둘째, 위임을 적절하게 수행해야 한다. 어떤 사람의 그릇은 위임할 수 있는 양의 크기로 정해진다. 즉 어떤 사람이 이루어낼 수 있는 최대 성과치는 그가 팀원들에게 권한을 위임할 수 있는 능력에 의해서 결정된다는 뜻이다. 할 일이 너무나 많지만 일할 시간이 없고 혼자서 모든 일을 처리하려고 하는 관리자는 탈진증후군(burnout syndrome)에 빠지게 된다. 그리고 탈진증후군에 빠진 관리자는 결국 팀을 궤멸시킨다.

셋째, 방법보다는 결과에 초점을 맞추어야 한다. 이 말에 오해가 없기를 바란다. 오로지 결과만 중요시하라는 뜻이 아니라, 결과가 올바르다면 방법은 팀원에게 맡겨두라는 뜻이다. 개발자 출신의 관리자는 자신이 선호하지 않은 방법으로 구현을 했다는 이유로 팀원을 질책하거나 업무를 회수하는 잘못을 저지르는 경우가 많다. 그런 관리자는 좋은 결과도 팀원들의 신뢰도 얻지 못할 것이다. 결과가 옳다면 그 방법은 팀원에게 맡겨두는 포용력을 가져야 한다.

넷째, 피드백을 주고, 코칭을 하고, 경력 개발을 지원해야 한다. 피드백이란 해당 직원의 업무 결과에 대해 어떻게 생각하는지 그 내용을 전달하는 것이다. 코칭은 일종의 도움을 주는 것으로서 선택 가능한 사항들 속에서 실행 계획을 만들도록 도와주는 것이다. 그리고 팀원이 새로운 지식과 경험을 쌓음으로써 성장할 수 있도록 경력 개발을 지원해야 한다. 팀원의 경력 개발에 전혀 신경을 쓰지 않은 관리자들이 너무 많다. 그것은 팀원을 일회용품으로 취급하고 있음을 스스로 증명하는 것과 같다. 경력 개발에 도움을 받은 팀원은 관심을 갖고 도와준 관리자를 언제까지나 기억할 것이다.

다섯째, 좋은 관리자는 자기 자신을 관리하는 사람이다. 좋은 관리자는 감정의 폭발에 반응하기보다는 사건에 대응한다. 불필요한 감정을 발산하여 팀원에게 공포심을 조장해서는 안 된다. 만일 감정이 폭발했거나 또는 잘못된 지시를 했다고 판단될 시에는 즉각 솔직하게 인정하고 사과를 해야 한다. 실수를 인정하는 관리자는 인간적으로 보인다.

좋은 관리 방법을 배우기는 힘들다. 왜냐하면 그것은 눈에 잘 보이지 않기 때문이다. 하지만 우리는 그것을 배우고 실천해야 한다. 그것이야말로 업계에 만연된 악순환의 고리를 끊어버리는 유일한 방법이기 때문이다. 우리가 겪은 불행한 경험을 다시금 후배들에게 전달해서는 안 된다.

비록 기술 중심의 소프트웨어 업체라고 할 지라도, 기술 관리란 기술이 아니라 사람을 다루는 것임을 잊지 말아야 한다. 회사가 가능한 범위 내에서 최상의 업무 환경을 제공하고, 개발자 개개인을 세심히 배려하는 피드백, 코칭, 경력 개발을 지원하는 관리자가 있는 조직이라면 개발자는 결코 불행하지 않을 것이며 더 나아가 어려운 일도 기꺼이 극복해 낼 것이다.

하지만 지금 이 순간에도 많은 기업들이 사소한 비용 절감과 무의미한 규칙 준수를 위해 직원들의 신뢰를 잃고 있으며, 나쁜 관리자를 배정함으로써 프로젝트와 팀원의 인생을 망치고 있다. 나쁜 관리자는 개인, 회사, 사회 모두에 악영향을 미치는 존재이다.

반면에 좋은 관리자는 탁월한 결과를 만들어내고 팀원들을 성장시키고 사회 전반에 좋은 인재를 공급한다. 그런 훌륭한 관리자가 어디 흔하냐고 항변하는 기업의 목소리가 들린다. 하지만 기업들이여, 그런 변명보다는 좋은 관리자를 채용하려는 노력, 그리고 양성하려는 노력, 그리고 그가 ‘진짜 관리’를 제대로 수행하였는지 평가하려는 노력을 무엇보다 먼저 기울여야 하지 않을까?

출처: ZDNet Korea

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. 개발자
    2010.08.05 13:35
    댓글 주소 수정/삭제 댓글
    현직 개발자로서 정말 공감합니다. 좋은글 잘 읽었습니다.
  2. 조규봉
    2010.08.19 08:53
    댓글 주소 수정/삭제 댓글
    ....퍼가도 될까요? 꼭 필요한 글 같아서요. -_-;;

저희 한 클라이언트를 방문하는 길입니다.
이 기업은 역사가 오래되다 보니, 조금 오래 전에 만들어진 공단 지역에 위치하고 있습니다.
처음에 방문하던 날, 참으로 놀랐는데, 그건 좁은 길 때문이었습니다.
도로는 모두 양방향이었는데, 길은 한대가 겨우 지나 갈 수 있는 폭이었기 때문이죠.
게다가 그 수많은 골목길들은 거미줄 같이 연결되어 있었죠.

'이런, 이 길로 가다가 반대편에서 차가 오면 어떡하지?'

아니나 다를까,
좁은 길을 들어서자 마자 반대편에서 파란 1톤 트럭이 저를 발견하고 멈춥니다.
'이거 어떻게 해야 되지?' 하며 머뭇거리고 있는데,
트럭 기사 아저씨께서 순식간에 후진을 하시더니 다음 골목길까지 차를 빼주셨습니다.
너무나 순식간에 일어난 일에 어리둥절하며, 감사의 인사도 못하고 앞으로 차를 진행시켰죠.
백미러를 보니, 트럭 아저씨는 빠른 속도로 골목길을 빠져 나가고 계십니다.

그렇게 300여 미터를 가는 동안, 3대의 차와 마주치게 되었지만
모두 순식간에 길을 비켜 주셔서 걱정했던 것과는 달리
아주 쉽게 그 좁은 길을 빠져 나와 목적지에 도착할 수 있었습니다.

그 다음에 또 그 곳을 방문했을 때도 똑같은 경험을 했습니다.
마주친 모든 분들이 먼저 길을 비켜 주셨죠.
제가 비켜주는 것이 예의인 것 같은 경우에도 말이죠.
아마도 저의 행동이 느려서 그러셨을 겁니다.

그렇게 몇 번의 방문이 이어지다 보니, 이제 저도 익숙해 집니다.
처음으로 제가 먼저 비켜드리는 일도 생기게 되었죠.
마치 이 골목길 커뮤니티 멤버가 된 기분이 듭니다.


지금도 이 골목길은 참 독특한 느낌으로 남아있습니다.

도로가 매우 열악하였음에도 불구하고, 길이 막히는 경우는 거의 없었죠.
그건 골목길 멤버들이 먼저 양보하며 문제를 해결하고 있었기 때문이었고요.
참으로 열악한 하드웨어를 가졌음에도 불구하고,
그걸 운영하는 분들에 의해서 이렇게 좋아질 수도 있구나 하고 생각하는 계기가 되었습니다.

이분 들을 지켜보고 있으면,
'누가 비켜주나'는 중요하지 않은 듯싶었습니다.
'어떻게 하면 우리가 빨리 지나갈 수 있는가'가 중요할 뿐이었죠.


이런 일들은 소프트웨어 협업을 하면서도 수없이 발생하는 것 같습니다.
서로 협력해야 하는 접점은 마치 골목길 같은 느낌이죠.
설계를 하거나 문제가 발생했을 때, 누군가는 양보를 해야 됩니다.
어느 한쪽에서 수정하지 않으면 우리는 더 이상 앞으로 나아갈 수 없으니까요.

이 때 팀의 문화가 참 중요한 역할을 하는 것 같습니다.

어떤 팀에서는 '누가' 수정하느냐가 중요한 이슈가 되죠.
'이번엔 내가 고쳤으니 다음에는 그쪽이 고치세요.'
'우리 쪽은 이런 이유 때문에 수정이 불가능합니다. 그쪽이 수정을 해야 해요.'
'왜 맨날 우리가 고쳐야 하죠?'
경험상 이런 자존심 싸움은 마음을 상하게 만들고,
소프트웨어를 정치적으로 만들어 버리곤 합니다.
엔지니어로서는 별로 재미 없는 상황이죠.

한편, 어떤 팀에선 어떻게 하면 '올바르게 혹은 효율적으로' 고칠 수 있는가가 관심사이죠.
'누가' 고치는가는 그다지 중요하지 않습니다.
어떤 방법이 올바르고 효율적인가에 대해서
서로의 의견을 듣고, 이야기 하면서 문제를 해결하는 것은 참으로 흥미진진한 일입니다.

올바르고, 효율적인 것이 이기는 환경,
바로 엔지니어가 신나게 일할 수 있는 문화인 것 같습니다.


아마도 이런 이유로,
그 골목길 커뮤니티가 아직까지도 좋은 인상으로 남아 있는 것 같아요.
또 한번 찾아 가야겠습니다. 하하.



원문 : http://jamestic.egloos.com/1905048

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

PHP mail 함수

2009.11.21 00:51

PHP 5.3.0 이상의 버전에서 mail() 함수로 메일을 발송할때
메일이 깨져서 발송되는걸 확인했다.

왜 그럴까 하고 메일헤더를 열어봤더니 평소에 볼 수 없던
'X-PHP-Originating-Script' 라는 헤더가 추가된걸 발견할 수 있었다.

도대체 이놈이 왜 붙나 한참을 고민하다 php.net을 찾아봤더니
PHP 5.3.0 부터 php.ini에 mail.add_x_header 라는 지시어가 추가된 것을 알 수 있었다.

이놈이 뭔가 했더니 스크립트의 UID와 파일명을 가지는 X-PHP-Originating-Script를 추가한다고 한다.

간단히 말해서..
'난 foobar.php 라는 놈에서 실행됐고 uid가 500으로 되어 있다.
의도하지 않은(인젝션 등) 메일이 발송된것이라면 이 파일을 잘 다듬어 봐라'
뭐 대략 이런 의도로 추가되지 않았을까 싶다.

우리 회사에서 저게 필요할까? 하고 잠깐 생각해봤으나
웹으로 메일 쏠 일이 매우 한정적이므로 불필요한 옵션이라 판단하고,
php.ini에서 mail.add_x_header = Off 시켜줌으로써 해결했다.

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

L4, LVS, DNS RR 등으로 여러대의 웹서버를 운영하다보면
늘 고민하게 되는게 세션 공유일 것 같다.

물론 L4의 Metric 중에 Hash를 이용하면 어느정도 해결 될 수 있는 문제이지만,
가끔 클라이언트가 다른 서버로 세션이 할당되는 경우를 볼 수 있다.

나 또한 이 문제로 많은 고민을 했고, 여러 많은 HOW를 보았지만 썩 마음에 드는것이 없었다.
아마 세션 공유를 위해서 사용되는 방법은 아래의 3가지가 가장 보편적이지 않을까 싶다.

1. NFS, Samba
특정 서버의 디렉토리를 다수의 웹서버에서 Network를 통해 공유하는 것이다.
그럼 한곳의 디렉토리에 모든 세션 파일이 존재할 것이고 문제는 해결이 된다.
그렇지만 NFS나 Samba는 Write 효율성이 상당히 떨어지는 데몬이다.
세션은 그 특성상 read/write가 매우 빈번히 일어나기 때문에 효율성 면에서는 좋지 않다.
(개인적으로 이 방법을 사용하다가 피본적이 있다-_-;;)

2. DBMS
세션 데이터를 DBMS와 연동하여 DB에 저장하는 방식이다.
보편적으로 주로 사용되는 방법이지만, 접속자가 매우 많은 환경에서는
DB서버에 부하가 늘어날 수 밖에 없는 구조이다.
또한 DBMS에서 생기는 lock도 무시못할 변수로 떠오를 수 있다.

3. Daemon
말 그대로 데몬을 이용하여 세션을 공유하는 방식이다.
세션서버를 따로 구축하기에 제일 적절한 방법이 아닐까 싶다.

늘 그렇지만.. 난 언제나 서론이 참 길다.
오늘은 sharedance 라는 데몬을 소개하고자 한다.
지인의 소개로 알게된 데몬인데..
약 2년정도를 15대의 웹서버에 적용해서 사용하고 계신다는데.. 별 문제는 없으시다고 한다.
그래서 현재 우리 회사에서도 적용중인 데몬이다.

1. 세션 서버 구성
이 데몬은 세션 서버로 사용될 서버에만 설치해주면 된다. 웹서버에는 설치할 필요가 없다.
sharedance의 최신버전은 http://sharedance.pureftpd.org/ 여기서 구할 수 있으며,
RPM으로 구하고 싶다면 http://rpm.pbone.net/ 에서 sharedance로 검색하면 된다.

1-1. RPM 설치
설치 끝났다. 참 쉽다. -_-

1-2. config 설정
sharedance의 환경설정 파일은 /etc/sysconfig/sharedance 에서 해주면 된다.
설정할 내용이 많은 것도 아니고, 달랑 2개면 된다.
SHAREDANCE_DIR="/var/lib/sharedance"
SHAREDANCE_OPTIONS="--expiration=1800 --timeout=1800"
SHAREDANCE_DIR 은 세션 파일이 저장될 디렉토리를 의미한다.
SHAREDANCE_OPTIONS 는 데몬을 시작할때 사용할 옵션을 지정해주는 것이다.
어떤 옵션들이 있는지 보고 싶다면 sharedanced --help 라고 치면 나온다.

1-3. sharedance 시작
[root@localhost]# /etc/init.d/sharedance start
이제 sharedance 사용 준비가 모두 완료 되었다.


2. Client 설정 (웹서버)
웹서버는 크게 설정하거나 설치할 내용이 없다.
단순히 php.ini에서 sharedance의 handler 파일만 호출해주도록 설정하면 된다.

2-1. handler 파일 준비
이 파일을 직접 만들 필요는 없고, sharedance 에서 제공하는 파일을 그대로 가져다 쓰면 된다.
세션서버에서 sharedance를 RPM으로 설치했다면,
/usr/share/doc/sharedance-0.6/php/ 에 핸들러 파일이 존재할 것이다.
[root@localhost]# ls /usr/share/doc/sharedance-0.6/php
session_handler.php  sharedance.php  test_session.php  test_sharedance.php
필요한 파일은 session_handler.php와 sharedance.php 파일이다.
이 2개의 파일을 웹서버로 전송한다.

2-2. handler 파일 복사 및 설정
세션서버에서 전송받은 핸들러 파일을 적당한곳에 잘 복사해두면 된다.
필자는 편의상 서버 운영에 필요한 파일을 한곳에 몰아서 관리하고 있기 때문에
/etc/sadmin/httpd/sharedance 에 복사를 했다.

핸들러 파일이 세션서버를 이용할 수 있도록, 핸들러 파일을 약간 수정해야 된다.
그렇지만 그리 어려운 내용은 아니기 때문에 쉽게 수정할 수 있다.
[root@localhost]# vi /etc/sadmin/httpd/sharedance/session_handler.php
define('SESSION_HANDLER_HOST', '192.168.0.100');
이 부분은 세션서버를 지정해주는 부분이다.
만약 세션서버가 같은 서버에서 돌고 있다면 localhost로 지정하면 될 것이고,
다른 서버에서 돌고 있다면 그 서버의 ip 혹은 host를 적어주면 된다.

[root@localhost]# vi /etc/sadmin/httpd/sharedance/sharedance.php
define('SHAREDANCE_DEFAULT_PORT', 1042);
define('SHAREDANCE_DEFAULT_TIMEOUT', 10);
이 부분은 세션서버의 listening port와 timeout 시간을 설정해주는 부분이다.
만약 세션서버에서 데몬의 포트가 다르게 설정되어 있다면 이곳에서 수정을 해주면 된다.

2-3. php.ini 설정
이제 모든 준비가 끝났으므로 웹서버의 PHP에서 session을 이용할때
sharedance의 핸들러를 통해 세션서버와 통신하도록 설정해주기만 하면 된다.
[root@localhost]# vi /etc/php.ini
...
auto_prepend_file = /etc/sadmin/httpd/sharedance/session_handler.php
...
session.save_handler = user
php.ini 수정이 모두 끝났으면 웹서버를 재시작하여 변경된 php.ini의 내용을 reload 시킨다.

3. sharedance 확인
모든 설정과 준비가 끝났다.
세션서버에 세션파일이 잘 생성 되는지 확인을 해보자.
[root@localhost]# ls /var/lib/sharedance
01c6hof0u872jp3grka4ifo3u4  4u44789jq4vtjt7l2fp3t1ime6  e7d6nq244j27l8bllif792pp25
...
...
위와 같이 세션파일이 생성이 된다면, 정상적으로 웹서버와 세션서버가 통신하고 있는 것이다.

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. ctlim
    2010.06.07 10:36
    댓글 주소 수정/삭제 댓글
    좋은 정보 감사 합니다.
    퍼가요~^.^
  2. 헬로우~^^
    2010.08.22 07:57
    댓글 주소 수정/삭제 댓글
    제가 잘 몰라서.. 질문을 드립니다.
    Daemon (세션서버)을 설치, 위에서 설명해 주신대로 설정을 하면
    다른 도메인간 세션공유도 되는건가요?

회사에 새로운 솔루션이 도입이 되면서, DBMS의 파티셔닝 테이블을 필요로 했다.
그리고 MySQL은 5.1부터 파티셔닝 테이블을 지원한다.
그러나...
CentOS 5에서는 MySQL 5.0 버전을 지원하고 있는 관계로 그냥 사용할 수가 없다.

물론 간단히 소스컴파일 해서 사용하면 되지 않겠냐고 말하는 분들 있겠지만..
과감히 이런 멘트를 날려준다.
'아직도 컴파일이 멋지다고 생각하는가? 가장 좋을거라 생각하는가? 착각이다'
최적의 환경에서, 최적의 빌드옵션으로 빌드 할 자신 없다면 관둬라
불필요한 컴파일로 성능저하나 안일어나면 다행이다.

서론이 길었다.
그럼 어떻게 해야될까? 나의 repo tree를 뒤적뒤적 찾아보니...
오! thanks for Remi!!
MySQL 5.1을 지원해주고 있는 repository를 찾았다. (덤으로 PHP 5.2까지..)
바로 설치에 들어가보자 고고싱..

1. Remi의 yum repository 세팅
[root@localhost]# wget http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm
[root@localhost]# wget http://rpms.famillecollet.com/enterprise/remi-release-5.rpm
[root@localhost]# rpm -Uvh remi-release-5*.rpm epel-release-5*.rpm
/etc/yum.repos.d 안에 remi.repo 파일과 epel.repo 파일이 생성이 된다.
이제 사용할 준비가 완료 되었다. (너무 쉬운가?!)

2. MySQL 설치
[root@localhost]# yum --disablerepo \* --enablerepo remi install mysql
[root@localhost]# yum --disablerepo \* --enablerepo remi install mysqlclient15 mysqlclient15-devel
[root@localhost]# yum --disablerepo \* --enablerepo remi install mysql-server mysql-libs mysql-devel
remi의 repo를 enable 시켜줌과 동시에 모든 repo를 disable 시켜주는 이유는
centos base repo의 mysql(5.0)과 remi의 mysql(5.1)이 중복되지 않게 하기 위해서이다.

그리고 두번째 라인의 mysqlclient15 패키지는.. PHP에서 사용하는 라이브러리가 들어있다.
완전히 독립적인 DB 서버의 경우는 설치하지 않아도 되지만,
APM이 하나의 서버에서 운영되는 경우에는 반드시 설치해야 의존성 에러를 피할 수 있다.

자 설치가 다 끝났다. 이제 잘 쓰자.
참 쉽죠잉~?!

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

I believe in my self.
자기 확신을 갖는다.

Be passionate & want it
열정을 불사른다

Extend your comfort zone
늘 새로운 일을 시도한다

Lies and luck don't work
쉬지않고 기회의 씨앗을 뿌린다

Install goals
목표를 명확히 규정한다

Enjoy hard work
원하는것을 즐겨라

Very very persistent
포기하지 않고 끈기를 갖는다

Expect failure
실패를 예상하라

- 밀리언달러 티켓

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. 2009.06.24 10:33
    댓글 주소 수정/삭제 댓글
    오호 이런 심오한 뜻이..... 흠..

반성16..

2008.12.11 11:20

반성16

술에 취하여
나는 수첩에다가 뭐라고 써 놓았다.
술이 깨니까
나는 그 글씨를 알아볼 수가 없었다.
세 병쯤 소주를 마시니까

'다시는 술마시지 말자'
고 써 있는 그 글씨가 보였다.


김영승의 詩集 '반성' 중에서...

... 가슴에 와닿는다.. -ㅅ-)y~ooO

태그

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. 2008.12.12 17:04
    댓글 주소 수정/삭제 댓글
    -_-훗...

    니 이야기지-ㅅ-?ㅋㅋㅋ
  2. 미르
    2008.12.25 22:17
    댓글 주소 수정/삭제 댓글
    내이야기를 함부로.....
  3. 2008.12.31 13:24
    댓글 주소 수정/삭제 댓글
    허허, 공감 공감 ㅋ
    • 2009.04.02 23:54 신고
      댓글 주소 수정/삭제
      ㅋㅋ 공감하는 분들이 꽤 많군여 ㅋㅋ