database.sarang.net
UserID
Passwd
Database
DBMS
ㆍMySQL
PostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
MySQL Tutorials 16726 게시물 읽기
 News | Q&A | Columns | Tutorials | Devel | Files | Links
No. 16726
MySQLmodule-1.4 문서
작성자
정재익(advance)
작성일
2002-08-05 22:10
조회수
10,176

MySQLmodule-1.4 문서

 

번역 및 편집 : 이강성 gslee@mail.gwu.ac.kr 1999.11.

 

--------------------------------------------------------------------------------

 

역자 주: 이 모듈은 mysql을 사용하기 위한 Python 인터페이스이다. 사실 Python은 Python Database API 2.0을 개발해 놓고 어느 데이터 베이스를 사용하든지 같은 인터페이스를 제공한다. 이 모듈은 이러한 API를 따르고 있지않다. 표준 Database API 2.0에 대해서 알고 싶으면 여기를 클릭하라.

 

다운로드 : mysql 공식 홈페이지에 가면 있다. 여기를 누르면 직접이동한다. (MySQLmoduel-1.4.tar.gz를 다운받아라.)

 

--------------------------------------------------------------------------------

 

이 모듈은 Linux, MySQL 3.21.30, Python 1.5.1 상에서 개발된 것이다.

 

판권은 MySQLmodule.c 을 보라.

 

MySQLmodule-1.x 은 mySQLmodule-0.1.4 에 기초하고 있으며 판권은

 

Copyright (C) 1997 Joseph Skinner <joe@earthlink.co.nz>

Copyright (C) 1997 James Henstridge <james@daa.com.au>

 

에 있다.

 

mySQLmodule-0.1.4 은 mSQLmodule에 기초하며, 부분 판권은,

 

Portions copyright (C) 1995 Thawte Consulting, cc

Portions copyright (C) 1994 Anthony Baxter.

 

에 있다. 자세한 내용은 \Credits\을 보라.

 

Joerg Senekowitsch (senekow@ibm.net), 1998년 10월

 

 

--------------------------------------------------------------------------------

 

]**목차**

 

왜 또다른 Python/MySQL interface가 필요한가?

MySQL module 컴파일과 설치

Exported types, functions and classes

MySQL module 사용하기

서버측의 스토리지에 관해서

감사의 글

번역과 편집

 

--------------------------------------------------------------------------------

 

**왜 또다른 Python/MySQL interface가 필요한가?**

 

나는 최근에 MySQL 데이터 베이스에서 널 캐릭터(\0)를 포함하는 문자열을 저장하는 문제에 부딛혔다. 처음에는 Python을 불평했지만, 확인한 결과 mySQLmodule에 몇가지 문제가 있는 것을 발견하였다. 몇개의 루틴이 할당된 메모리를 해제하지 않았고, 몇몇 MySQL API 함수들은 사용할 수 없었다. 그리고 난 mySQLmodule이 method(그리고 tuple들)에 따라 다른 자료구조를 넘기는 사실을 좋아하지 않았다. 그래서 코드를 다 찢어 버리고, 골격은 놔두었지만 많은 변화를 주었다. 그 변화중에는 Python의 method와 리턴값을 바꾸는 것까지 포함되어 있었으므로, 주요 버젼 번호를 올렸고 이름도 MySQL로 바꾸었다. 그렇게 함으로 원리 mySQL과 충돌이 생기지 않게 되었다.

 

tuple혹은 tuple의 list를 사용하기 보다 list의 list를 사용하도록 바꾼 것은 합리적이었다. 난 내 DB 접근 루틴들이 리턴 타잎에 대해 신경쓰는 것을 원치 않았고 데이터를 복귀된 테이블로 수정하고 싶었다.

 

Data = DBH[\select * from MyTable\]
if Data:
    rows = len(Data)
    cols = len(Data[0])
    for i in range(rows):
        for j in range(cols):
            if not Data[i][j]: Data[i][j] = DefaultElement()
    Do_Something(Data)

 

더이상 list안에 tuple을 가짐으로 복잡해질 필요가 없었다.

사전(dictionary) 형식을 좋아하는 사람들을 위해서, STH method fetchdict()는 사전의 리스트를 복귀할 것이다. 사전 키는 대응하는 테이블명으로 자격이 주어진다.

 

--------------------------------------------------------------------------------

 

**컴파일과 설치**

 

i. Win32시스템에 설치하고자 하면 README.NT을 읽어라.

 

ii. MySQLmodule.c 를 Python 소스의 Modules 디렉토리에 복사하라.

 

iii. 그 디렉토리의 Setup 화일에 다음의 행을 추가하라:

 

MySQL MySQLmodule.c -L/usr/local/lib/mysql/ -lmysqlclient \

-I/usr/local/include/mysql

 

MySQL 라이브러리와 인클루드 디렉토리는 시스템에 따라 다를 수 있음에 주의하라. 공용 모듈로 만들고 싶다면 Setup 화일의 *shared* 아래에 삽입하라.

 

iv. Python을 컴파일한 적이 있으면 Python 디렉토리에서 make를 수행시킨다. 그렇지 않으면, compile/install 의 지시내용을 따라라.

 

Python 소스를 건드리지 않고 동적으로 적재가능한 모듈을 만들려면 다음을 실행하라. (Trond Eivind Glomsr?):

 

gcc -shared -I/usr/include/python1.5 -I/usr/local/include/mysql MySQLmodule.c -lmysqlclient -L/usr/lib/python1.5/config -lpython1.5 -o MySQLmodule.so

 

그리고 만들어진 MySQLmodule.so 를 PYTHONPATH 로 이동하라. 인클루드와 라이브러리는 여러분 환경에 맞게 조정해야 할지 모른다.

 

모듈은 대소문자를 구별하는 것에 주의. mySQL모듈과 충돌 생기지 않도록 조심스럽게 이름이 변경되었다.

 

--------------------------------------------------------------------------------

 

**EXPORTED TYPES AND OBJECTS**

 

모듈 (MySQL)은 다음을 export 한다:

  DBH_Type:    database object 형
  STH_Type:    cursor object 형
  error:       어떤 화경에서 발생되는 exception(예외처리) (TypeError는 아님)
  __doc__:     Python에서 쓰는 버전

  connect([host[,user[,pass]]]) 

database object를 리턴한다. 옵션 인수는 연결할 호스트 이름, MySQL을 사용하는 사용자명 그리고 패스워드이다. 호스트가 주어져 있지않으면 \localhost\이다(그리고 빠른 유닉스 소켓 연결을 사용한다.)

 

escape(string)

 

DB에 삽입을 허락하는 적절한 escape 된 문자열을 (가능하면) 리턴한다. 이 루틴은 mysql_escape_string()을 호출하는데, 3.21.29-gamma에선 동작하지 않는다. 버전 >=3.21.30 에선 동작된다.

 

MySQL.connect()

 

데이타베이스 핸들(DBH)을 리턴한다. 다음의 method를 갖는다.

(주의:다음에서 \Table\ 은 \list of lists\을 의미한다. (fetchdict제외))

 

Table = DBH.listdbs([wild])

 

MySQL.connect()로 연결된 MySQL 호스트상의 데이타베이스들의 이름을 테이블로 리턴한다. 선택인자는 MySQL 와일드카드 문자열이다. (LIKE와 같은 문법)

 

DBH.selectdb(DB_Name[,storage])

 

이 개체를 특정한 데이타베이스에 붙인다. 실행된 질의는 다른 selectdb가 호출되기 전까지는 이 데이터베이스로 향한다. 선택적인 storage는 서버상에 질의 결과를 유지할 때 사용된다. 이 것은 서버 성능을 저하시킴에 주의하라. 하지만 클라어언트가 더 작은 메모리 footprint를 사용하게 한다. 왜냐하면 레코드들은 요구에 의해서만 전송되기 때문이다. 기본값은 0, 즉, 모든 레코드가 클라이언트로 전송된다.

 

Table = DBH.listtables([wild])

 

선택된 데이타베이스의 테이블 이름들을 리턴한다. selectdb 호출 후에 사용가능하다. 옵션은 테이블의 집합을 제한하기 위해 사용된다.(LIKE와 같은 문법)

 

Table = DBH.listfields(table[,wild])

 

주어진 테이블의 필드 기술(description)표를 리턴한다. 옵션은 필드의 집합을 제한하기 위해 사용된다.(LIKE와 같은 문법)

 

Table = DBH.listprocesses()

 

 

실행중인 MySQL 프로세스들에 대한 정보를 리턴한다. 특권이 필요함(아니면 None을 리턴)

 

String = DBH.stat()

 

MySQL의 상태정보 리턴

 

DBH.create(DB_Definition)

 

새로운 데이타베이스 생성

 

DBH.drop(DB_Name)

 

하루를 망칠수 있음. (역자주:데이타베이스를 단번에 날리고 싶으면 이것을 사용할 것)

 

DBH.reload()

 

MySQL특권 테이블을 재적재.

 

DBH.shutdown()

 

MySQL 데몬을 죽임.

 

DBH.close()

 

DB연결을 종료시킴.

 

String = DBH.clientinfo()

 

MySQLmodule 버전 정보 리턴.

 

String = DBH.serverinfo()

 

MySQL 서버 정보 리턴.

 

String = DBH.hostinfo()

 

호스트와 연결 종류에 관한 정보 리턴.

 

Integer = DBH.protoinfo()

 

MySQL 프로토콜 버전 번호 리턴 (10).

 

Table = DBH.do(query) or Table = DBH[query]

 

SQL 질의 결과를 리턴한다. 질의 결과와 행수를 리턴한다 (mySQL이 거짓말 할지도 모른다). 두가지 방법은 DBH.selectdb()로 설정된 저장 형을 이용한다. WIN32버전을 수행중이면 코드의 주석을 참조하라.

 

Integer = DBH.insert_id()

 

마지막 생성된 auto_increment 번호에 접근한다. 질의가 호출 사이에 제출되었다면 이 번호는 바뀔 수도 있다. WIN32버전을 수행중이면 코드의 주석을 참조하라.

 

STH = DBH.query(query[,storage])

 

커서 메소드(아래를 볼 것)의 문 핸들을 리턴한다. 옵션 \storage\파라미터는 DBH.selectdb()로 설정된 DBH 기본값을 바꾸는데 (override) 사용될 수 있다.

 

문 핸들(statement handles : STH)을 위한 메소드들:

 

Table = STH.fetchrows([n])

 

DB 질의의 결과를 리턴한다. 만일 n < 0 이면 전체 행이 넘어온다. 아니면, 다음 n개의 행이 리턴된다. 기본값은 전체 행이다.

 

Table = STH.fetchdict([n])

 

STH.fetchrows()와 동일하나, \tablename.fieldname:data\ 쌍으로 사전의 리스트가 리턴된다.

 

Table = STH.fields()

 

STH 질의 결과의 필드 기술(descriptions)이 리턴된다. 현재, MySQLmodule은 \pri\, \notnull\, \auto_inc\, \ukey\, \mkey\ 에 대해서 안다.

 

STH.seek(n)

 

커서를 n 행으로 이동한다. (0 부터 시작함). 클라이언트 측 결과 저장(=0, DBH.selectdb참조)이 선택되었을 경우만 가능. 그렇지 않으면 예외 발생.

 

Integer = STH.numrows()

 

얼마나 많은 행이 STH 질의 결과에 있는지 리턴한다. 경고: 실제로 이 수치는 클라이언트가 몇개의 레코드를 받았는지 나타낸다. 서버측 저장 메소드에서보면, 이 수치는 0에서 시작하고 클라이언트가 행을 가져감으로 증가된다. 클라이언트 측에서는, 이 수치는 즉시 이 질의에 대한 총 행의 수를 준다.

 

Integer = STH.numfields()

 

얼마나 많은 열이 STH 질의 결과에 있는지 리턴한다.

 

Integer = STH.affectedrows()

 

얼마나 많은 행이 마지막 질의에 의해 영향을 받았는지 리턴한다. MySQL이 어떤 경우에 잘못된 수치를 넘겨줄 수도 있음을 주의하라. WIN32버전을 수행중이면 코드의 주석을 참조하라.

 

Integer = STH.insert_id()

 

삽입 STH 질의로 부터 auto_increment 값을 리턴한다. 이 수치는 STH가 존재하는한 유지됨을 주의. WIN32버전을 수행중이면 코드의 주석을 참조하라.

 

Integer = STH.eof()

 

마지막 행이 읽혀졌으면 1복귀, 아니면 0.

클라이언트 측 스토리지가 선택되었으면(기본값) 언제나 1이고, 서버측 스토리지에서는 경우에 따라 유용함. 왜냐하면 과거의 마지막 레코드를 읽었을 경우에만 \참\으로 변하기 때문이다.

 

 

--------------------------------------------------------------------------------

 

**MySQL module 사용하기**

 

import MySQL

DBH = MySQL.connect() # localhost

print DBH.listdbs()

DBH.selectdb(\test\)

print DBH.serverinfo()

print DBH.stat()

DBH[\create table pytest (x int, y int, s char(20))\]

DBH[\insert into pytest values (1,2,\abc\)\]

DBH.do(\insert into pytest values (3,4,\def\)\)

STH = DBH.query(\insert into pytest values (5,6,\ghi\)\)

print STH.affectedrows()

print DBH[\select * from pytest\]

STH = DBH.query(\select * from pytest\)

print STH.numrows()

print STH.fields()

print STH.fetchrows(-1)

STH.seek(0)

print STH.fetchrows(1)

print STH.fetchrows(1)

STH.seek(0)

print STH.fetchrows(2)

print STH.fetchrows(2)

print STH.numfields()

STH.seek(0)

print STH.fetchdict(1)

print STH.fetchdict()

STH = DBH.query(\select * from pytest\,1)

print STH.fetchdict(1)

print STH.fetchdict() # compare to previous dicts

STH = DBH.query(\select * from pytest\,1)

print STH.fetchrows(1)

print STH.eof()

print STH.fetchrows()

print STH.eof()

DBH[\drop table pytest\]

 

--------------------------------------------------------------------------------

 

**서버측의 스토리지에 관해서**

 

MySQL은 두가지 약간 다른 데이타베이스 데이타 접근방법을 제공한다.

 

기본 방법은 클라이언트 측 스토리지를 사용하는 것이다. 즉, 커서(STH) 메소드를 포함하는 모든 질의들은 서버에서 모든 데이터를 가져온다. 행들은 STH.fetchrows(n)혹은 STH.fetchdict(n)을 통해서 개별적으로(n=1), 분할되어(n>1), 한번에(n<0) 접근되거나 접근되지 (n=0) 않는다. STH.numrows()는 질의후에 얼마나 많은 행이 결과에 있는가를 말해준다. STH.seek(k) 은 랜덤하게 행을 접근하는데 사용된다. 클라이언트 측 스토리지의 단점은 (클라이언트) 메모리를 모든 행을 유지하기 위해 사용한다는 것이다. 클라이언트 측 스토리지는 다음과 같은 구성을 가능하게 한다:

        STH = DBH.query(\select * from Foo\)
        N = STH.numrows()
        if N > 1000: raise Hell,\You must be joking!\
        for i in xrange(N):
                [Data] = STH.fetchdict(1)

클라이언트가 효과적으로 모든 행을 전송했으므로 서버가 관계하고 있는한 이 채널의 모든 트랜잭션은 멈추었고 서버는 새 명령을 받을 준비가 되어있다. 그것은 STH.eof()가 클라이언트 측 스토리지에 대해 언제나 참(1)이라는 것을 의미하기도 한다.

 

서버 측 스토리지는 많은 클라이언트 메모리를 요구하지 않는다. 왜냐하면 모든 레코드들은 요구에 근거하여 전송되었기 때문이다. 그러나, 서버측 스토리지는 몇가지 단점이 있다. 클라이언트가 모든 행을 검색하지 못한다는 가능성이 생길 수 있기 때문에, 각 새로운 명령은 서버가 새 명령을 받을 준비가 되었는지 반드시 검사해야한다. 그렇지 않다면, 남아있는 행들을 retrieve하는 충분한 읽기를 수행함으로 명령 채널을 명령으로 깨끗하게 해야한다. (3.21) MySQL은 \abort()\와 같은 종류의 API를 제공하지 않는다. STH>numrows()는 더 이상 질의로 얼마나 많은 행이 선택되었는지 알지 못한다. 그래서 위의 예제 코드는 실패할 것이다. STH.numrows()는 그러나 행이 읽혀짐에 따라 갱신될 것이다. 예를 들면:

        STH = DBH.query(\select * from Foo\)
        Data = STH.fetchrows(-1)
        print \Got\,STH.numrows(),\rows.\ # len(Data) is the same

STH.eof() 는 서버측 스토리지에서만 의미가 있다. 하지만 여기서의 코드는 그렇게 유용한 것이 아니다:

        STH = DBH.query(\select 1\)
        print STH.eof()          # will print 0
        Data = STH.fetchrows(1)  # retrieve the row
        print STH.eof()          # still 0 :-(
        Data = STH.fetchrows(1)  # must repeat. Data will be []
        print STH.eof()          # now we get 1, but we already 
                                 # knew that we\ve hit the end

이것을 버그로 생각하는 사람이 있을지 모른다. STH.seek(k) 은 더이상 사용할 수 없으며 에러를 발생시킬 것이다.(\cannot seek on server\), 즉, 행은 순차적으로 읽혀야 한다.

 

서버측 스토리지는 서버에 긴장을 더한다. 특별히 서버는 모든 행이 읽혀질 때 까지 클라이언트와의 연결을 유지할 필요가 있다. MySQL 메뉴얼에 따르면, 클라이언트들이 행을 빠르게 읽어가고, 어떤 긴 처리나 실행을 멈추는 것을 하지 말것을 권면한다. (예를 들면, 대화 인터페이스에서 Ctrl-S를 누르는 것과 같은..)

 

어떤 응용에 어떤 방법이 좋을지 결정 하지 못하는 사람들에게, MySQLmodule은 두가지 방법을 자유롭게 섞어서 사용할 것을 허용한다. 기본 행동 방식은 DBH.selectdb()로 설정될 수 있으며 개별 커서(STH)에 근거한 질의에 따라 변경될 수 있다. 불완전한 서버측 질의가 새롭게 제출된 명령에의해 취소될 수 있음을 주의하라:

        STH = DBH.query(\select * from Foo\,1) # 서버측 스토리지 사용
        Tables = DBH.listtables()              # 이전 결과들을 stomp 한다
        Data = STH.fetchrows()                 # nothing here anymore
   vs.
        STH = DBH.query(\select * from Foo\,0) # 클라이언트측 스토리지 사용
        Tables = DBH.listtables()              # 간섭하지 않음
        Data = STH.fetchrows()                 # no problem...

서버측 스토리지는 또한 MySQLmodule에 머리를 쥐어뜯게 하는 코드를 만든다. 일반적으로 (클라이언트 측 스토리지) STH커서는 데이타베이스 핸들에 독립적이다. 질의 직후, 모든 데이터는 전송되고 사용자는 DBH또는 STH핸들을 이용하여 하고 싶은 것을 마음대로 할 수 있다. 서버측 스토리지를 가지고는 좀 까다롭다. 데이타베이스 연결을 위한 메모리 필요량은 DBH 핸들에의해 제공된다. 서버측 커서를 가지고, 이 핸들을 향하는 포인터는 STH핸들에 저장된다. MySQLmodule은 이 메모리 영역이 모든 (서버측의) 외부 커서들이 닫히기 전에는 해제되지 않을 것임을 확실히 하고 있다. 이 말은 데이타베이스 핸들 DBH가 없어졌을 때 mysql_close()가 꼭 불릴필요는 없다는 것이다.

 

        DBH = MySQL.connect()         # get a DB handle
        STH = DBH.query(\select 1\,1) # server side cursor
        del DBH                       # mysql_close() *not* called
        STH.fetchrows()               # will succeed!
        del STH                       # now mysql_close() will be called
                                      # in DBH_dealloc()

DB 핸들을 닫고자 한다면, DBH-close()를 사용하라. 이 핸들과 통신하기 위한 모든 추가의 시도는 (외부 서버측 커서조차) \... server has gone away\ 예외를 일으킨다. mySQL은 열(sequence)에서 벗어난 명령을 받아들일 수 없기 때문에, 모든 DBH 메소드는 불완전한 STH 커서를 검사해야한다. 그들을 접근하기 위해서, DBH 핸들은 STH 커서로의 포인터를 포함한다... (한숨)

 

 

--------------------------------------------------------------------------------

 

**감사의 글**

 

Python을 개발한 친구들에게 감사한다. (Guido 외).

Python 정말 훌륭한 언어이다.

 

MySQL에 대해 Monty Widenius와 TcX Datakonsult AB 에게 감사한다. MySQL은 내 응용에서 mSQL, Oracle, Solid, 그리고 Postgres를 때려 눕혔다.

 

Python/MySQL 인터페이스의 개발을 위해 도와주신 다음 분들께 감사한다.

 

Joseph Skinner

James Henstridge

Thawte Consulting

Anthony Baxter

 

mySQLmodule의 판권에 관해서는 \Credits\ 화일을 봐주기 바란다.

 

 

--------------------------------------------------------------------------------

 

 

1999년 12월 13일

[Top]
No.
제목
작성자
작성일
조회
17063MySQL 의 간단한 설명서 [1]
정재익
2002-09-09
33126
17062too many connections 에러 해결책
정재익
2002-09-09
14027
16728MySQLmodule-1.4 설치/사용법
정재익
2002-08-05
12940
16726MySQLmodule-1.4 문서
정재익
2002-08-05
10176
16666Mysql 한방에 백업하기 [8]
정재익
2002-07-30
14753
16665mysql 에러 복구.
정재익
2002-07-30
10461
16664MySQL Index 속도 높이기..꽁수
정재익
2002-07-30
12014
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2023 DSN, All rights reserved.
작업시간: 0.051초, 이곳 서비스는
	PostgreSQL v16.1로 자료를 관리합니다