Hôm nay tôi phát hiện ra ổ cứng lưu trữ cơ sở dữ liệu của tôi đã đầy. Điều này đã xảy ra trước đây, thường là nguyên nhân khá rõ ràng. Thông thường có một truy vấn xấu, gây ra sự cố tràn lớn đến tempdb, phát triển cho đến khi đĩa đầy. Lần này nó ít rõ ràng hơn những gì đã xảy ra, vì tempdb không phải là nguyên nhân của toàn bộ ổ đĩa, đó là chính cơ sở dữ liệu.
Sự thật:
- Kích thước cơ sở dữ liệu thông thường là khoảng 55 GB, nó tăng lên 605 GB.
- Tệp nhật ký có kích thước bình thường, datafile là rất lớn.
- Datafile có 85% dung lượng khả dụng (Tôi hiểu đây là 'không khí': không gian đã được sử dụng, nhưng đã được giải phóng. SQL Server dành toàn bộ không gian sau khi được phân bổ).
- Kích thước Tempdb là bình thường.
Tôi đã tìm thấy nguyên nhân có thể; có một truy vấn chọn quá nhiều hàng (tham gia xấu gây ra lựa chọn 11 tỷ hàng trong đó dự kiến sẽ có một vài trăm nghìn). Đây là một SELECT INTO
truy vấn, khiến tôi tự hỏi liệu kịch bản sau đây có thể xảy ra hay không:
- CHỌN VÀO được thực thi
- Bảng mục tiêu được tạo
- Dữ liệu được chèn khi nó được chọn
- Đĩa bị đầy, khiến cho việc chèn không thành công
- CHỌN VÀO bị hủy bỏ và khôi phục
- Rollback giải phóng không gian (dữ liệu đã chèn được xóa), nhưng SQL Server không giải phóng không gian giải phóng.
Tuy nhiên, trong tình huống này, tôi không mong đợi bảng được tạo bởi SELECT INTO
vẫn còn tồn tại, nó sẽ bị loại bỏ bởi rollback. Tôi đã thử nghiệm điều này:
BEGIN TRANSACTION
SELECT T.x
INTO TMP.test
FROM (VALUES(1))T(x)
ROLLBACK
SELECT *
FROM TMP.test
Kết quả này trong:
(1 row affected)
Msg 208, Level 16, State 1, Line 8
Invalid object name 'TMP.test'.
Tuy nhiên, bảng mục tiêu không tồn tại. Truy vấn thực tế không được thực hiện trong một giao dịch rõ ràng, điều đó có thể giải thích sự tồn tại của bảng mục tiêu không?
Những giả định tôi đã phác thảo ở đây có đúng không? Đây có phải là một kịch bản có khả năng đã xảy ra?