2011-11-26 3 views
3

지금까지 우리 응용 프로그램에서는 SQLObject가있는 SQLite 데이터베이스를 ORM으로 사용했습니다. 분명히 어느 시점에서 우리는 SQLite 동시성 문제에 직면해야한다는 것을 알았고 그렇게했습니다.SQLObject를 사용하여 하나의 sqlite 데이터베이스에서 여러 SQLite 데이터베이스로 데이터 이동

우리는 현재 데이터베이스를 여러 데이터베이스로 분할했습니다. 각 테이블 스키마는 동일하게 유지되지만 서로 다른 테이블을 긴밀하게 결합 된 여러 데이터베이스에 분산 시켰습니다.

이제는 새 버전의 응용 프로그램을 새로 설치할 때 매우 잘 작동하지만 이전 버전의 응용 프로그램을이 새 버전으로 업그레이드하려면 응용 프로그램을 시작하기 전에 특수 데이터 마이그레이션이 필요합니다. 이 경우 데이터베이스 이주는이 단일 데이터베이스의 테이블을 적합한 다른 데이터베이스로 간단하게 이동합니다.

는이 오래된 구조 고려 예시하려면

single_db.db --- 하나의 DB

* A -- Table A 
* B -- Table B 
* C -- Table C 
* D -- Table D 
* E -- Table E 
* F -- Table F 

새로운 구조 :

db1.db --- 데이터베이스 (1)

- A -- Table A 
- B -- Table B 
- C -- Table C 
- D -- Table D 

db2.db --- 데이터베이스 2

- E -- Table E 

db3.db --- 데이터베이스 3

- F -- Table F 

업그레이드가 일어날 때, 우리의 응용 프로그램은 위의 세 데이터베이스와 그들에 빈 테이블에 새로운 구조를 만들 것입니다. 또한 모든 테이블과 실제 데이터가있는 이전 데이터베이스 single_db.db가 있습니다. 이제 응용 프로그램이 작동하기 전에 테이블을 이동해야합니다. 그렇지 않으면 이전 데이터베이스의 테이블에서 해당하는 새 데이터베이스의 해당 테이블로 데이터를 복사해야합니다.

이 데이터베이스 마이그레이션을위한 코드를 작성해야합니다. 이전 데이터베이스 연결을 사용하여 테이블을 쿼리하고 새로운 데이터베이스 연결을 사용하여 반환 된 행을 해당 테이블에 삽입 할 수 있다는 것을 알고 있습니다. 여기서 언급해야 할 한 가지주의 사항은 이러한 테이블 중 일부는 많은 수의 행을 포함 할 수 있다는 것입니다. 행은 2/3 테이블에서 2 ~ 250 만 개가 될 수 있습니다.

SQLite 위에 SQLObject를 사용하고 있기 때문에 다른 SLQObject 트릭을 사용할 수 있는지 물어보고 싶습니다.

도움 주셔서 감사합니다.

답변

1

나는 이것이 지금까지는 아마 해결되었다는 것을 알았지 만, 내가 검색 한 것과 거의 동일한 작업을 수행해야했던 사람들에게 이것은 내가 사용한 코드의 핵심 부분이었습니다 (발견 된 것에서 수정되었지만 '는 t는 다시 사과를 원래의 저자를 신용 찾을!)

def _iterdump(connection, table_name): 
    """ 
    Returns an iterator to dump a database table in SQL text format. 
    """ 

    cu = connection.cursor() 

    yield('BEGIN TRANSACTION;') 

    # sqlite_master table contains the SQL CREATE statements for the database. 
    q = """ 
     SELECT name, type, sql 
     FROM sqlite_master 
      WHERE sql NOT NULL AND 
      type == 'table' AND 
      name == :table_name 
     """ 
    schema_res = cu.execute(q, {'table_name': table_name}) 
    for table_name, type, sql in schema_res.fetchall(): 
     if table_name == 'sqlite_sequence': 
      yield('DELETE FROM sqlite_sequence;') 
     elif table_name == 'sqlite_stat1': 
      yield('ANALYZE sqlite_master;') 
     elif table_name.startswith('sqlite_'): 
      continue 
     else: 
      yield('%s;' % sql) 

     # Build the insert statement for each row of the current table 
     res = cu.execute("PRAGMA table_info('%s')" % table_name) 
     column_names = [str(table_info[1]) for table_info in res.fetchall()] 
     q = "SELECT 'INSERT INTO \"%(tbl_name)s\" VALUES(" 
     q += ",".join(["'||quote(" + col + ")||'" for col in column_names]) 
     q += ")' FROM '%(tbl_name)s'" 
     query_res = cu.execute(q % {'tbl_name': table_name}) 
     for row in query_res: 
      yield("%s;" % row[0]) 

원래 DB에 대한 SQLite는 연결하고 원래의 테이블의 이름을 전달하면이 발전기는 당신이 할 수있는 명령을 다시 줄 것이다 DB를 새 db에 대해 sqlite 객체에서 실행하도록 전달합니다.

내가이 작업을 수행했을 때 모든 테이블에서 행 개수를 먼저 계산하고 INSERT 행을 실행하여 카운터를 증가 시켜서 마이그레이션 진행 상황을 보여줄 수있었습니다.