큰 삭제 쿼리가 정지 된 것 같습니다


10

우리는 18 억 행의 데이터베이스에서 삭제 쿼리를 실행했습니다. 이 삭제는 12 억 행을 삭제합니다.

가늠자에 따르면이 쿼리는 한 번에 100m로 분할되었지만 24 시간 동안 실행되고 로그 파일은 2Tb에 있으며 로그 파일에 허용되는 최대 크기 인 것으로 보입니다.

데이터베이스가 단순 복구 모드에 있습니다.

이 검색어를 저장 하시겠습니까? 아니면 SQL Server를 다시 시작하고 어떻게되는지 확인해야합니까? 데이터베이스를 사용할 수 없습니까? 가능한 한 깨끗하게 제거하기 위해 할 수있는 일이 있습니까?


SSMS에서 실행 했습니까? 그냥 취소하십시오. 취소하는 데 시간이 걸립니다. 그것이 달리고있는 한 좋아한다. 인내심을 가져야합니다.
paparazzo

1
@Graeme 10 억 개의 레코드 데이터베이스 (두 개의 데이터베이스를 실행)에 대한 경험을 통해 희생자 테이블에서 남은 레코드 를 저장하고 , 잘라 내고, 삭제하고, 저장된 레코드의 이름을 원래 이름으로 다시 변경 한 후 색인을 복원 하는 것이 더 빠릅니다. .
Anton Krouglov

1
이 spid를 지우고 나면 100m보다 훨씬 작은 배치를 권장합니다. 나는 보통 100k에서 1m를 수행합니다. 또한 기본 키를 WHERE 절로 사용하여 가능한 경우 삭제할 레코드를 선택하십시오.
BradC

대량의 데이터를 삭제하고 로그 문제를 피하려고 할 때 잘림은 친구입니다.
Jeff.Clark

답변:


14

우선, SQL 오류 로그가 실제로 로그의 최대 크기에 도달했는지 확인하십시오. 만약 그렇다면, 쿼리는 완료 될 희망이 없으며, 아마도 이미 롤백 상태에있을 것입니다.

그것이더라도, 나는 항상 수동으로 spid를 죽이는 것을 선호합니다 (spid를 사용 sp_who2하거나 sp_WhoIsActive찾은 다음 a kill 59또는 무엇이든하십시오). 명시적인 KILL을 수행하지 않으면 롤백 상태를 확인할 수도 없습니다 . 관련 스레드를 참조하십시오 .

이것은 업데이트이며 삽입이 아닌 삭제이므로 매우 운이 좋으며 즉시 롤백되는 것을 알 수 있습니다. 그렇지 않으면이 시점에 도달하는 것처럼 롤백하는 데 시간이 오래 걸릴 수 있습니다.

롤백 상태를 보려면

kill 59 with statusonly

불행히도, 나는 이것이 종종 유용한 것을 보여주지 않고 단지 "0 % 완료"를 발견했다. 이 경우 sp_who2IO 및 CPU를 사용 하고 감시하여 여전히 무언가를 수행하고 있는지 확인해야합니다.

재부팅과 관련하여 이는 심각한 위험입니다. spid가 활발하게 롤백하는 경우 (CPU 및 IO가 변경됨) SQL을 다시 시작하면 롤백이 완전히 완료 될 때까지 (시간 및 시간) 데이터베이스가 완전히 오프라인 상태가됩니다. 그러나 CPU와 IO가 움직이지 않으면 실제로 그것을 지울 수 있습니다. 어느 쪽이든 위험합니다.

마지막으로 옵션 일들이 특히 무서운 경우 : 당신은에서 백업이있는 경우 바로 삭제 (와 DB에 다른 업데이트가되지 않았습니다) 시작하기 전에 , 다음 회복하는 가장 빠른 방법은 단순히 DB를 드롭 할 수있다, 다시 시작 SQL 및 백업에서 복원

DB를 삭제할 수 없거나 (또는 ​​이미 인스턴스를 다시 시작한 후 SQL 오류 로그에서 24 시간 복구 시간을 예측하는 경우) SQL 서비스를 종료하고 디스크에서 MDF 및 LDF 파일을 삭제하고 SQL을 시작한 후 삭제하십시오. (고스트) 데이터베이스 및 백업에서 복원하십시오.

분명히 이것이 사용자가 상호 작용하지 않은 백엔드 처리 데이터베이스 인 경우에만 시도합니다.


3
복원 옵션에 대한 좋은 조언. 지옥처럼 무섭지 만 여전히 좋은 조언입니다.
Max Vernon

2
그러나이 상황에서 DBA가 인스턴스를 다시 시작하게함으로써 18-24 시간 동안 다운되거나 쿼리가 시작되기 전에 롤백하여 데이터가 손실되는 두 가지 매우 나쁜 옵션을 결정해야했습니다. 사업은 롤백하기로 결정했습니다.
BradC

1
3 월 4 일부터 전체 백업이 이루어지며 재부팅이 작동하지 않으면 최후의 수단으로 복원됩니다. 운 좋게도 우리가 정리하고 싶었던 정적 인 충분한 DB입니다. 의견을 보내 주셔서 감사합니다.
Graeme

4
@Graeme-FYI-12 억 행을 삭제하는 대신 테이블 구조의 복사본을 만들고 유지하려는 행을 새 테이블에 복사 한 다음 이전 테이블을 삭제하십시오. 방법을 묻는 새로운 질문을 추가하면 12 억 행을 삭제하는 것보다 훨씬 매끄러운 방법을 보여줄 수 있습니다.
Max Vernon

내 대답은 db가 SIMPLE 복구 모드에 있다고 가정합니다. FULL 모드 인 경우 대용량 트랜 로그 백업도 관리해야합니다.
BradC

8

SQL Server를 다시 시작하지 마십시오. 복구가 수행되므로 삭제를 포함하여 완료되지 않은 모든 트랜잭션을 롤백하거나 다시 실행할 수 있기 때문에 고통을 연장 할뿐입니다.

삭제를 실행중인 세션을 종료하면 롤백이 발생하고 완료하는 데 시간이 오래 걸립니다.

다음 쿼리를보고 작업 상태를 확인하려고합니다.

SELECT des.session_id 
    , des.host_name
    , des.login_name
    , der.command
    , der.estimated_completion_time
    , der.blocking_session_id
    , der.last_wait_type
    , der.percent_complete
    , der.start_time
    , der.status
    , der.wait_resource
    , der.wait_type
    , der.wait_time
FROM sys.dm_exec_sessions des
    INNER JOIN sys.dm_exec_requests der ON des.session_id = der.session_id
WHERE des.session_id <> @@SPID
    AND des.is_user_process = 1
ORDER BY des.session_id;

열과이 percent_complete열에 의존하는 열 estimated_completion_time은 다음 작업에 대해서만 채워집니다.

ALTER INDEX REORGANIZE
AUTO_SHRINK option with ALTER DATABASE
BACKUP DATABASE
DBCC CHECKDB
DBCC CHECKFILEGROUP
DBCC CHECKTABLE
DBCC INDEXDEFRAG
DBCC SHRINKDATABASE
DBCC SHRINKFILE
RECOVERY
RESTORE DATABASE
ROLLBACK
TDE ENCRYPTION

따라서 delete 문을 이미 취소하고 열을 롤백하거나 이미 SQL Server를 다시 시작하여 복구중인 경우에만 해당 열이 의미가 있음을 알 수 있습니다.

blocking_session_id열에 숫자가 포함되어 있으면 다른 세션이 삭제 작업을 차단하고 있음을 나타냅니다. 해당 세션이 시작된 이후 삭제 조작을 차단 한 경우 롤백을 수행하지 않아도 조작을 취소 할 수 있습니다.


좋은 쿼리이지만 삭제가 차단되면 로그가 커질 가능성이 거의 없습니다.
BradC

4
예. 출력을 약간 설명하려고합니다. 미래의 독자들도 이것을 볼 수 있습니다. 실제로 다음에 OP에서 소식을들을 지 의문입니다. 그는 매우 바쁠 것입니다.
Max Vernon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.