2017-02-18 8 views
0

데이터베이스에서 ACID 용어를 수행 할 때 한 번에 한 사용자에게 데이터베이스 테이블을 잠글 수 있는지 알고 싶습니다. VBA를 사용하는 Microsoft Access 데이터베이스의 시간. 난 의사 코드에서 다음과 같은 것을 찾고있다.Microsoft Access VBA에서 한 번에 한 사용자에게 데이터베이스 테이블 잠그기

  • 모든 테이블 (또는 특정 테이블)을 잠급니다.
  • 모든 SQL 또는 다른 내부 조작을 수행하십시오.
  • 트랜잭션을 수행하고 모든 테이블 (또는 특정 테이블)의 잠금을 해제하십시오.

그러나 클라이언트 실패의 경우. 클라이언트 응용 프로그램이 중단되고 사용자가 강제로 트랜잭션을 처리하는 동안 클라이언트 응용 프로그램을 강제 종료해야합니다. 변경 사항을 되돌리고 실제로 트랜잭션을 수행하지 않으며 잠금을 해제합니다. 내가 찾고있는 것은 READ 및 WRITE 잠금이고, 이미 잠긴 상태에서 데이터베이스를 잠그려고하는 클라이언트는 잠길 때까지 기다려야 만 할 것입니다. 오류가 잠재적 인 경우

Dim wks  As DAO.Workspace 
Dim dbs  As DAO.Database 

Set wks = DBEngine(0) 
Set dbs = wks.Databases(0) 

wks.BeginTrans 
    ' Do stuff using dbs and DAO. 
wks.CommitTrans 

Set dbs = Nothing 
Set wks = Nothing 

이 적 CommitTrans 및 통화 건너 뛰고 오류 처리기 다음과 같습니다 :

+0

이것은 원하는 것의 시작입니다. http://stackoverflow.com/questions/5792169/opening-access-database-in-exclusive-mode#answer-5792773 –

답변

1

작업 공간의 트랜잭션 내에서 거래를 감싸 사실

wks.RollBack 
+0

하지만 독서도 차단하지 않습니다. 나는 그것을 전에 시험해 보았다!! – falhumai

+2

귀하의 질문에 귀하의 문제가 해결되지 않는다고 생각하는 이유가 언급되어 있어야합니다. 다른 사용자가 트랜잭션이 실행되는 동안 읽기 액세스 권한을 갖고 있지 않아야하는 이유는 여전히 분명하지 않습니다. ACID (Access가이를 준수하지는 않지만)는 데이터베이스에 일관성없는 상태가 없음을 보장합니다. 트랜잭션이 * 성공적으로 완료되었거나 전혀 완료되지 않습니다. 그 사이에는 아무 것도 없습니다. 다른 사용자의 트랜잭션 중 동시 읽기는 ACID가 보장하는 핵심 기능입니다. – Leviathan

+1

@ Leviathan이 옳습니다. 사용자가 파일에 액세스 할 수있는 경우 읽기를 차단할 수있는 방법이 없습니다. 읽기는 가능한 최저 수준의 접근입니다. 실제로 데이터베이스를 사용하는 사용자가없는 경우에만 액세스를 차단할 수 있습니다. 첫 번째 사용자는 독점적으로 파일을 열 수 있습니다 (단일 사용자 모드라고 할 수 있습니다). 그러면 다른 사용자가 데이터베이스를 열 수 없습니다. 그러나 VBA에서는이 작업을 수행 할 수 없습니다.이 작업은 명령 줄에 의해 제어됩니다. – Gustav

0

을 나는 방법에 발견 구성된 해킹 잠금 유형을 통해 읽기 및 쓰기를위한 단일 사용자 액세스를 시뮬레이트합니다. 다음은 어떻게 달성했는지 설명합니다.

예를 들어 Lock이라는 작은 테이블에 액세스하고 SomeValue이라는 열이 있습니다. 이 열은 기본 키이어야하며 어떤 값일 수도 있으므로 예를 들어 유형 번호로 만들었습니다. 이 테이블은 그 안에 만들어 질 모든 자물쇠를 저장하고, 자물쇠를 얻으려는 쪽은 자물쇠 값에 대해 동의해야합니다. 예를 들어 두 클라이언트는 값 1의 잠금을 획득하려고 시도하므로 잠금 1을 요청하고 잠금 1을 해제해야합니다.

SetLock 쿼리 :

INSERT INTO Lock (SomeValue) 
VALUES ([GetLockValue]); 

ReleaseLock을

첫째, 여기에 내가 설정하고 잠금의를 취득하려고 측면을 값을 전달하여 잠금을 해제하기 위해 만든 두 도우미 쿼리는 질의 : 다음

DELETE * 
FROM Lock 
WHERE SomeValue=[GetLockValue]; 

, 여기에 1 패스이고, 설정 결과 값 전달의 잠금을 설정하고 반환하려고 할 것 TrySetLock 기능 (이며, 0은 FA입니다 - 값 전달 된 그것을 획득 비어에 의해 잠금 될 때까지 대기 위원장)과 SetLock 서브는 (은 잠금이 획득 스핀 잠금 방식) 사용

Public Function TrySetLock(LockValue As Integer) As Integer 
    Dim dbs As dao.Database 
    Dim qdf As dao.QueryDef 
    Set dbs = CurrentDb 
    Set qdf = dbs.QueryDefs("SetLock") 
    qdf.Parameters("GetLockValue").Value = LockValue 
    qdf.Execute 
    TrySetLock = qdf.RecordsAffected 
End Function 

Public Sub SetLock(LockValue As Integer) 
    Do While TrySetLock(LockValue) = 0 
    Loop 
End Sub 

을 그리고 여기 (이 릴리스 것 ReleaseLock 하위입니다 값 전달에 의한 잠금 -이 하위 항상) 그러한 잠금이 존재하지 않는 경우에도 성공 : 당신이 여기에서 볼 수있는 바와 같이

Public Sub ReleaseLock(LockValue As Integer) 
    Dim dbs As dao.Database 
    Dim qdf As dao.QueryDef 
    Set dbs = CurrentDb 
    Set qdf = dbs.QueryDefs("ReleaseLock") 
    qdf.Parameters("GetLockValue").Value = LockValue 
    qdf.Execute 
End Sub 

, 나는 SQL 및 Microsoft의 기본 키 속성의 도움을 사용했다 테이블에 액세스하여 삽입 (또는 여기에서 잠금으로 참조)은 한 번에 한쪽 또는 클라이언트에서만 성공할 수 있으며 다른 쪽에서는 성공하지 못합니다. 첫 번째 측면은 양측이 동의하는 동일한 값의 잠금을 제거 (또는 해제)합니다.

그러나 이것은 하나의 클라이언트가 잠금을 해제하지 못하면 (예를 들어 클라이언트의 프로그램이 고정되어있어 강제로 프로그램을 강제 종료해야하는 경우) 동일한 잠금을 사용하는 모든 클라이언트를 차단하는 문제를 일으 킵니다. 프로그램이 강제 종료 될 때 Class 모듈의 소멸자가 호출되는지 여부를 알고 싶습니다. 그것이 호출되면, 나는이 문제가 어떤 값을 가진 잠금 클래스를 만들어서 고쳐질 수 있다고 생각한다. 그리고 그 클래스의 destuctor는 잠금을 해제하고 다른 클라이언트가 그 특정 잠금을 기다릴 필요가 없다.