IT TIP

Python SQLite에서 데이터베이스 연결을 닫지 않으면 어떻게 되나요?

itqueen 2021. 1. 8. 22:40
반응형

Python SQLite에서 데이터베이스 연결을 닫지 않으면 어떻게 되나요?


이런 짓을하고 있어요 ...

conn = sqlite3.connect(db_filename)

with conn:
    cur = conn.cursor()
    cur.execute( ... )

with변경 사항을 자동으로 커밋합니다. 그러나 문서는 연결을 닫는 것에 대해 아무것도 말하지 않습니다.

실제로 나는 conn(내가 테스트 한) 나중 문장에서 사용할 수있다 . 따라서 컨텍스트 관리자가 연결을 닫지 않는 것 같습니다.

수동으로 연결을 종료해야합니까? 열어두면 어떻게 되나요?

편집하다

내 결과 :

  • 연결이 종료되지 않은 상황에 맞는 관리자에 나는 테스트를 확인했다. __exit__, 컨텍스트 관리자 만 수행하여 변경 사항을 커밋conn.commit()
  • with connwith sqlite3.connect(db_filename) as conn중 하나를 사용하여 살아 연결을 유지할 수 있도록, 동일
  • with 문은 새 범위를 생성하지 않으므로 with 제품군 내에서 생성 된 모든 변수는 외부에서 액세스 할 수 있습니다.
  • 마지막으로 연결을 수동으로 닫아야합니다.

SQLite 데이터베이스를 닫지 않으면 어떤 일이 발생하는지에 대한 구체적인 질문에 대한 대답은 매우 간단하며 모든 프로그래밍 언어에서 SQLite를 사용하는 데 적용됩니다. 연결이 코드에 의해 명시 적으로 또는 프로그램 종료에 의해 암시 적으로 닫히면 처리되지 않은 트랜잭션이 롤백됩니다. (롤백은 실제로 데이터베이스를 열기 위해 다음 프로그램에 의해 수행됩니다.) 열려있는 미해결 트랜잭션이 없으면 아무 일도 일어나지 않습니다.

즉, 프로세스가 종료되기 전에 항상 데이터베이스를 닫는 것에 대해 너무 걱정할 필요가 없으며 트랜잭션을 시작하고 적절한 지점에서 커밋하도록주의를 기울여야합니다.


여기에 유효한 근본적인 문제가 있지만 sqlite가 어떻게 작동하는지 이해하는 것도 중요합니다.

1. connection open
    2. transaction started
        3. statement executes
    4. transaction done
5. connection closed

데이터 정확성 측면에서 트랜잭션에 대해서만 걱정하면되고 핸들을 열지 않아도됩니다. sqlite는 트랜잭션 (*) 또는 명령문 실행 내부의 데이터베이스에만 잠금을 보유합니다.

그러나 리소스 관리 측면에서 , 예를 들어 sqlite 파일을 제거하거나 너무 많은 연결을 사용하여 파일 설명자가 부족할 수있는 경우 트랜잭션 외 연결 열기에도 신경을 씁니다.

연결이 닫히는 방법에는 두 가지가 있습니다. .close()명시 적으로 호출 한 후에 핸들이 있지만 사용할 수 없거나 연결이 범위를 벗어나 가비지 수집됩니다.

당신이 경우 연결을 종료해야합니다 가까이, 명시 적으로, 파이썬의 모토에 따라 " 노골적인 암시보다 낫다 ."

부작용에 대한 코드 만 확인하는 경우 연결에 대한 참조를 보유하는 마지막 변수가 범위를 벗어나는 것이 허용 될 수 있지만 예외가 스택을 캡처하므로 해당 스택의 참조가 있음을 명심하십시오. 예외를 전달하면 연결 수명이 임의로 연장 될 수 있습니다.

프로그래머에게주의해야합니다 . sqlite는 기본적으로 "지연된"트랜잭션을 사용합니다. 즉, 트랜잭션은 명령문을 실행할 때만 시작됩니다. 위의 예에서 트랜잭션은 2-4가 아닌 3-4에서 실행됩니다.


이것이 제가 사용하는 코드입니다. Connection하고는 Cursor자동으로 가까운 덕분 것이다 contextlib.closing(). Connection자동으로 컨텍스트 매니저 덕분에 커밋됩니다.

import sqlite3
import contextlib

def execute_statement(statement):
    with contextlib.closing(sqlite3.connect(path_to_file)) as conn: # auto-closes
        with conn: # auto-commits
            with contextlib.closing(conn.cursor()) as cursor: # auto-closes
                cursor.execute(statement)

다음 with과 같은 블록을 사용할 수 있습니다 .

from contextlib import closing
import sqlite3

def query(self, db_name, sql):
    with closing(sqlite3.connect(db_name)) as con, con,  \
            closing(con.cursor()) as cur:
        cur.execute(sql)
        return cur.fetchall()
  • 연결
  • 거래를 시작하다
  • db 커서를 만듭니다.
  • preforms the operation and returns the results
  • closes the cursor
  • commits/rolls-back the transaction
  • closes the connection

all safe in both happy and exceptional cases


Your version leaves conn in scope after connection usage.

EXAMPLE:

your version

    conn = sqlite3.connect(db_filename) #DECLARE CONNECTION OUT OF WITH BLOCK

    with conn:                          #USE CONNECTION IN WITH BLOCK
        cur = conn.cursor()
        cur.execute( ... )

   #conn variable is still in scope, so you can use it again

new version

    with sqlite3.connect(db_filename) as conn:  #DECLARE CONNECTION AT START OF WITH BLOCK
        cur = conn.cursor()
        cur.execute( ... )   

   #conn variable is out of scope, so connection is closed 
   # MIGHT BE IT IS NOT CLOSED BUT WHAT  Avaris SAID!
   #(I believe auto close goes for with block)

For managing a connection to a database I usually do this,

# query method belonging to a DB manager class

def query (self, sql):
    con = sqlite3.connect(self.dbName)
    with con:
        cur = con.cursor()
        cur.execute(sql)
        res = cur.fetchall()
    if con:
        con.close()

    return res

doing so, I'm sure that the connection is explicitly closed.

ReferenceURL : https://stackoverflow.com/questions/9561832/what-if-i-dont-close-the-database-connection-in-python-sqlite

반응형