2010년 5월 25일 화요일

Delphi - ODBC Create

Sample1

 

const
ODBC_ADD_DSN=1;
ODBC_CONFIG_DSN=2;
ODBC_REMOVE_DSN=3;
ODBC_ADD_SYS_DSN=4;
ODBC_CONFIG_SYS_DSN=5;
ODBC_REMOVE_SYS_DSN=6;
ODBC_REMOVE_DEFAULT_DSN=7;

function SQLConfigDataSource(HwndParent:HWND;FRequest:WORD;Driver:PChar;
                             Attributes:Pchar):boolean;Stdcall;

function SQLWriteDSNToIni(DSN: PChar;Driver: PChar):Boolean stdcall;
function SQLRemoveDSNFromIni(DSN: PChar):Boolean stdcall;

implementation

{$R *.dfm}


function SQLConfigDataSource;external 'odbccp32.dll' name 'SQLConfigDataSource';
function SQLWriteDSNToIni;external 'odbccp32.dll' name 'SQLWriteDSNToIni';
function SQLRemoveDSNFromIni;external 'odbccp32.dll' name 'SQLRemoveDSNFromIni';

procedure TForm1.Button1Click(Sender: TObject);
begin
  if SQLRemoveDSNFromIni('TA') then
  begin
    SQLWriteDSNToIni('TA', 'SQL Server');
    SQLConfigDataSource(0, ODBC_CONFIG_DSN,
                        PChar('SQL Server'),
    // add other params to the last one here:
                        PChar('DSN=TA'+ #0 +
                              'Server=(local)'+ #0#0));
  // to remove the one that you created, use this code:
  // SQLRemoveDSNFromIni('TA');
end;

 

 

 

Sample2

 

const
 
ODBC_ADD_DSN = 1;
// Add data source
 
ODBC_CONFIG_DSN = 2;
// Configure (edit) data source
 
ODBC_REMOVE_DSN = 3;
// Remove data source
 
ODBC_ADD_SYS_DSN = 4;
// add a system DSN
 
ODBC_CONFIG_SYS_DSN = 5;
// Configure a system DSN
 
ODBC_REMOVE_SYS_DSN = 6;
// remove a system DSN
 
ODBC_REMOVE_DEFAULT_DSN = 7;
// remove the default DSN

function SQLConfigDataSource(hwndParent: HWND;
  fRequest: Word;
  lpszDriver: LPCSTR;
  lpszAttributes: LPCSTR): BOOL; stdcall; external 'ODBCCP32.DLL';

function CreateDB(const Database: string): Boolean;
begin
 
Result := SQLConfigDataSource(0, ODBC_ADD_DSN,
    'Microsoft Access Driver (*.mdb)', PChar('CREATE_DB=' + Database + ' General'#0));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 
CreateAccessDatabase('c:\Testdb.mdb');
end;

2010년 5월 24일 월요일

ShowPicture

procedure TForm1.ShowPicture;
Var
  Tmp : TmemoryStream;
  Blb : TBlobStream;
  jpg : TJPEGImage;
begin
  Tmp := TMemoryStream.Create;
  blb := TBlobStream.Create(TblobField(ADODataSet1.Fields[0]), bmRead);
  try
    Tmp.LoadFromStream(Blb);
    jpg := TJPEGImage.Create;
    try
      jpg.LoadFromStream(Tmp);
      Image1.Picture.Assign(jpg);
    finally
      jpg.Free;
    end;
  finally
    Tmp.Free;
    Blb.Free;
  end;
end;

2010년 5월 23일 일요일

PostgreSQL clog xlog 손상에 따른 복구 이야기

이 글은 어제 이곳 DB 서버 사고에 대한 처리 과정을 기록해 두는 글입니다. 글 성격이 투토리얼이기 보다는 DBA 긴급 처리 문서에 더 가깝습니다.

PostgreSQL 서버를 어느정도 관리하실 수 있는 분을 대상으로 그냥 기록해 두겠습니다. 이해가 잘 안가시면 QnA에서 문의 하시든지, 아니면, 열심히 혼자서 메뉴얼보면서 공부하시든지. :)

 

 

0. 사태의 원인

이곳 db 서버의 PGDATA 디렉토리의 디스크 사용량이 그 파티션의 최대용량을 초과 하면서, OS 차원의 파일 쓰기에 오류가 발생했습니다.

이때, 쓰기가 별로 없는 서버였다면, 별 문제가 없었을진데, 이곳 게시판들의 검색은 그 검색 결과를 임시테이블에 저장하는 방식을 택하지는지라, 특히나 파일 쓰기가 꽤 자주 일어납니다.

즉, 여기서 완전 꼬여버렸습니다.

임시 테이블의 정보를 담는 pg_class, pg_class, pg_index, pg_attribute, pg_type 의 system catalog 테이블들은 그 정보가 담겨지고, 실재 물리적인 파일은 0byte 의 전혀 쓸모 없는 형태로 만들어지면서 postmaster 놈은 계속에서 오류를 알려주고 있는 과정에서 누군가가 게시물 작성을 하면서, 게시물 작성 과정에서 발생하는 4-5가지의 트리거작업을 하면서, pg_clog, pg_xlog 디렉토리의 undo, redo 정보를 담는 파일 조차 손상을 입었습니다.

 

1. pg_resetxlog 사용하기

이명령은 db server가 정상적으로 실행될 수 없는 상황에서 가장 마지막 선택하는 방법입니다. (물론 보다 더 저수준으로 자료만이라도 살리는 방법도 있겠지만)

이 명령을 사용하기 위해서는 먼저 PostgreSQL 서비스를 중지해야합니다.

 

일단 pg_resetxlog PGDATA

명령으로 pg_xlog 디렉토리 이하의 redo, undo 정보부터 바르게 정리합니다. (정 안되면, pg_xlog 이하 모든 파일을 지우고, pg_resetxlog 명령을 이용해서 다시 만드는 방법도 있겠지요)

 

2. pg_clog 자료 복구하기.

일단 깨어진 clog 파일이 어느 것인지 부터 찾아야합니다.

참고고, clog 디렉토리 안에 있는 자료는 commit 되지 않고 비정상 종료된 - 정상 종료되면 당연히 rollback 됩니다 - 트랜젝션의 변경 정보가 담겨집니다. 서버가 가동될 때, 이 정보가 있으면, pg_xlog 디렉토리 안에 있는 해당 자료를 찾아서 rollback을 완벽하기 시키겠지요.

(그 깊숙한 곳 까지는 공부를 더 해봐야알겠네요)

아무튼 어떠한 트랜젝션이 없다고 가정한다면, clog 파일은 그 파일이 정상적으로 있느냐 없느냐만 체크할 수 있으면 됩니다.

 

즉, 다른 정상적인 clog 파일을 복사해서 손상된 clog 파일에 덮어쓰면 되겠지요.

cd PGDATA/pg_clog; cp 0000 0001

이런식으로

 

3. 서버 재가동

일단 여기까지 하면, postmaster가 정상적으로 실행될 수 있으면, connect 까지도 가능할 것입니다.

 

4. catalog 테이블 정리

문제는 여기서부터 아주 인내심을 요하는 데이터 정리 작업을 해야합니다.

만일 이곳 서버처럼 임시 테이블을 빈번히 사용하는 상태라면, 임시테이블 삭제가 정상적으로 이루워졌는지 살펴보고, 만일 그렇지 못한 상태에서 종료되었다면, pg_class, pg_index, pg_attribute 등 아무튼 임시 테이블이 만들어지면서 변경되는 catalog 테이블들을 정상상태로 만들어야합니다.

 

(손상된 임시테이블 수동으로 정리하기)

4.1. select oid from pg_class where relname 'pg_temp_%'

형태로 모든 임시 테이블들의 oid를 구하고, 그놈들 기반으로 구성된 column (pg_attribute), index(pg_index) 의 관련 데이터들을 모두 지워야겠지요. 그리고 마지막에 pg_class 도 지우고.

이때 주의하셔야할 사항은 pg_toast_% 테이블이 pg_temp_% 테이블과 관련이 있을 수도 있습니다. 이것도 함께 지워야한다면, 같이 삭제해야할 것입니다.

 

4.2. 그리고 몇가지 catalog 테이블을 더 손봤는데, 기억이 안남. -.-

 

4.3. 다음은 pg_class의 해당 oid 들의 물리적인 파일을 지우는 일이 남았습니다. (자신 없으면 지우지 않으셔도 괜찮습니다, 괜히 잘못 지웠다가 예상치 못한 데이터 파일이 삭제 될 수도 있으니)

 

5. vacuum -f

-f 옵션은 데이터도, 인덱스도 모두 새로 깔끔하게 만드는 것을 의미합니다. 데이터가 많다면, 시간이 꽤 걸리는 작업입니다.

 

6. 모든 데이터가 제대로 정리 되었다면,

안전하게 pg_dump 로 dump 받고, 다시 새로운 db에 restore 해보고, 정상적으로 작동한다면, 그 새로운 db를 기존 것과 바꾸어 사용하면 끝납니다.

 

(물론 어제 사태처럼 디스크 공간이 부족해서 발생한 것은 이런 식의 완벽한 처리가 불가능하겠지만, 아무튼 최종 마무리는 새로운 db를 만들고 그곳에 다시 정상적인 restore 하는 것이 제일 안전할 것입니다)

 

--

오후 시간 내내 이 문제를 풀어가면서 꽤 많은 경험을 하게 되었네요.

개인적으로 꽤 즐거운(?) 경험이었습니다.

좀처럼 발생하지 않는, 그러나 발생하면 거의 대책이 안서는 사태를 수습했다는 것에 뿌듯하기도 하고...

아무튼 이런 심각한 db 사고의 복구를 한번 더 해보고싶네요

 

출처 : http://database.sarang.net/?inc=read&aid=4516&criteria=pgsql&subcrit=tutorials&record_idx=6&currpg=1

2010년 5월 15일 토요일

[PostgreSql] 데이터베이스 깨져서 Start 가 안되는 경우

 

제 노트북에서 전원이 나가면서...

데이터베이스가 깨져서 Postgresql 이 Start 가 안되는 현상을 확인 했습니다.

 

아래와 같은 방법으로 데이터 복구를 했습니다.

 

일단 C:\Program Files\PostgreSQL\8.3\data 폴더를 압축 합니다.

 

cmd 를 실행 하여

cd C:\Program Files\PostgreSQL\8.3\bin

 

C:\Program Files\PostgreSQL\8.3\bin>initdb -U postgres -D "C:\Program Files\PostgreSQL\8.3\data" -E UNICODE --lc-messages=ko_KR.eucKR -D C:\Program Files\PostgreSQL\8.3\data"

 

데이터베이스 생성

 

C:\Program Files\PostgreSQL\8.3\bin>"pg_ctl" -D "C:\Program Files\PostgreSQL\8.3\data" -l logfile start

 

서비스 시작

 

이 상태에서 데이터베이스 백업을 받은 후...

 

PostGreSql 삭제 후 (설치디렉토리까지 삭제) 재 설치 후...

 

복구 루틴에 의해 복구

2010년 5월 14일 금요일

[PostgreSQL] Service (PostgreSQL) failed to start

어제, 오늘은 PostgreSQL과 싸웠다. 꼬박 2일 걸렸다. 야근까지 생각하면 2일반인겐가 TㅅT

왜 싸웠는고 하면.. 이 녀석이 데이터베이스인데 설치가 안되는 것이었다. service로 등록해서 사용(설치할 때 체크하는 부분이 있음)하도록 설치를 하는데 파일 복사를 다 하고는 마지막에 서비스(Windows Service)로 등록이 되질 않는 것이다. 꺄윽~~ 아래와 같이 "Service 'PosgreSQL Database Server 8.3' (pgsql-8.3) failed to start. Verify that you sufficient privileges to start system services."라는 메시지 오류창 하나를 띵~하고 내놓고는 아무것도 되질 않는다. retry를 클릭하면 저 창이 계속 뜨고, cancel을 클릭하면 설치가 취소되면서 롤백(roll back)이 되는 것이다 TㅅT

우선, 저 구문으로 이게 무슨 오류인지 찾았다. "Windows Installer Error Code 1920"이며, "Windows Event ID 11920"과 함께 발생한다. "Windows Event ID 11920"은 "Msi Installer (Microsoft Installer)"에서 발생하며 종류는 에러(error)이고, "Product: <product> -- Error 1920. Service '[2]' ([3]) failed to start. Verify that you have sufficient privileges to start system services."라는 description을 가지고 있다. 한 마디로 다시 얘기하자면 Windows 서비스 등록이 실패했다는 것이다.

한참을 아니 이틀을 구글링에 빠졌다. 어떻게 하면 서비스로 등록을 할 수 있을까?? 원인은 아주 다양했다. 시도해 본 방법은 약 15가지 정도인데 성공한 방법과 중요해 보이는 부분만 골라서 설명하겠다. 보통 아래의 권한 부족 부분의 1 단계만 수행하면 사용이 가능할 것이다. 혹시 안된다면 2 단계도 확인하고 수행해 볼 것.




위와 같은 오류를 뱉고는 설치가 되지 않는 이유는 주로 Anti Virus와 방화벽, 그리고 사용자 계정의 권한이 가장 큰 요인이라고 한다. Anti Virus 제품들이 설치되어 있는 경우는 Anti Virus를 잠시 중지시키거나 설치하는 폴더만이라도 작동을 중지시키고, 그래도 안되면 삭제 후 설치하라고 한다. 방화벽도 Anti Virus와 마찬가지이다.

이번에 설치하는 곳은 랩탑이고 회사 내부에서만 사용하느라 Anti Virus도 없었다. 그런데 안되는 것이다 TㅅT 그럼 다음 원인으로 보이는 권한 부족!! PostgreSQL은 (일반적으로) 설치하고 서버를 실행할 때 postgres라는 계정을 만들어 사용한다. 이 계정이 실행하기 위해 서비스를 등록할 때는 몇 가지 권한을 가지고 있어야 한다.

1. 사용자 계정(postgres)이 서비스(Windows Service)를 제어할 수 있도록 권한을 부여한다.
1.1. "제어판 -> 관리 도구 -> 로컬 보안 정책"을 클릭하면 "로컬 보안 설정"창이 뜬다. ("시작 -> 실행"을 클릭하고 "secpol.msc"를 입력해도 된다.)
1.2. 이 창의 좌측에서 "보안 설정 -> 로컬 정책 -> 사용자 권한 할당"을 선택하면 오른쪽에
1.3. "서비스로 로그온 (log on as a service)" 항목이 보일 것이다. 여기에 사용자 계정 (postgres) 추가한다.


이 과정은 이 문서 5페이지에 잘 정리되어 있다.

아직도 설치가 되지 않는 경우가 있다. Windows XP pro, 2000, 2003 등에서 발생할 수 있으며, Windows Home edition은 발생하지 않는다.
2. 원인은 사용자 마다 폴더에 접근할 수 있는 권한을 따로 설정할 수 있게 되어 있어서이다. 그렇다면 PostgreSQL을 설치하면서 추가한 사용자 계정(postgres)에게도 권한을 부여해야지..
2.1. 탐색기를 연다.
2.2. 위의 메뉴 중에 "도구(T) -> 폴더 옵션(O)..."을 선택하면 아래와 같은 "폴더 옵션"창이 뜬다.

2.3. "보기"탭을 선택하면 중간에 "고급 설정"에 아래 그림과 같이 "모든 사용자에게 동일한 폴더 공유 권한을 지정(권장)"이라는 부분이 보일 것이다. 이 부분에 체크가 없는 사람만 아래와 같은 방법을 이용할 수 있다. 미안하지만 여기에 체크가 되어 있는 사람은 모르겠다 TㅅT
2.4. 체크가 되어 있지 않다면, 취소를 선택하고 윈도 설치 폴더("C:\Widows" 혹은 "C:\WINNT" 등)를 오른쪽 클릭하여 속성(R)을 클릭하여 아래와 같은 "폴더 등록 정보"창을 띄운다.


2.5. "보안"탭을 선택하고 추가(D)버튼을 클릭하여 사용자 계정(postgres)을 추가하고 "읽기 및 실행" 권한을 부여한다.
2.6. ta da~ 자.. 이제 설치가 가능할 것이다.



아~~ 해결하고 난 뒤의 이 달콤함이란.. 역시 이 맛에 개발자를 하는건데 이건 너무 오래 걸렸다. 자료가 너무 없어서 TㅅT 그런데 오늘은 벌써 저녁을 먹어서 야근을 해야 한다는거!! TㅅT 이렇게 곰방 찾을 줄 알았으면 저녁 먹지 말고 칼퇴근 하는건뒈~~ TㅅT

 

 

출처 : [PostgreSQL] Service (PostgreSQL) failed to start

2010년 5월 12일 수요일

adoconnection 에서 "exception class EAccessViolation with message" 에러 발생시

"exception class EAccessViolation with message"

 

이 메시지가 출력 되는 경우는

AdoConnection 이 생성되지 않은 상태에서 Connect 을 하려고 하는 경우...

 

일반적으로 데이터모듈에 AdoConnection 을 올리고...

데이터모듈이 생성 되지 않은 상태에서 AdoConnect 을 시도 하는 경우에 발생함

2010년 5월 11일 화요일

재설치시 "The password specified was incorrect. Please enter the correct password for the postgres windows user account." 에러 발생 하는 경우

비밀번호를 잊어 버려서 지우고 다시 설치 하는 경우...

 

The password specified was incorrect. Please enter the correct password for the postgres windows user account.

 

와 같은 에러 발생 시

 

실행 -> cmd

입력하여 MS-DOS 창을 띄워서 다음과 같이 입력하여 계정 정보를 삭제 합니다.

 

 

net user postgres /delete             //계정삭제

net user postgres 1234 /add            //계정 추가