2010-10-13 38 views
6

Tôi cần phải thả và tạo lại một bảng, vốn tồn tại để "lưu trữ" chế độ xem đắt tiền. Chế độ xem có thể thay đổi và tôi muốn bảo trì dễ dàng nhất có thể, vì vậy tôi muốn bảng mới phản ánh phiên bản mới nhất của chế độ xem.Máy chủ SQL - Thả và Tạo lại một Bảng - Truy cập Chặn Trong khi Thực hiện

Tôi cũng muốn có thể ngăn chặn lỗi đọc nếu thủ tục cố gắng truy cập vào bảng trong khi đang ở giữa bị xóa và được tạo lại. Tôi đang sử dụng một giao dịch, nhưng tôi không chắc chắn nếu điều đó sẽ làm việc trên một bảng 'giảm' cho rằng phân chia thứ hai mà nó không tồn tại.

Tôi đã thực hiện kiểm tra cơ bản, 30 x SELECT từ chế độ xem trong vòng lặp trong khi chạy chế độ xem thả/tạo lại. Không có lỗi cho đến nay.

Tôi đã coi Truncate/Delete có chèn, nhưng các cột có khả năng thay đổi trên chế độ xem trong tương lai yêu cầu tôi giữ điều này linh hoạt nhất có thể và các cột cố định sẽ không giúp ích gì với điều này.

Bất cứ ai có thể cho tôi biết liệu giao dịch sẽ bảo vệ bảng khỏi truy cập đọc trong khi bị xóa và điều này là an toàn hoặc nếu có cách nào tốt hơn?

Drop/tái Code:

BEGIN TRAN 

    BEGIN TRY 

     DROP TABLE Persisted_View_1 

     SELECT * INTO Persisted_View_1 

     FROM View_1 

    END TRY 
    BEGIN CATCH 

     RAISERROR('The procedure proc_PersistView1 failed to commit, the transaction was rolled back', 16, 1) 

     IF @@TRANCOUNT > 0 
     BEGIN 
      ROLLBACK TRAN 
     END 

    END CATCH 

     IF @@TRANCOUNT > 0 
     BEGIN 
      COMMIT TRAN 
     END 

    GO 

UPDATE: truy vấn Revised Brads sau trả lời:

ALTER PROCEDURE proc_Drop_Recreate_Persisted_View_MyData 

AS 
BEGIN 

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 

    BEGIN TRAN 

     BEGIN TRY 

      -- Re create 

      SELECT * INTO Persisted_View_MyData_Temp FROM View_MyData 

      -- Create index on product ID 

      CREATE CLUSTERED INDEX [IX_ProductID_ProductTypeID] ON [dbo].[Persisted_View_MyData_Temp] 
      (
       [productID] ASC, 
       [productTypeID] ASC 
      ) 
      WITH 
      (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 

      -- Check and drop table 

      IF EXISTS (SELECT Id FROM sysObjects WHERE Name like 'Persisted_View_MyData') 
      BEGIN   
       DROP TABLE Persisted_View_MyData  
      END   

      EXEC sp_rename 'Persisted_View_MyData_Temp', 'Persisted_View_MyData' 

     END TRY 
     BEGIN CATCH 

      RAISERROR('The procedure proc_PersistViewMyData failed to commit, the transaction was rolled back', 16, 1) 

      IF @@TRANCOUNT > 0 
      BEGIN 
       ROLLBACK TRAN 
      END 

     END CATCH 

      IF @@TRANCOUNT > 0 
      BEGIN 
       COMMIT TRAN 
      END 


END 
+2

Thay vì sử dụng bảng lưu trong bộ nhớ cache thủ công này, bạn có thể thực hiện chế độ xem bằng cách đặt chế độ xem được lập chỉ mục không? Sau đó, SQL sẽ xử lý tất cả các chi tiết này cho bạn. (Lưu ý rằng một số cấu trúc nhất định trong chế độ xem có thể loại trừ điều này, như UNION hoặc GROUP BYs) – BradC

+0

@BradC, bạn có thể nhận xét thêm về cách tạo chế độ xem "chế độ xem được lập chỉ mục" không? – Brad

+0

@Brad Mở rộng nhận xét của tôi thành câu trả lời. Xem bên dưới. – BradC

Trả lời

8

Tôi sử dụng quy trình mà tôi đã đến để đặt tên là drop-flip- flop. Tôi đã sử dụng quá trình này với thành công lớn khi tạo bảng mất một thời gian và tôi không muốn tất cả các ứng dụng/người dùng cần bảng được tổ chức trong quá trình xây dựng lại này.

  1. Tạo phiên bản mới của bảng với một số tiền/hậu sửa chữa (ví dụ <TableName>_New)
  2. Drop item đang tồn tại (ví dụ DROP TABLE <TableName>)
  3. Đổi tên bảng mới với tên của bảng gốc (EXEC sql_rename...) [REF]

Tôi thường tạo một thủ tục được lưu với logic này và lên lịch cho công việc đó.


* Chú ý: Để tận dụng tối đa quá trình này, bạn sẽ cần phải tạo ra bất kỳ chỉ số bạn cần trên bảng mới giữa bước 1 và 2. Điều này có nghĩa rằng bạn sẽ phải sẵn/sau đó sửa chúng và đổi tên chúng cùng với bảng để tránh gặp sự cố khi tập lệnh chạy lại.

Để tăng cường bảo mật, bạn có thể tạo giao dịch quanh bước 2 và 3. Đặt mức cách ly thành Serialized sẽ đảm bảo an toàn nhất, nhưng tôi không có kinh nghiệm nếu nó thực sự ngăn lỗi. Tôi chưa bao giờ gặp phải bất kỳ vấn đề nào mà không sử dụng giao dịch.

+0

Cảm ơn, tôi đã sửa đổi quy trình trên. Hy vọng rằng đó là bằng chứng đạn. – gb2d

+0

Tôi có đặt mức cách ly giao dịch một cách chính xác không? – gb2d

+0

Tôi nghĩ rằng bạn có thể di chuyển 'TRẦN BEGIN' (và' TRY BEGIN') xuống sau khi tạo bảng '_Temp' và thêm logic vào đầu để thả bảng' _Temp' nếu nó được tìm thấy. – Brad

0

Đặt mức cô lập giao dịch để tuần tự. Điều này có nghĩa là khi bạn bắt đầu một giao dịch thì các hàng bị khóa được thực hiện sao cho những người khác không thể đọc chúng cho đến khi tranny kết thúc

+0

Bạn có thể giải thích lợi ích không? – gb2d

3

Điều này sẽ hoạt động, nhưng giống như @Brad chỉ ra, bạn có thể có một khoảng thời gian dài bị tắc nghẽn trong khi bảng đang được xây dựng lại.Tạo/thả cũ/đổi tên của mình sẽ hoạt động khá tốt.

Một lừa tôi đã sử dụng được dựa trên quan điểm:

  • Bạn có hai bảng vĩnh viễn, MyTable0 và MyTable1
  • Bạn lưu trữ một chỉ báo ở đâu đó cho thấy đó là bảng "hiện tại", và đó là ẩn
  • bạn có một cái nhìn định so với đồng bảng "hiện tại" (đơn giản như CREATE VIEW MyTable as SELECT * from MyTable0)
  • Khi đó là thời gian để cập nhật, bạn tải dữ liệu của bạn vào bảng ngoại tuyến,
  • ru n một khung nhìn ALTER để tham khảo bảng hiện tại (như một câu lệnh đơn, nó được bao bọc trong một giao dịch ngầm định, vì vậy bạn có thể không cần phải giao dịch với các giao dịch đã khai báo),
  • và cập nhật chỉ báo tương ứng (Indicator = (Indicator + 1) % 2)

(Tôi từng có hệ thống bảng bốn chiều dựa trên ý tưởng này, cho dữ liệu trong quá khứ, dữ liệu hiện tại, dữ liệu trong tương lai có sẵn cho khách hàng cao cấp và "chờ tải tiếp theo".)

+0

@Phillip, +1 cho ý tưởng thú vị ... – Brad

+0

Cảm ơn bạn đã có cách tiếp cận thú vị khác. – gb2d

3

Tôi sẽ mở rộng nhận xét dưới dạng câu trả lời đầy đủ: Trước khi triển khai drop-flip-flop, tôi sẽ kiểm tra trước để xem liệu bạn có thể chỉ lập chỉ mục chế độ xem:

Indexed views in SQL 2000
Indexed views in SQL 2005
Indexed views in SQL 2008

Về cơ bản, nếu quan điểm đáp ứng một tập hợp một số điều kiện, bạn có thể chỉ cần thêm một nhóm chỉ số để xem, và nó thực sự tiết kiệm một bản sao vật lý của các kết quả xem, đó là cập nhật mỗi lần các bảng bên dưới được sửa đổi.

Nói cách khác, SQL đang thực hiện tất cả công việc cho bạn mà bạn hiện đang thực hiện thủ công.

Thật không may, không phải tất cả lượt xem đều có thể thực hiện được. Một cái nhìn được lập chỉ mục không thể chứa:

  • DISTINCT
  • Bàn hoặc các truy vấn con nguồn gốc
  • Tồn tại/Không Tồn tại
  • UNION
  • TOP
  • OUTER tham gia
  • ORDER BY

và một loạt các ot những thứ của cô bạn có thể đọc ở các liên kết ở trên.

+0

+1 cho một giải pháp tốt (nếu khả thi trong một số trường hợp cụ thể) – Brad

+0

Tôi đã xem xét các chỉ mục, đó là giải pháp gọn gàng hơn, nhưng nhanh chóng phát hiện ra rằng các hạn chế bạn đã đề cập sẽ áp dụng trong trường hợp của tôi. đã sử dụng. +1 – gb2d

Các vấn đề liên quan