Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>
http://sqlitedbms.sourceforge.net/

Contents

What is "SQLiteDBMS"?

  • 간단히 말하자면 SQLite를 이용한 DB"MS"이다.
  • SQLite는 많은 장점이 있지만 그만큼 단점도 있다.
  • http://sourceforge.net/projects/sqlitedbms/
아래는 지극히 주관적인 생각이다

SQLite의 장점

  1. 작다
  2. 빠르다
  3. 파일복사로 백업이 끝난다
  4. VM 단위까지 접근하여 처리하는 것이 가능하다

SQLite의 단점

  1. DB"MS"가 아니라 원격 사용이 불가능하다
  2. 쓰레드 세이프로 컴파일 되지 않으면 동시에 많은 프로세스가 접근할 때 문제가 생길수 있다
  3. 쓰레드 세이프로 컴파일 되어도 많은 쓰레드가 접근할 때 에러가 생기는 것을 목격했다..... 쩝 -_-;
  4. 카탈로그가 내부적으로 처리되지 않아 데이터의 양등을 알기 힘들다
  5. 처리한 데이터 양등을 알 수 없다
  • 위의 단점들을 극복 할 수 있는 MS를 만든다

SQLite Server 작성 프로젝트

SQLite가 비록 웹등을 통해서 간접적으로 원격 접근이 가능하다고는 하지만, 서버/클라이언트 모델을 지원하지 않는 것은 SQLite의 큰 단점이 될 수 있다. 이러한 단점을 제거하기 위해서 SQLite의 원격 제어가 가능하도록 SQLiteServer를 작성하기로 했다. SQLite의 소스를 고치는 것이 아닙니다. 관리의 목적을 벗어나는 부분인 SQLite의 코어를 건드리는 것이 아니라 SQLite가 제공하는 인터페이스를 이용하는 것입니다. SQLite의 메인터넌스와 관계없이 별도의 메인터넌스를 가지는 것이 좋겠습니다 -소타-
  • 네 그런 방향으로 이루어질 겁니다 - yundream -

전체 구성

다음은 SQLiteServer의 전체 구성도다. 우선은 ASCII ART로 나타내고 시간이 된다면 GIF이미지로 재 작성 하도록 하겠다.
  1. 클라이언트와 SQLiteHOST는 인터넷으로 연결되어 있다. SQLite는 기능상의 제약으로 CLIENT와 직접 대화할 수 없다.
  2. 이러한 제약을 없애기 위해서 SQLiteServer이 존재한다. SQLiteServer은 CLIENT의 요청을 받아서 요청을 SQLite로 전달하고 SQLite로 부터 받은 결과를 CLIENT로 보낸다.
  3. SQLite 프로세스로 SQLiteServer로 부터 CLIENT의 요청(Query)를 받고 여기에 대한 응답을 SQLiteServer로 보낸다.

SPEC (구체화 할 예정임)

Alpha SPEC

(-) : 구현되지 않음.

  1. 모든 쿼리(real query)를 처리하고 응답한다.
  2. 동시에 1k 이상의 콘넥션을 처리한다.
  3. SQLite의 VM수준 처리를 하여 쿼리 취소를 가능 하게 한다.
  4. 가볍고 빠른 프로토콜을 사용한다.
  5. VM 단위의 처리로 응답시 async 한 응답이 가능하게 한다.
  6. (-) 리플리케이션, 미러링 등 백업 처리
  7. (-) DBMS접근시 권한 인증을 처리한다.
  8. 사용자 정의 응답(DOC.SPEC.PROTOCOL 문서내의 convert 부분)을 가능하게 한다.
  9. (-) 확장된 DB모니터링(status)
  10. (-) 설정파일 따로 둔다.

Beta SPEC

  1. cache 를 내부적으로 처리한다.

통신 프로토콜 SPEC

SQLiteServer(이하 SSE)와 클라이언트간의 데이터 통신을 위해서 프로토콜이 정의 되어야 한다. SSE와 클라이언트간 데이터 교환을 위해서 2가지 방안이 제시 되었다.
  • XML
    • XML을 사용할 경우 유연하고 확장가능한 개발이 가능하다는 큰 장점을 가진다. 응용에 따라서는 쿼리 결과 자체를 재사용 가능한 XML데이터로 만들 수 있다는 응용상의 장점도 가지지만 SSE와 클라이언트, 네트워크에 너무 많은 부담을 준다라는 의견이 우세해서 일단 제외 시키기로 했다. 그러나 완전히 포기한 건 아니고 때에 따라서 추가 가능한 기능으로 분류 시켰다.
  • 전용 바이너리 포맷
    • 전용 바이너리 포맷은 확장이 어렵고 초기 설계를 잘못해서 변경이 이루어지게 될경우 관련 코드의 많은 부분에 영향을 준다라는 점이 단점이다. 반면 SSE와 클라이언트, 네트워크에 부담을 주지 않는 장점을 가진다. 이런 이유로 우선은 전용 바이너리 포맷을 사용하기로 결정을 했다.

통신 프로토콜 정의

SSE와 클라이언트간 사용될 통신 프로토콜은 아래의 기능을 만족 시켜야 한다.
  • 유저의 쿼리의 종류에 따라 복수의 결과값(레코드)이 패킷 형태로 전달 될 수 있으므로 패킷에 대한 식별이 가능해야 한다.
패킷의 식별을 위해서 패킷의 처음에는 패킷의 종류를 나타내는 일련 번호를 보내도록 한다. 다음은 패킷구조를 나타낸 간단한 예이다. 패킷의 종류를 나타내는 일련번호는 패킷ID라고 부르도록 한다. 다음은 간단한 예이다. 아직 패킷ID는 정의 하지 않았다. 패킷 ID에 대한 정의는 ??장을 참고하기 바란다.
|<-- HEADER -->|<----- DATA ---->| 
+----+----+----+---+--------+--------+
|A001|TYPE|size|QID| USERID | PASSWD |  인증요청
+----+----+----+---+--------+--------+
+----+----+----+---+--------+
|Q001|TYPE|size|QID| RESULT | 인증요청에 대한 결과
+----+----+----+---+--------+
           
+----+----+----+---+--------------+
|A002|TYPE|size|QID| QUERY STRING | QUERY
+----+----+----+---+--------------+
+----+----+----+---+--------------+
|Q002|TYPE|size|QID| QUERY RESULT | QUERY RESULT
+----+----+----+---+--------------+
패킷은 크게 3부분으로 이루어진다.
  1. 패킷ID가 정의된다. A면 요청이며 Q는 응답이다. Q001이라면 A001에 대하 응답 패킷임을 뜻한다.
  2. TYPE영역으로 각 패킷ID에 대한 세부적인 종류를 명시한다. 예를 들어 Q002를 이용해서 쿼리 결과를 전송할 때 여러개의 패킷이 전송될 수 있으므로 시작과 끝을 명시해주어야 할것이다. 이럴때 사용할 수 있다. 시작패킷인지, 데이터인지, 종료패킷인지 등에 대한 명시를 위해서 사용한다.
  3. SIZE실제 DATA영역의 크기를 명시한다. 사이즈 역시 int형이 아닌 char배열로 한다.
  4. QID데이터 ID다. 서버/클라이언트가 데이터교환시 혼동이 없도록 하기 위한 ID이다. QID는 프로세스 ID로 하면 될것 같다. 실제 서버는 하나의 클라이언트에서 단지 하나의 쿼리만을 처리하도록 할것이므로 필요없는 부분이라고 할 수 있게으나 만약을 대비하는 목적으로 추가했다.
  • 각 레코드의 필드의 정보를 명확히 유지할 수 있어야 한다.
유저가 요청한 쿼리의 결과에 대한 레코드를 되돌려 주기전에 클라이언트가 레코드를 편하게 처리 가능하도록 필드의 정보를 전송해 주어야 한다. 필드의 정보는 모든 레코드에 동일하게 적용될 것이므로 최초에 한번만 전송하면 된다. 필드는 가변 크기를 가지게 될것이다. 다음은 현재 생각중인 전송 구조이다. 패킷의 이름은 INIT패킷이라고 부르도록 한다. INIT은 쿼리 요청에 대한 응답이 있을 때 실제 레코드를 보내기전 가장 먼저 보내는 패킷으로 응답의 시작을 알리기 위한 용도와 응답될 레코드에 대한 정보를 저장하기 위해서 사용된다.
typedef _init_info
{
   char query_id[12];
   char field_num[4];
} init_info;
                 |<----- FIELD NUM --------------------->|
+------+---------+----+----+----+----+----+----+    +----+
|HEADER|INIT_INFO|NAME|    |    |    |    |    |    |    |
+------+---------+----+----+----+----+----+----+....+----+
NAME은 각 필드의 이름이다. 필드의 이름에는 '\0'이 들어갈 수 없으모 필드이름간의 구분은 '\0'을 이용하도록 한다.

  • 레코드의 길이를 알려줄 수 있어야 한다.
INIT패킷이 올라간 다음에는 쿼리결과 문이 레코드 단위로 넘어오게 된다. 쿼리 결과는 클라이언트에서 필드단위로 구분할 수 있어야 하므로 각 필드의 크기를 별도로 명시해줘야할 필요가 있다.
       |<-- FINFO -->|
+------+----+--------++----+--------++----+--------++----+--------+
|HEADER|SIZE| DATA 1 ||SIZE| DATA 2 ||SIZE| DATA 3 ||SIZE| DATA 4 |
+------+----+--------++----+--------++----+--------++----+--------+
  • 여러개의 레코드가 전송될 경우 시작과 끝을 명확히 할 수 있어야 한다.
시작은 INIT패킷으로 명확히 전달할 수 있다. 전송의 끝은 HEADER의 TYPE에 FIN을 설정함으로서 이루어진다. 다음은 실제 클라이언트와 서버간의 쿼리요청과 결과에 대한 패킷통신 시나리오다.
+----+----+----+---+--------------+
|A002|TYPE|size|QID| QUERY STRING | QUERY REQUEST
+----+----+----+---+--------------+
+----+----+----+---+-----------+
|Q002|INIT|size|QID| INIT_INFO |    DATA START  ----+
+----+----+----+---+-----------+                    | (      ) 
+----+----+----+---+--------------+                 |
|Q002|TYPE|size|QID| QUERY RESULT | DATA            |
+----+----+----+---+--------------+                 |
......                                              |
+----+----+----+---+-----------+                    |
|Q002| FIN|size|QID| INIT_INFO |    DATA END    ----+
+----+----+----+---+-----------+

  • 가능한 압축된 데이터여야 한다.
패킷에서 쓸데없는 부분은 가능한 제거 시켜야 한다. 프로토콜은 가능한 작고 효율적으로 응용을 지원할 수 있도록 작성되어져야 한다.

  • 레코드 전송중 에러가 발생했다면 에러 정보도 전송 가능해야 한다.
TYPE를 통해서 지원할 수 있다. 발생가능한 에러들에 대해서 가능한 상세하게 정의해야 한다.

RDBMS 구현 SPEC

SQLite 자체적으로 보자면 RDBS로서 가져야할 몇 가지 주요기능들이 제외되어 있다. 어디까지나 로컬 시스템에서의 복잡하지 않은 DB 관리용으로 용도를 제한하고 있기 때문이다. 그러므로 이들 기능을 SSE에서 대신 구현해주어야 한다. 구현하기 위해서는 필요조건을 확인해야 한다. 여기에서는 RDBMS의 기능을 수행하기 위해서 필요한 기능들을 정의하고 어떤 방식으로 SSE에서 지원할 것인가를 정의 하도록 한다.

인증 구현 SPEC

RDBMS는 당연하지만 인증이 구현되어야 한다. 여기에서는 인증구현과 관련된 스팩을 정의 한다. Mysql의 인증 방식을 참고하면 될것 같다. 우선은 mysql의 인증 테이블을 참고하도록 한다.

유저 정보 DB

mysql, pgsql등을 보면 유저데이터 저장을 위한 별도의 데이터베이스와 테이블을 유지한다. 유저 정보를 위한 DB의 이름은 userinfo로 한다. userinfo 데이터 베이스에는 host, user, db 테이블이 있다. IPv6를 지원할 수 있도록 구성되어야 한다. mysql과 거의 동일하게 구성하도록 했다.
+-----------------+-----------------+------+-----+---------+-------+
| Field           | Type            | Null | Key | Default | Extra |
+-----------------+-----------------+------+-----+---------+-------+
| Host            | char(60) binary |      | PRI |         |       |
| User            | char(16) binary |      | PRI |         |       |
| Password        | char(16) binary |      |     |         |       |
| Select_priv     | enum('N','Y')   |      |     | N       |       |
| Insert_priv     | enum('N','Y')   |      |     | N       |       |
| Update_priv     | enum('N','Y')   |      |     | N       |       |
| Delete_priv     | enum('N','Y')   |      |     | N       |       |
| Create_priv     | enum('N','Y')   |      |     | N       |       |
| Drop_priv       | enum('N','Y')   |      |     | N       |       |
| Reload_priv     | enum('N','Y')   |      |     | N       |       |
| Shutdown_priv   | enum('N','Y')   |      |     | N       |       |
| Grant_priv      | enum('N','Y')   |      |     | N       |       |
| References_priv | enum('N','Y')   |      |     | N       |       |
| Index_priv      | enum('N','Y')   |      |     | N       |       |
| Alter_priv      | enum('N','Y')   |      |     | N       |       |
+-----------------+-----------------+------+-----+---------+-------+
  1. Host : IPv6에 대응될 수 있어야 하기 때문에 충분한 공간을 확보해야 한다.
  2. Password : crypt + md5 를 통해서 사용자 패스워드를 암호화 시킨다.

host 테이블

호스트에 대한 인증 여부 체크를 위한 테이블 이다. 필요없는 필드를 제외한 것 외에는 mysql의 host테이블을 그대로 사용했다.
+-----------------+-----------------+------+-----+---------+-------+
| Field           | Type            | Null | Key | Default | Extra |
+-----------------+-----------------+------+-----+---------+-------+
| Host            | char(60) binary |      | PRI |         |       |
| Db              | char(64) binary |      | PRI |         |       |
| Select_priv     | enum('N','Y')   |      |     | N       |       |
| Insert_priv     | enum('N','Y')   |      |     | N       |       |
| Update_priv     | enum('N','Y')   |      |     | N       |       |
| Delete_priv     | enum('N','Y')   |      |     | N       |       |
| Create_priv     | enum('N','Y')   |      |     | N       |       |
| Drop_priv       | enum('N','Y')   |      |     | N       |       |
| Grant_priv      | enum('N','Y')   |      |     | N       |       |
| Index_priv      | enum('N','Y')   |      |     | N       |       |
| Alter_priv      | enum('N','Y')   |      |     | N       |       |
+-----------------+-----------------+------+-----+---------+-------+

서버/클라이언트간 세션성립

클라이언트와 서버간 세션이 만들어 지기 위해서 클라이언트는 아이디와 패스워드 쌍을 서버에 전송한다. 아이디/패스워드를 받은 서버는 host, user테이블을 이용해서 host, user, password가 모두 허용하는 값인지를 확인한후 문제 없으면 세션을 성립시킨다. 다음은 서버/클라이언트간 세션을 만들기 위한 프로세스다.
                            +-----------------------------------+
                    4.      |                                   | 
     +-------CLOSE-------------------+       +---------------+  |
     |   1.                 |    2.  |       |  SQLITE DB    |  |
 +--------+  ID, PASSWORD   | +--------+     | +------+-----+|  |
 | Client | ----------------->| MS     |-----|>| USER | HOST||  |
 +--------+                 | +--------+     | +------+-----+|  |
     |                      |     |  |       +------|--------+  | 
     +----------CONNECT-----------+  +------<<------+           |
             3.             |                                   |
                            | HOST                              |
                            +-----------------------------------+
  1. 클라이언트는 Server에 연결을 시도한다. 이때 ID와 패스워드를 보낸다.
  2. MS는 USER, HOST DB를 확인한다.
  3. host, id, password가 인증가능한 상태라면 Client에게 Connection 메시지를 보내고 세션을 만든다.
  4. 실패했다면 클라이언트에게 Close 메시지를 보내고 연결을 끊는다.
세션 성립후 유저 권한 정보의 유지
세션연결이 성공했다면 유저의 권한 정보(DB에 대한 읽기/쓰기/삭제 등)를 유지해야 한다. 세션연결이 성공하면 유저의 이러한 권한 정보를 위해서 자료구조가지고 있어야 한다. 이러한 자료구조는 다음과 같이 구성하도록 한다.

// GrantBit 
#define  GREAD    1
#define  GWRITE   1 << 1
#define  GUPDATE  1 << 2 
#define  GCREATE  1 << 3
#define  GDROP    1 << 4  
#define  GALTER   1 << 5
#define  GINDEX   1 << 6

#define GREAD     GSELECT 

typedef int Grantbit;
struct DbGrant
{
    char dbname[MAX_DB_LEN];
    int  grantbit;
    int  status;
    uint opentime;
    char lastquery[MAX_DB_QUERY];
};

struct UserInfo
{
    int                         sockfd;
    struct sockaddr_in          addr;
    vector<DbGrant>             dbgrant;  
};

vector<UserInfo> UInfo;
DbGrant에는 각종 메서드들 - 즉 grantbit와의 비트연산을 통한 유저의 DB(dbname)에 대한 권한을 검사하는 루틴을 포함한 - 이 올 수 있다.

클라이언트가 서버로 연결 후 일정 시간 동안 클라이언트로 부터 아무 데이터를 받지 않는 경우 섹션을 자동으로 닫아버려 MS의 부하를 줄이는 것도 좋은 방법일듯 합니다. - 멍

데이터 보안 구현 SPEC

서버와 클라이언트 데이터간의 데이터가 도청당하지 않도록 장치를 구현한다. SSL이 가장 유망할 것으로 생각된다.

무선랜(802.11b) 보안에서 Station(PC, Notebook, PDA)과 AP(Access Point), Radius(인증 서버)간에 인증 프로토콜으로 사용하는 EAP-MD5나 EAP-TLS(Transport Layer Secure)방식을 사용하면 좋긴 한데 생각보다 작업량이 많아질 수 있다. EAP-TLS를 이용한 인증 방식은 Station과 Radius간에 AP가 인증서 교환을 중계하여 인증 성공 후에 Station과 AP가 각각 WEP Key를 생성하여 패킷 암호화하여 실제로 송수신함으로써 인터넷 서비스를 시작하게 된다. - 멍

Management SPEC

각 DB파일 마다 유지해야 할 데이터들(열린시간, 마지막 사용시간, 사용중인지, 쿼리 처리 개수, 에러 개수, 현재 진행중인 SQL문, 마지막 수정된 row 카운트, 전체 row 갯수 등..)을 정하고 이것들을 메모리에만 유지할 지(몇가지 정보들을 DB오픈시마다 알아내야 한다), 따로 저장을 해놓을지(데이터 무결성에 문제가 생길지 모른다) 를 결정하고 이것에 대한 설계를 해야 합니다.
  • 음.. 서버모델을 어떻게 가져갈지 아직 결정이 안된것 같지만 공유데이터 영역을 만들고 거기에 이들 정보를 넣는건 어떨런지요. 공유 메모리를 구성하기 위해서는 선택의 여지가 있겠지만 mmap과 세마포어 정도면 무난 할것 같습니다. 물론 서버가 쓰레드 모델이라면 다른 도구를 이용해야 할겁니다.
    
      |<------------------공유메모리-------------------------->|
      |<-- one db -->|
      +---+---+--+---++---+---+--+---++---+---+--+---+
      |DID|UID|ST|NUM||DID|UID|ST|NUM||DID|UID|ST|NUM|
      +---+---+--+---++---+---+--+---++---+---+--+---+     .....
      |<---------------------------------------------- MS DBINFO 
      DID : DB ID
      UID : 가장 최근 query를 내린 유저
      ST  : 가장 최근 query의 상태  
      NUM : 현재 open중인 유저의 수
    1. MS DBINFO는 MS가 올라오면 작성하도록 하면 되겠구요.
    2. UID는 최근 쿼리를 내린 유저의 ID입니다.
    3. ST는 최근의 query의 상태를 나타냅니다. query의 상태가 중요한 경우는 update, insert와 같은 경우일 겁니다. 만약 update, insert와 같이 테이블의 내용이 변경되는 쿼리의 경우 다른 프로세스에게 정보를 알려줄 필요가 있기 때문입니다. 0보다 더 크면 update, insert와 같은 쿼리가 진행되고 있음을 의미합니다.
    4. NUM은 이 DB를 열고 있는 유저의 수를 나타냅니다.
  • 현재 pre-alpha 까지는 DB가 열린 시간, 마지막 접근 시간, 전체 처리한 쿼리수, 성공한 쿼리수, 실패한 쿼리수, DB가 열린 후 현재까지 평균 쿼리수(q/s) 를 응답합니다. 앞으로는 현재 열린 DB의 목록, DB들이 가진 테이블의 목록, 테이블의 row수 등 많은 부분에 대한 정보를 제공해야 합니다. (소타)

    백업 SPEC

    원격 리플리케이션

    2개 이상의 MS상에서 마스터, 슬레이브의 개념을 두고 마스터는 row change가 일어난 쿼리문을 모두 로깅해서 슬레이브가 가져갈 수 있는 통로를 열어줘야 한다. 이 부분에 대한 분석, 설계가 필요함

    이 부분에 대해 짚고 넘어가야 할 것이 현재 vm단위의 처리로 인해 변경된 row의 숫자 확인이 불가능합니다. 아래 RAID 미러링도 마찬가지입니다.. 계속 찾아보겠습니다. (소타)

    RAID 미러링

    RAID 미러링을 모방한 백업에 대한 분석, 설계가 필요하다. 설정파일에 적힌대로 백업 경로가 있으면 현재 열어야 하는 DB파일을 복사하고 모든 row change 되는 쿼리들을 2DB에 적용해야 한다. 퍼포먼스에 큰 영향을 끼치게 되지만 백업 이라는 요소가 빠지면 실무에 적용하기가 힘들어 진다.

    멤버들

    1. yundream
    2. 멍 3. 소타 = nonun ;; 4. [minsu]

    관련 링크

    잡담

    제가 생각하는 구성
     +------+
     | INIT |
     +------+
     +-----+----+------+----+------+----+------+ 
     |Total|size|value1|size|value2|size|value3|  Record 1
     +-----+----+------+----+------+----+------+
     +-----+----+------+----+------+----+------+ 
     |Total|size|value1|size|value2|size|value3|  Record 2 
     +-----+----+------+----+------+----+------+
     +-----+----+------+----+------+----+------+ 
     |Total|size|value1|size|value2|size|value3|  Record 3
     +-----+----+------+----+------+----+------+
    • 제가 만들었던 DB는 아래와같이 Tree구조출력도 지원가능합니다. (젠투 포티지를 몽땅 넣어본겁니다.) 보기 편하쟎아요? 파일시스템 없이도 사용가능하지요~ 한번 고려해주세요. 파일시스템 없이 구현하는것을... - [minzkn]
    t
    • minzkn님 그 DB가 어디에 있어요?
      • 자체 포멧이고요. 비공개입니다. 파일시스템에 의존하지 않고 직접 저장할수 있고 자체 format을 사용하고요. 기본적으로 저널링이 가능토록 만든것이고요. 개인적으로 만들고 있는 운영체제(MINZ)의 일부기능을 조금 뺄것(사실은 무지 많이 빼먹음)은 빼고 해서 단순화해서 리눅스용으로 포팅한겁니다. 캐쉬를 조금 하고요. 리눅스용은 MINZ용보다 기능적으로 많은 부분이 누락되어 있어요. 사실 ext3/NTFS와 대응하려고 만들었던 일종의 파일시스템의 개념에 가까워요. 그냥 보기의 편리성과 파일시스템의 비의존성에 의한 저널링기법의 도입을 한번 고려해보시면 어떨지 의견드린겁니다. 소스 넘보지 마세요~ ㅋㅋ - [minzkn]
        • 저런 비공개 군요 -.-; sqlite를 선택한 이유는 sql92의 대부분의 기능을 지원하기 때문이였습니다. 클라이언트 입장에서는 아무래도 sql이 지원되는 DB가 응용이나 관리가 편할것 같아서요. 아 그런데 파일 시스템 없이 사용한다는 것은 무슨 뜻이죠 ? 메모리에서 관리한다는 건지요 ? 아니면 RAW DISK 사용 ? 저널링기법이라 하심은 일반적으로 파일시스템의 빠른 복구를 위해서 사용하는 그 저널링을 말씀하시는 건가요 ? 저널링 기법에 대한 문서가 있으면 부탁해요 - [yundream]
      • 좀 설계를 처음부터 정리할 필요가 있는거 같습니다. UML로 좀 더 이쁘게 다듬어 보는게 어떨까요? --[minsu]

        참고 문헌

        1. SQLite 프로그래밍
        2. SQLite 홈페이지
        3. SQLIte 구조
        4. SQLite console 프로그램 분석

        번역 교정 요청!

        "The Architecture Of SQLite"를 번역한 내용 좀 교정봐주셨으면 합니다. 그대로 올릴려면 그대로 올리기엔 너무 허접하고, 오역으로 인해 잘못된 정보를 습득하여 헷갈리는 그런 상황이 발생하면 않될꺼같아서요

        원문 사이트: http://www.sqlite.org/arch.html

        아무나 연락 주시면 파일을 보내드리겠습니다. [멍]
        • 음 일단 번역한 부분만이라도 올리는게 좋지 않을까요 ? 잘못된 부분이 있다면 관심있어 하는 누군가가 수정해 주겠죠 - yundream
        sqlite3가 나오면서 중지했던 프로젝트를 최근 sqlite3를 이용한 버전으로 다시 개발했습니다. 프로토콜은 HTTP를 그대로 사용하고 응답은 XML로 하게 되었습니다. 몇가지 SQL을 추가했습니다. http://sqlitedbms.sourceforge.net/