Оптимизация работы серверов баз данных Microsoft SQL Server 2005

Хранение архивных данных

Разбить на страницы
Показывать лекцию целиком

В предыдущей лекции рассказывалось об использовании транзакций для обеспечения целостности данных. В этой лекции мы поговорим об обеспечении целостности данных путем отслеживания изменений и сохранения архивных версий данных, которые могут при необходимости восстанавливаться без восстановления всей базы данных.

Архивные данные могут принимать различные формы, от данных аудита до хранилищ данных для аналитиков. В этой лекции речь, главным образом, пойдет о методах аудита и архивации данных. Одна из главных целей этой лекции - продемонстрировать способы восстановления данных и отслеживания изменений. Как видно из приведенного выше списка задач, существует несколько способов достижения этой цели. Однако Microsoft SQL Server 2005 имеет и другие методы, которые будут выделяться на протяжении всей лекции как альтернативные. В процессе чтения просматривайте Советы, которые помогут узнать об этих альтернативных методах.

Создание моментального снимка базы данных

В SQL Server 2005 существует возможность создать моментальный снимок данных. Моментальный снимок базы данных - это, по сути, указатель места момента времени, в который он создается. В любой момент времени после этого вы можете вернуться к снимку и удалить изменения, которые были внесены в данные. Ниже приводится краткий список ситуаций, в которых моментальные снимки могут оказаться очень полезными.

  • Во время цикла разработки базы данных или связанных приложений можно создать моментальный снимок, чтобы сохранить базовый набор данных для работы. Конечно, это поможет и разработчикам, поскольку им не придется часто восстанавливать базы данных. Можно хранить несколько моментальных снимков с различными изменениями, которые позволят вернуться назад на необходимое количество шагов и не потерять работу, сделанную до этого момента.
  • Моментальные снимки можно использовать при тестировании. Вносите ли вы изменения в схему или тестируете новые технологии загрузки данных, вы можете создать моментальный снимок базы данных, как хорошо известную исходную точку, к которой можно вернуться, чтобы повторить тест.
  • Моментальные снимки можно использовать для восстановления данных из потока высокопроизводительной массовой загрузки в производственной системе. Существует много ситуаций, в которых высокопроизводительная массовая загрузка данных может сгенерировать ошибку, причем откат тоже может не произойти должным образом, в результате база данных останется в неопределенном состоянии. Раньше нужно было бы восстанавливать базу данных из резервной копии, но если перед выполнением массовой загрузки вы создали моментальный снимок, можно вернуться к этому снимку и быстро восстановить работоспособность системы.Совет. Моментальные снимки можно также использовать для баз данных со статическими отчетами. Например, если вам нужно создать несколько отчетов о данных на конец прошлого года, можно создать моментальный снимок данных 31 декабря или 1 января и использовать его для создания годового отчета.

    Мы видим, что моментальные снимки базы данных могут быть очень полезными в разработке, тестировании и производственной среде.

    Важно. Моментальные снимки баз данных доступны только в SQL Server 2005 Enterprise Edition и SQL Server 2005 Developer Edition. Большая часть коллектива разработчиков и тестиров-щиков могут использовать Developer Edition, но если нужно реализовать этот механизм в производственной среде, придется использовать версию SQL Server 2005 Enterprise Edition.
  • Создание моментального снимка базы данных

    Моментальные снимки базы данных можно создать только при помощи Transact-SQL. Через интерфейс SQL Server Management Studio создать их нельзя. Ниже приводится код для создания моментального снимка базы данных Adventure Works (этот код можно найти в файлах примеров под именем Create Snapshot.sql ).

    Создаем моментальный снимок

  • В меню Start (Пуск) выберите All Programs,. Microsoft SQL Server 2005, SQL Server Management Studio (Все программы, Microsoft SQL Server 2005, Среда SQL Server Management Studio).
  • Откройте окно New Query (Новый запрос). Чтобы создать моментальный снимок базы данных Adventure Works, введите и выполните следующий код. Внесите исправления в путь к файлу, чтобы он соответствовал вашей структуре папок.
    CREATE DATABASE AdventureWorks_SBSExample1 ON
      ( NAME = AdventureWorks_Data,
        FILENAME =
         "C:\MySnapshotData\AdventureWorks_SBSExample1.snapshot" ) 
      AS SNAPSHOT OF AdventureWorks; 
    GO
  • Первое, что следует отметить – это то, что инструкция CREATE представляет собой ту же инструкцию, которая используется для создания базы данных. Это значит, что пользователь, который выполняет инструкцию, должен иметь необходимые разрешения на создание баз данных на сервере, с которым он работает. Далее следует отметить, что моментальный снимок должен отражать все файлы, которые содержатся в исходной базе данных. В данном случае, база Adventure Works имеет только один файл – Adventure Works_Data. Но если в исходной базе данных используется более одного файла или группы файлов, вам придется добавить предложение NAME и FILENAME для каждого файла.

    Важно. При создании моментального снимка логическое имя файла должно соответствовать имени файла исходной базы данных. Если используется несколько файлов, то логические имена файлов также следует создавать в соответствии с исходными логическими именами.

    Последний фрагмент кода уведомляет SQL Server о том, что нужно создать моментальный снимок определенной базы данных. Не забывайте, что моментальные снимки и исходные базы данных должны размещаться на одном сервере.

    Что еще следует учитывать при создании моментального снимка

    Имена моментальных снимков

    При назначении имени моментального снимка следует выбирать понятные имена. В нашем примере SBSExample1 –это производное от названия книги, Step-by-Step. Однако, возможно, вам покажется более удобным использовать в имени дату и время создания снимка, чтобы пользователи могли легко понять, какие данные в нем содержатся.

    Имена файлов

    Обычно удобно создать имя файла, исходя из имени базы данных или логического имени файла. Более того, расширение имени файла тоже может что-то означать. В Электронной документации SQL Server 2005 используется расширение .ss, а в нашем примере - расширение .snapshot. Используйте то соглашение о назначении имен, которое вам лучше подходит.

    Использование дискового пространства

    Необходимо учитывать размер дискового пространства, необходимого для моментального снимка. Моментальные снимки содержат только изменения исходной базы данных на момент создания снимка. Это значит, что чем больше изменений было сделано в исходной базе данных, тем больше пространства потребуется для хранения моментальных снимков с записью этих изменений. Учтите также и то, сколько снимков нужно хранить.

    Возврат к моментальному снимку базы данных

    Как и в случае создания моментальных снимков, чтобы вернуться к моментальному снимку базы данных, придется использовать T-SQL. Для возврата к снимку базы данных в T-SQL используется команда RESTORE DATABASE.

    Предупреждение.При возврате к моментальному снимку ВСЕ изменения схемы и данных, сделанные после этого момента, будут потеряны. Если нужно отслеживать сделанные изменения, обязательно перед возвращением к моментальному снимку создайте резервную копию исходной базы данных.

    Возвращаемся к моментальному снимку базы данных

  • Сначала нужно выбрать моментальный снимок, к которому нужно вернуться. Доступные снимки можно просмотреть в SQL Server Management Studio в папке Database Snapshot (Моментальные снимки базы данных). Расположение этой папки показано на следующем рисунке:
  • После того, как вы выбрали нужный моментальный снимок, следует удалить все моментальные снимки, которые были сделаны после выбранного снимка. После того, как возврат будет выполнен, они станут бесполезными, поэтому SQL Server не позволит вам выполнить возврат до тех пор, пока вы их не удалите. Подробную информацию об удалении моментальных снимков можно найти в разделе "Удаление моментальных снимков базы данных".
  • Введите и выполните следующий код, который использует команду RESTORE DATABASE, для возврата к выбранному моментальному снимку (этот код можно найти в файлах примеров под именем FromSnapshot.sql ).
    RESTORE DATABASE AdventureWorks 
    FROM DATABASE_SNAPSHOT = "AdventureWorks_SBSExample1"
    Совет. Если вы разрабатываете или тестируете базу данных, то можно сохранить этот моментальный снимок и попытаться снова вернуть изменения. Вы обнаружите, что можно возвращаться к этому моментальному снимку регулярно, и для этого требуется меньше времени, чем на восстановление данных из резервной копии, особенно если тестируется довольно большая база данных.
  • После завершения восстановления исходную базу данных можно использовать как обычно.Совет. Для хранения архивных данных можно также использовать секционирование таблиц. Это можно сделать при помощи метода раздвижного окна, при котором перемещаются и архивируются группы файлов. Подробную информацию об использовании секционирования таблиц можно найти в теме "Секционирование таблиц и индексов" Электронной документации SQL Server 2005/
  • Удаление моментального снимка базы данных

    В отличие от создания и возврата к моментальному снимку, удалить моментальный снимок можно и через T-SQL, и через интерфейс SQL Server Management Studio. Как вы уже успели заметить, для выполнения операций моментальные снимки используют варианты команды базы данных в T-SQL. То же происходит и при удалении моментального снимка.

    Удаление моментального снимка при помощи T-SQL

    При удалении моментального снимка с помощью T-SQL используйте команду DROP DATABASE. Для удаления моментальных снимков существуют те же ограничения, что и для удаления баз данных. Перед выполнением действия необходимо закрыть все соединения и иметь разрешение на удаление базы данных. Чтобы удалить созданный нами моментальный снимок, введите и выполните следующий код в окне нового запроса. (Этот код можно найти в файлах примеров под именем DeleteSnapshot.sql.)

    DROP DATABASE AdventureWorks_SBSExample1;

    Удаление моментального снимка базы данных через интерфейс SQL Server Management Studio

    В SQL Server Management Studio можно удалить снимок базы данных так же, как и обычную базу данных.

  • Запустите SQL Server Management Studio.
  • Разверните папку Database Snapshots (Моментальные снимки базы данных) в Object Explorer (Обозревателе объектов).
  • Выделите снимок, который нужно удалить.
  • Щелкните правой кнопкой мыши на этом снимке и выберите из контекстного меню команду Delete (Удалить). Откроется диалоговое окно Delete Object (Удаление объекта), показанное на рисунке.
  • В этом диалоговом окне можно указать, чтобы SQL Server закрыл соединения; для этого надо установить флажок Close Existing Connections (Закрыть существующие соединения). Преимущество этого подхода заключается в том, что операции удаления не придется ждать завершения транзакции. Это эквивалентно отправке инструкции KILL всем соединениям базы данных.
  • Нажмите кнопку ОК, чтобы удалить моментальный снимок.
  • Влияние на исходную базу данных

    При использовании моментального снимка базы данных имеют место следующие влияния на исходную базу данных:

  • Управление базой данных
  • Вы не сможете удалить или отсоединить исходную базу данных, пока существует снимок базы данных. Сначала нужно будет удалить снимок базы данных.
  • Вы не сможете восстановить исходную базу данных из резервной копии, пока существуют снимки базы данных.Примечание. Операции резервного копирования исходной базы данных продолжают функционировать как обычно. На эти операции наличие моментальных снимков не влияет.
  • Если происходит возврат к моментальному снимку, цепочка журналов разрывается, и восстановление данных из резервных копий журнала транзакций в полном объеме будет невозможным.
  • Нельзя удалить файлы из исходной базы данных, пока не будут удалены моментальные снимки.
  • Производительность базы данных
  • Неизбежно снижение производительности, потому что базе данных придется управлять и исходной версией, и связанными моментальными снимками. Базе данных придется копировать оригинальное значение в моментальный снимок, а затем записывать изменение в исходную базу данных. Это приводит к дополнительным операциям ввода/вывода до тех пор, пока используются моментальные снимки.
  • Обобщение информации в таблице хроник

    Перемещая данные в таблицы хроники, можно освободить систему транзакций от всплесков, имеющих место в том случае, когда к ней выполняются запросы для создания отчетов. Таблицы хроники могут быть оптимизированы для запросов и обслуживаться отдельно от всей остальной системы. Существует несколько способов создания таких таблиц и поддержания их в актуальном состоянии. Мы рассмотрим несколько примеров, которые используют для загрузки таблиц и T-SQL, и службу агент SQL Server.

    Затем мы создадим итоговую таблицу из базы данных Adventure Works, которая будет отслеживать продажи данного продукта с сортировкой по продавцам. Задача - выполнив запрос по фамилии продавца, быстро узнать, сколько единиц данного изделия он продал.

    Создаем и загружаем таблицу хроники

  • Для того, чтобы использовать эти примеры в полном объеме, придется создать таблицу в базе данных
    USE AdventureWorks;
    GO
    CREATE TABLE Sales.SalesPersonProductWeeklySummary
      (SalesPersonID INT
      ,SalesPersonFirstName NVARCHAR(50)
      ,SalesPersonLastName NVARCHAR(50)
      ,OrderWeekOfYear INT
      ,OrderYear INT ,ProductID INT
      ,ProductName NVARCHAR(50) 
      ,WeeklyOrderQty INT 
      ,WeeklyLineTotal MONEY ); 
    GO
    CREATE CLUSTERED INDEX cidx_SalesPersonProductWeeklySummary
      ON Sales.SalesPersonProductWeeklySummary(OrderYear, 
                                 OrderWeekOfYear, SalesPersonID);
    GO
  • Далее, нам потребуется хранимая процедура, которую можно использовать для выборки загружаемых в таблицу SalesPersonProductWeeklySummary данных. Следующий код (он включен в файлы примеров под именем CreateUspGetWeeklySalesSummary.sql ) создает процедуру. Введите и выполните код в окне нового запроса.
    USE AdventureWorks GO
    CREATE PROCEDURE Sales.uspGetSalesWeeklySummary 
            (@StartOfWeek DATETIME 
            ,@EndOfWeek DATETIME ) 
    AS 
    BEGIN
      SELECT hdr.SalesPersonID
            ,cntc.FirstName AS SalesPersonFirstName 
            ,cntc.LastName AS SalesPersonLastName 
            ,DATEPART(WEEK, hdr.OrderDate) AS OrderWeekOfYear 
            ,DATEPART(YEAR, hdr.OrderDate) AS OrderYear 
            ,prod.ProductID ,prod.Name AS ProductName 
            ,SUM(dtl.OrderQty) as WeeklyOrderQty 
            ,SUM(dtl.LineTotal) as WeeklyLineTotal 
        FROM Sales.SalesOrderHeader hdr
        INNER JOIN Sales.SalesOrderDetail dtl
          ON hdr.SalesOrderID = dtl.SalesOrderID 
        INNER JOIN HumanResources.Employee emp 
          ON hdr.SalesPersonID = emp.EmployeeID 
        INNER JOIN Person.Contact cntc
          ON emp.ContactID = cntc.ContactID 
        INNER JOIN Production.Product prod 
          ON dtl.ProductID = prod.ProductID 
        WHERE hdr.OrderDate BETWEEN @StartOfWeek AND @EndOfWeek 
        GROUP BY hdr.SalesPersonID 
                ,cntc.FirstName 
                ,cntc.LastName 
                ,prod.ProductID 
                ,prod.Name 
                ,hdr.OrderDate 
    END; 
    GO
    Совет. С помощью схемы Sales можно гарантировать, что разрешения на доступ к сведениям о продажах будут применяться и к новым объектам сводных данных.
  • Теперь можно загрузить таблицу при помощи хранимой процедуры uspGetWeeklySalesSummary, выполнив следующий код (его можно найти в файле примеров с именем LoadSalesPersonProduct WeeklySummary.sql ). Введите и выполните код в окне нового запроса.
    INSERT INTO Sales.SalesPersonProductWeeklySummary
       (SalesPersonID
       ,SalesPersonFirstName
       ,SalesPersonLastName
       ,OrderWeekOfYear
       ,OrderYear
       ,ProductID
       ,ProductName
       ,WeeklyOrderQty
       ,WeeklyLineTotal
       )
    EXEC Sales.uspGetSalesWeeklySummary 
         @StartOfWeek = "1/1/2004 00:00:00",
         @EndOfWeek = "1/7/2004 11:59:59"; 
    GO
  • Наконец, можно использовать варианты этого кода в агенте SQL Server, чтобы автоматизировать еженедельную загрузку данных.Совет. Для загрузки данных можно также использовать SQL Server Integration Services (Службы интеграции SQL Server).

    Если вам приходится выполнять больше одной операции загрузки, то это может быть наилучшим вариантом.

  • В SQL Server Management Studio откройте диалоговое окно New Job (Новое задание), развернув дерево узла SQL Server Agent в Object Explorer (Обозревателе объектов) и щелкнув правой кнопкой мыши на папке Jobs (Задания). Выберите из контекстного меню команду New Job (Создать задание).
  • На странице General (Общие) диалогового окна New Job (Новое задание) дайте заданию понятное имя. Здесь можно также добавить описание.
  • На странице Steps (Шаги) диалогового окна New Job (Новое задание) нажмите кнопку New (Создать), чтобы создать новый шаг задания. Откроется окно New Job Step (Новый этап задания), показанное ниже.
  • После того, как шагу будет присвоено понятное имя (здесь используется имя Load The Weekly Summary), нужно выбрать сценарий Transact SQL (T-SQL) из раскрывающегося меню Type (Тип), а из раскрывающегося меню Database (База данных) - Adventure Works.Совет. Для запуска задания можно выбрать другую учетную запись, задав параметр Run As (Запуск от имени). По умолчанию для выполнения команды используется учетная запись службы Агент SQL Server.
  • Затем введем код команды. Нам нужно, чтобы значение даты устанавливалось автоматически. Введите следующий код, чтобы определить переменные для запуска задания в любой день с воскресенья до субботы предыдущей недели и загрузки таблицы. На этом этапе мы предполагаем, что задание запланировано для запуска во вторник (этот код можно найти в файлах примеров под именем ScheduledJobStep.sql.)
    DECLARE @StartOfWeek datetime
           ,@EndOfWeek datetime 
    SET @StartOfWeek = CAST(ROUND(CAST(DATEADD(DAY, -2, GETDATE())
      AS FLOAT),0,1) AS DATETIME) 
    SET @EndOfWeek = DATEADD(DAY, 7, @StartOfWeek)
    
    INSERT INTO Sales.SalesPersonProductWeeklySummary
       (SalesPersonID
       ,SalesPersonFirstName
       ,SalesPersonLastName
       ,OrderWeekOfYear
       ,OrderYear
       ,ProductID
       ,ProductName
       ,WeeklyOrderQty
       ,WeeklyLineTotal
       ) 
     EXEC Sales.uspGetSalesWeeklySummary 
       @StartOfWeek, 
       @EndOfWeek
    Совет. Поскольку SQL Server не имеет типа данных, который поддерживал бы только дату, то для того, чтобы правильно настроить параметры, необходимо удалить время из DateTime. Это можно сделать следующим образом: SET @StartOfWeek = CAST(CONVERT(VARCHAR, DATEADD(DAY, -2, GETDATE()), 101) AS DATETIME).

    Можете попробовать сделать это по-другому. Один метод использует конверсию строк, в то время как другой код использует конверсию чисел и может выполняться быстрее.

  • Нажмите кнопку OK, чтобы завершить создание шага задания Load the Weekly Summary.
  • На странице Schedules (Расписания) диалогового окна New Job (Новое задание) можно определить, когда будет выполняться задание. В этом примере задайте запуск задания по еженедельному регулярному расписанию по вторникам в 2 часа ночи. Нажмите кнопку New (Создать) и введите соответствующие параметры в диалоговом окне New Job Schedule (Новое расписание задания). На рисунке показано диалоговое окно New Job Schedule (Новое расписание задания), настроенное на выполнение этого задания. Нажмите кнопку OK, чтобы сохранить новое расписание и применить его к текущему заданию.
  • Нажмите кнопку ОК, чтобы выйти из диалогового окна New Job (Новое задание) и создать новое задание.
  • Вывод итоговых данных в индексированных представлениях

    Еще одна возможность сохранить итоговые данные– это использование индексированных представлений. Индексированные представления также называют материализованными представлениями, потому что они вычисляют и хранят данные. От обычных представлений их отличает наличие уникальных кластеризованных индексов, реализованных в них для повышения производительности выполняемых запросов. Как правило, наилучший выигрыш в производительности достигается при создании индексированных представлений данных, которые являются итоговыми и не требуют для получения результата множественных соединений. Если данные, к которым нужно выполнить запрос, имеют несколько агрегатов или соединений или часто обновляются, индексированные представления дадут либо небольшой выигрыш, либо вообще никакого выигрыша не будет.

    Важно. Индексированные представления поддерживаются только в SQL Server Enterprise Edition (версии 2000 и 2005). Как и для всех функций, поддерживаемых только в версии Enterprise, можно использовать в разработке функциональные возможности Enterprise Edition, работая в SQL Server Developer Edition.

    Далее мы создадим индексированное представление, которое будет возвращать продажи отдельных изделий в 2004 году, сгруппированные по продавцам. Индексированные представления имеют много ограничений, которые препятствуют их созданию на основе изменяющихся значений. В этом случае мы используем диапазон данных, в котором данные, вероятнее всего, не будут изменяться. Если вам нужно показать эти данные по месяцам, то придется создать отдельное индексированное представление для каждого месяца.

    Совет. Если вы используете такой тип представлений главным образом для вывода итоговых данных, можно создать набор представлений, которые будут выводить итоговые данные сразу за целый год, используя месяцы только для текущего года. Например, можно иметь индексированные представления для 2004, 2005 годов, января 2006, февраля 2006 и так далее. В конце каждого года можно удалить ежемесячные представления за этот год и создать годовое представление.

    Создаем индексированное представление для итогов продаж

  • Создайте представление, выполнив следующий код (его можно найти в файлах примеров под именем Create View.sql ) в окне нового запроса в SQL Server Management Studio. Фрагменты кода, выделенные полужирным шрифтом, подробно объясняются на врезке "Параметры, обязательные при работе с индексированными представлениями". Они обязательны для применения индекса.
    USE AdventureWorks; 
    GO
    
    IF EXISTS(SELECT 1 FROM sys.objects WHERE name = 
           N'v_SalesPerson2004ProductSummary') 
      DROP VIEW Sales.v_SalesPerson2004ProductSummary 
    GO
    
    SET ANSI_NULLS ON
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE VIEW Sales.v_SalesPerson2004ProductSummary 
      WITH SCHEMABINDING
    AS  
      SELECT hdr.SalesPersonID
            ,cntc.FirstName AS SalesPersonFirstName 
            ,cntc.LastName AS SalesPersonLastName 
            ,prod.ProductID 
            ,prod.Name AS ProductName
            ,COUNT_BIG(*) AS OrderLineCount
            ,SUM(dtl.OrderQty) as OrderQty
            ,SUM(dtl.LineTotal) as LineTotal
        FROM Sales.SalesOrderHeader hdr
        INNER JOIN Sales.SalesOrderDetail dtl
          ON hdr.SalesOrderID = dtl.SalesOrderID 
        INNER JOIN HumanResources.Employee emp
          ON hdr.SalesPersonID = emp.EmployeeID 
        INNER JOIN Person.Contact cntc
          ON emp.ContactID = cntc.ContactID 
        INNER JOIN Production.Product prod
          ON dtl.ProductID = prod.ProductID
        WHERE hdr.OrderDate BETWEEN 
              CONVERT(DATETIME,  "1/1/2004 00:00:00",120)
          AND CONVERT(DATETIME,"12/31/2004 23:59:59",120)
        GROUP BY hdr.SalesPersonID
                ,cntc.FirstName
                ,cntc.LastName
                ,prod.ProductID
                ,prod.Name; 
    GO
  • Затем, чтобы представление стало индексированным, следует добавить к нему уникальный кластеризованный индекс. В этом случае мы не можем использовать тот же кластеризованный индекс, который уже использовался в таблице, потому что он не будет уникальным. Чтобы создать уникальный индекс, придется добавить в индекс столбец ProductID. Выполните следующий код (его можно найти среди файлов примеров под именем AddIndex.sql ).
    USE AdventureWorks
    GO
    CREATE UNIQUE CLUSTERED INDEX cidx_v_SalesPerson2004ProductSummary
      ON Sales.v_SalesPerson2004ProductSummary 
          (SalesPersonID 
          ,ProductID); 
    GO
  • Параметры, обязательные при работе с индексированными представлениями

    Хотя использование индексированных представлений способно повысить производительность при извлечении итоговых данных из среды, оно связано с некоторыми обязательными параметрами и ограничениями. Представление, созданное в разделе "Создаем индексированное представление для итогов продаж" было разработано для обхода некоторых из таких ограничений.

  • При создании представления параметры ANSI_NULLS и QUOTED_IDENTIFIER должны быть установлены на ON. Параметр ANSI_NULLS должен быть включен также и для базовой таблицы, лежащей в основе представления.
  • Необходимо создать представление, использующее параметр SCHEMA_BINDING. Оно объединит схему со схемами базовых таблиц.
  • При использовании агрегатов и предложений GROUP BY необходимо включить в список SELECT COUNT_BIG(*).
  • В синтаксисе представления допускается использовать только детерминированные функции. Нельзя использовать функцию GET-DATE(), поскольку она не является детерминированной. Необходимо также конвертировать даты в строковых форматах в даты в детерминированных форматах. В данном примере мы конвертируем строковое выражение в тип данных DATETIME при помощи канонического стандартного стиля ODBC (120).
  • Следует иметь в виду еще несколько параметров и ограничений. Полный список можно найти в Электронной документации по SQL Server 2005 в теме "Создание индексированных представлений". Обязательно ознакомьтесь с этим списком, прежде чем приступать к использованию индексированных представлений, поскольку окончательный проект может оказаться слишком усложненным и не даст желательных преимуществ.

    Отслеживание изменений при помощи столбцов и таблиц аудита

    В предыдущих двух разделах мы узнали, как хранить итоговые архивные данные и осуществлять к ним доступ. Теперь мы познакомимся с некоторыми методами отслеживания меняющихся данных в самой таблице и за пределами исходной таблицы. Уровень аудита, который следует выбирать, зависит от того, что в действительности требуется узнать.

    Можно выбрать простой уровень аудита, при котором будет записываться только дата изменения, или сложный уровень, при котором будет вестись полная запись изменения с возможностью восстановления, если возникнет необходимость. В последнем варианте используются столбцы аудита, таблицы аудита или их сочетание.

    Аудит при помощи столбцов

    Преимущество аудита с помощью столбцов заключается в том, что контрольная информация размещается в той же таблице, что и данные. В табл. 7.1 перечислены некоторые столбцы аудита, которые обычно добавляются в таблицы.

    Различные типы столбцов аудита
    Отслеживаемые события Типы данных Комментарии
    INSERT, UPDATE, или DELETE DATETIME Используется для отслеживания даты и времени выполнения отслеживаемого действия.
    Обычно используется с функцией GETDATE() как значение по умолчанию, но значение может задаваться и вызывающим приложением.
    INSERT, UPDATE или DELETE VARCHAR Используется для отслеживания имени пользователя или приложения, выполняющего отслеживаемое действие.
    DELETE BIT/TINYINT Используется для того, чтобы пометить данные как удаляемые. Это может с большой эффективностью применяться в индексировании и фильтрации.

    По этой таблице можно сделать вывод, что изменения данных в действительности не протоколируются. Наиболее эффективный способ использования столбцов аудита – это отслеживание факта внесения изменения, времени изменения и лица или приложения, выполнившего это изменение. Можно использовать эти столбцы в любой комбинации, чтобы отслеживать изменения в записях в реальной таблице. В зависимости от особенностей приложения и выбранного уровня аудита, вы поймете, что эти столбцы удовлетворяют большей части потребностей в аудите на уровне записей.

    Настраиваем столбцы аудита

  • Сначала нужно определить события, которые нужно отслеживать. В этом примере вы научитесь добавлять столбцы аудита для отслеживания инициатора изменений, даты и времени создания записи, даты и времени последнего обновления записи и того, была ли удалена запись из таблицы Person.Address базы данных Adventure Works.
  • Выбрав таблицу ( Person.Address ) и определив события, которые будут отслеживаться, нужно решить, какие столбцы добавить в таблицу.
  • Столбец ModifiedDate уже существует в таблице. Он будет отслеживать дату, показывающую, когда запись была в последний раз изменена или удалена.
  • Столбец CreatedDate будет отслеживать, когда была создана запись. Тип данных этого столбца DATETIME, с использованием функции GETDATE() для предоставления текущей даты как значения по умолчанию.
  • Столбец ModifiedBy —это столбец VARCHAR, который будет содержать имя пользователя или некоторые другие средства для идентификации пользователя или приложения, которые внесли изменения.
  • Столбец IsDeleted - столбец с типом данных BIT, который будет использоваться для записи об удалении строки. Дата и пользователь будут отслеживаться через столбцы ModifiedDate и ModifiedBy. Если запись была удалена, этот столбец будет помечен, а в измененном столбце будут сведения о том, кто и когда удалил запись.
  • Теперь можно выполнить представленный ниже сценарий, чтобы изменить таблицу Person.Address (этот код можно найти в файлах примеров под именем AlterTable.sql ).
    USE AdventureWorks
    GO
    ALTER TABLE Person.Address
      ADD CreatedDate DATETIME NULL DEFAULT GETDATE()
         ,ModifiedBy VARCHAR(50) NULL
         ,IsDeleted BIT DEFAULT (0)
  • Далее, если вы изменяете таблицу с уже имеющимися данными, следует задать в столбце CreatedDate значение, показывающее, что столбец был создан до того, как был начат аудит. Чтобы задать значение CreatedDate, выполните следующий код:
    UPDATE Person.Address 
    SET CreatedDate = "1/1/1980";
  • Теперь нужно изменить хранимые процедуры и код приложения для заполнения этих столбцов нужными результатами. Для обновления столбцов можно использовать триггеры, но обычно лучше контролировать изменение данных и использовать для обновления столбцов аудита код приложения.
  • Последнее действие в этом процессе – это добавление фильтра ко всем процедурам и программам, ссылающимся на данную таблицу, чтобы предотвратить возвращение удаленных записей. Вот фильтр, который нужно использовать:
    WHERE IsDeleted = 0
  • Аудит с помощью таблиц

    Теперь мы знаем, как использовать аудит для уведомления о сделанных изменениях. Однако единственное изменение, которое может быть легко отменено - это событие DELETE. Достаточно просто сбросить флаг IsDeleted, и данные будут снова доступны. Существует также возможность отменить событие CREATE, если об этом действии имеется достаточная информация. Однако если нужно иметь возможность полностью отслеживать состояние данных перед изменением, возможно, лучшим вариантом окажется использование таблиц аудита. Эту возможность следует использовать с осторожностью, потому что она может вызвать много проблем с обслуживанием и производительностью. Такие проблемы возникают потому, что приходится копировать данные в таблицу аудита и изменять их в исходной таблице. Для этого примера мы зададим аудит на базе таблицы в таблице Sales.Special Offer. Цель – отслеживание любых изменений в этой таблице и обеспечение возможности отменить изменения после того, как они были зафи ксированы.

    Настраиваем таблицы аудита

  • Запустите SQL Server Management Studio и найдите в Object Explorer (Обозревателе объектов) в базе данных Adventure Works таблицу Sales.SpecialOffer.
  • Сгенерируйте базовый сценарий аудита, щелкнув правой кнопкой мыши таблицу Sales.SpecialOffer и выбрав из контекстного меню команды Script Table As, Create To, New Query Editor Window (Создать сценарий для таблицы, Используя CREATE, В новом окне редактора запросов). После этого откроется новое окно запроса с готовым для редактирования сценарием CREATE TABLE.
  • Отредактируйте сценарий, выполнив перечисленные ниже действия. Для этого примера окончательная редакция сценария показана в действии 4.
  • Сначала удалите все дополнительные сценарии. Нужно удалить все строки кода, которые не входят в инструкцию CREATE.
  • Затем измените имя таблицы с Sales.SpecialOffer на Sales.SpecialOffer_Audit.
  • Теперь удалите все ограничения для таблицы и разрешите для всех столбцов значения NULL. Благодаря этому таблица будет больше похожа на журнальную таблицу. В этом случае таблица аудита не должна мешать обычным операциям в таблице с самого начала. Это также должно упростить управление таблицей.
  • Добавьте все дополнительные столбцы, которые будут помогать в определении типа изменений, даты изменений и других элементов аудита, которые нужно отслеживать. В данном примере нужно добавить столбцы, перечисленные в табл. 7.2.
    Столбцы, которые нужно добавить в таблицу аудита
    Имя столбца Тип данных
    AuditModifiedDate DATETIME
    AuditType NVARCHAR(20)
  • Выполните окончательный сценарий, представленный ниже, в базе данных AdventureWorks. (Этот код можно найти в файлах примеров под именем CreateAuditTable.sql.)
    USE AdventureWorks;
    GO
    CREATE TABLE Sales.SpecialOffer_Audit(
        SpecialOfferID INT NULL,
        Description NVARCHAR(255) NULL,
        DiscountPct SMALLMONEY NULL,
        [Type] NVARCHAR(50) NULL,
        Category NVARCHAR(50) NULL,
        StartDate DATETIME NULL,
        EndDate DATETIME NULL,
        MinQty INT NULL,
        MaxQty INT NULL,
        rowguid UNIQUEIDENTIFIER NULL,
        ModifiedDate DATETIME NULL,
        AuditModifiedDate DATETIME NULL,
        AuditType NVARCHAR(20) null 
    ); 
    GO
    Совет. Возможно, придется создать новую схему для объектов аудита.
  • Запись данных аудита в таблицу аудита

    Основные способы перемещения данных в таблицы аудита в SQL Server 2005 - это триггеры базы данных и новое предложение T-SQL OUTPUT. Однако новое предложение OUTPUT добавляет некоторые интересные возможности. В следующем разделе мы на примере изучим каждый из этих двух вариантов.

    Используем триггер UPDATE для заполнения таблицы аудита

  • Создайте в таблице Sales.SpecialOffer триггер, который будет записывать предыдущее состояние данных в созданную нами таблицу Sales.SpecialOffer_Audit. Код, приведенный ниже – это пример синтаксической конструкции, которую можно использовать. (Этот код можно найти в файлах примеров под именем CreateTrigger.sql.) Введите и выполните код в окне нового запроса SQL Server Management Studio.
    USE AdventureWorks
    GO
    CREATE TRIGGER SpecialOfferUpdateAudit ON Sales.SpecialOffer
    FOR UPDATE
    AS
    INSERT INTO Sales.SpecialOffer_Audit 
           (SpecialOfferID
           ,Description
           ,DiscountPct
           ,[Type]
           ,Category
           ,StartDate
           ,EndDate
           ,MinQty
           ,MaxQty
           ,rowguid
           ,ModifiedDate
           ,AuditModifiedDate
           ,AuditType) 
    SELECT TOP 1 d.SpecialOfferID
                ,d.Description
                ,d.DiscountPct
                ,d.[Type]
                ,d.Category
                ,d.StartDate
                ,d.EndDate
                ,d.MinQty
                ,d.MaxQty
                ,d.rowguid
                ,d.ModifiedDate
                ,GETDATE()
                ,'UPDATE' 
      FROM deleted d; GO
  • Примечание. Если вы не делали никаких изменений в таблице Sales.SpecialOffer, скорее всего, вам придется удалить триггер, который уже существует в таблице ( uSpecial Offer ). Необходимо сохранить сценарий для триггера, чтобы можно было использовать его в дальнейшем. Если этот триггер не удалить, то вы будете получать строки данных в таблице Sales.SpecialOffer_Audit при любом обновлении таблицы.

    Преимущество использования триггера заключается в том, что он будет захватывать любые обновления, которые произойдут в таблице, независимо от их источника. Это вариант аудита с полным охватом. Если речь идет о данных, которые изменяются без контроля с вашей стороны, то это превосходный вариант. Но если вы тщательно контролируете данные, которые заносятся в таблицу, особенно если это выполняется при помощи хранимых процедур, то в SQL Server 2005 есть новая возможность аудита изменений - предложение OUTPUT.

    Используем предложение OUTPUT для заполнения таблицы аудита

  • Чтобы эффективно использовать предложение OUTPUT, каждое событие, которое нужно отслеживать, потребует разработки хранимых процедур и инструкций SQL, которые будут использоваться для обновления ( UPDATE ), вставки ( INSERT ) или удаления ( DELETE ) данных в отслеживаемых таблицах. Предложение OUTPUT предоставляет доступ к вставляемым и удаляемым таблицам в этих процедурах и инструкциях SQL. Теперь не обязательно использовать триггеры для доступа к данным. Представленный ниже код показывает пример использования предложения OUTPUT для аудита обновления в таблице SpecialOffer в таблице SpecialOffer_Audit. (Этот код можно найти в файлах примеров под именем UsingOutputClause.sql.) Введите и выполните данный код в окне нового запроса SQL Server Management Studio.Важно. Предложение OUTPUT должно вставлять свои данные в табличную переменную, во временную таблицу или - как в данном случае - в постоянную таблицу.
    USE AdventureWorks
    GO
    UPDATE Sales.SpecialOffer
    SET description = "Big Mountain Tire Sale" 
    OUTPUT deleted.SpecialOfferID
          ,deleted.Description
          ,deleted.DiscountPct
          ,deleted.[Type]
          ,deleted.Category
          ,deleted.StartDate
          ,deleted.EndDate
          ,deleted.MinQty
          ,deleted.MaxQty
          ,deleted.rowguid
          ,deleted.ModifiedDate
          ,GETDATE()
          ,'UPDATE' INTO Sales.SpecialOffer_Audit 
      WHERE SpecialOfferID = 10
  • Предложение OUTPUT помещает измененные данные в рамках простого доступа в процессе изменения данных. В процессе операций UPDATE и DELETE доступен префикс DELETED. В процессе операций UPDATE и INSERT доступен префикс INSERTED. Обратите внимание на то, что оба префикса не могут быть доступными одновременно, в отличие от таблиц deleted и inserted, которые используются в триггерах. Эта взаимоисключающая доступность требует, чтобы различные операции обрабатывались по-разному для сбора нужных данных и помещения их в таблицы аудита.Совет. Предложение OUTPUT можно также использовать для возвращения значения из столбца IDENTITY в процессе операции INSERT.
  • Восстановление данных с помощью таблиц аудита

    Теперь, когда у нас есть два варианта загрузки данных в таблицу аудита, можно подумать, для чего использовать эти данные. Поскольку все изменения в таблице сохраняются в таблице аудита, можно восстановить любые изменения данных, перезаписав текущие данные изменением, которое нужно сохранить. Таблица аудита может хранить несколько версий данных, поэтому чаще всего это придется делать вручную. Однако можно также создать обслуживающую хранимую процедуру для отмены самого последнего изменения.

    Используем таблицу аудита для восстановления измененных данных

  • Определите, какую запись следует восстановить. Для этого нужно будет идентифицировать изменяемую запись и данные, которые ее заменят.
  • Воспользуйтесь приложением UPDATE для перезаписи текущих данных изменением, которое следует восстановить в этой таблице. В данном примере придется использовать либо свойство rowguid, либо столбец SpecialOfferID в сочетании с AuditModifiedDate в качестве критерия для инструкции UPDATE, как показано ниже. (Этот код можно найти в файлах примеров под именем RecoveringChangedData.sql.) Введите и выполните этот код в окне нового запроса SQL Server Management Studio.
    — В этом сценарии нужно заменить AuditModifiedDate на
    —AuditModifiedDate из таблицы SpecialOffer_Audit
    USE AdventureWorks
    GO
    UPDATE Sales.SpecialOffer
    SET Description = a.Description
       ,DiscountPct = a.DiscountPct
       ,Type = a.Type
       ,Category = a.Category
       ,StartDate = a.StartDate
       ,EndDate = a.EndDate
       ,MinQty = a.MinQty
       ,MaxQty = a.MaxQty
       ,rowguid = a.rowguid
       ,ModifiedDate = a.ModifiedDate 
      FROM Sales.SpecialOffer_Audit a 
      WHERE SpecialOffer.SpecialOfferID = 10
        AND a.SpecialOfferID = 10
        AND a.AuditModifiedDate = "2006-04-02 22:40:27.513"
  • Если у вас есть данные, которые нуждаются в регулярном восстановлении, можно инкапсулировать приведенный выше код в хранимую процедуру обслуживания. Однако если вы решите реализовать ее, у вас могут возникнуть проблемы с вводом восстановленных данных. Описанные варианты хорошо подходят для ограниченного количества строк в одной таблице. Если вы работаете с массовой высокопроизводительной загрузкой в нескольких таблицах, следует использовать моментальные снимки, о которых шла речь в первом разделе данной лекции.

    Заключение

    Вы научились создавать моментальные снимки данных. Моментальные снимки могут эффективно использоваться для решения различных задач в процессе разработки, тестирования и производства. Можно использовать архивные данные для подведения итогов и анализа данных на определенных отрезках времени. Вы также научились выполнять аудит изменений данных и восстанавливать отдельные записи при помощи данных аудита. Сохраняя архивные данные и отслеживая изменения в базе данных, можно обеспечить целостность данных, используя возможность отмены отдельных изменений, не восстанавливая всю базу данных.

    Чтобы Выполните следующие действия
    Создать моментальный снимок базы данных Воспользуйтесь инструкцией CREATE DATABASE с параметром AS SNAPSHOT OF.
    Вернуться к моментальному снимку базы данных Воспользуйтесь инструкцией RESTORE DATABASE с параметром FROM SNAPSHOT.
    Удалить моментальный снимок базы данных Воспользуйтесь инструкцией DROP DATABASE или удалите моментальный снимок базы данных через интерфейс SQL Server Management Studio.
    Запланировать загрузку архивных данных Создайте новое задание в агенте SQL Server и составьте расписание которое будет удовлетворять вашим потребностям.
    Вывести итоговую информацию за определенный отрезок времени Создайте индексированное представление для вывода итогов по одному или нескольким временным отрезкам.
    Вести аудит изменений данных Добавьте в таблицу столбцы аудита, в которых будет отслеживаться, кто и когда внес изменение.
    Отслеживать все изменения данных и иметь возможность восстановить данные после ошибки ввода Создайте и загрузите таблицу аудита либо при помощи триггеров, либо при помощи предложения OUTPUT.
    Страницы:

    В предыдущей лекции рассказывалось об использовании транзакций для обеспечения целостности данных. В этой лекции мы поговорим об обеспечении целостности данных путем отслеживания изменений и сохранения архивных версий данных, которые могут при необходимости восстанавливаться без восстановления всей базы данных.

    Архивные данные могут принимать различные формы, от данных аудита до хранилищ данных для аналитиков. В этой лекции речь, главным образом, пойдет о методах аудита и архивации данных. Одна из главных целей этой лекции - продемонстрировать способы восстановления данных и отслеживания изменений. Как видно из приведенного выше списка задач, существует несколько способов достижения этой цели. Однако Microsoft SQL Server 2005 имеет и другие методы, которые будут выделяться на протяжении всей лекции как альтернативные. В процессе чтения просматривайте Советы, которые помогут узнать об этих альтернативных методах.

    Создание моментального снимка базы данных

    В SQL Server 2005 существует возможность создать моментальный снимок данных. Моментальный снимок базы данных - это, по сути, указатель места момента времени, в который он создается. В любой момент времени после этого вы можете вернуться к снимку и удалить изменения, которые были внесены в данные. Ниже приводится краткий список ситуаций, в которых моментальные снимки могут оказаться очень полезными.

  • Во время цикла разработки базы данных или связанных приложений можно создать моментальный снимок, чтобы сохранить базовый набор данных для работы. Конечно, это поможет и разработчикам, поскольку им не придется часто восстанавливать базы данных. Можно хранить несколько моментальных снимков с различными изменениями, которые позволят вернуться назад на необходимое количество шагов и не потерять работу, сделанную до этого момента.
  • Моментальные снимки можно использовать при тестировании. Вносите ли вы изменения в схему или тестируете новые технологии загрузки данных, вы можете создать моментальный снимок базы данных, как хорошо известную исходную точку, к которой можно вернуться, чтобы повторить тест.
  • Моментальные снимки можно использовать для восстановления данных из потока высокопроизводительной массовой загрузки в производственной системе. Существует много ситуаций, в которых высокопроизводительная массовая загрузка данных может сгенерировать ошибку, причем откат тоже может не произойти должным образом, в результате база данных останется в неопределенном состоянии. Раньше нужно было бы восстанавливать базу данных из резервной копии, но если перед выполнением массовой загрузки вы создали моментальный снимок, можно вернуться к этому снимку и быстро восстановить работоспособность системы.Совет. Моментальные снимки можно также использовать для баз данных со статическими отчетами. Например, если вам нужно создать несколько отчетов о данных на конец прошлого года, можно создать моментальный снимок данных 31 декабря или 1 января и использовать его для создания годового отчета.

    Мы видим, что моментальные снимки базы данных могут быть очень полезными в разработке, тестировании и производственной среде.

    Важно. Моментальные снимки баз данных доступны только в SQL Server 2005 Enterprise Edition и SQL Server 2005 Developer Edition. Большая часть коллектива разработчиков и тестиров-щиков могут использовать Developer Edition, но если нужно реализовать этот механизм в производственной среде, придется использовать версию SQL Server 2005 Enterprise Edition.
  • Создание моментального снимка базы данных

    Моментальные снимки базы данных можно создать только при помощи Transact-SQL. Через интерфейс SQL Server Management Studio создать их нельзя. Ниже приводится код для создания моментального снимка базы данных Adventure Works (этот код можно найти в файлах примеров под именем Create Snapshot.sql ).

    Создаем моментальный снимок

  • В меню Start (Пуск) выберите All Programs,. Microsoft SQL Server 2005, SQL Server Management Studio (Все программы, Microsoft SQL Server 2005, Среда SQL Server Management Studio).
  • Откройте окно New Query (Новый запрос). Чтобы создать моментальный снимок базы данных Adventure Works, введите и выполните следующий код. Внесите исправления в путь к файлу, чтобы он соответствовал вашей структуре папок.
    CREATE DATABASE AdventureWorks_SBSExample1 ON
      ( NAME = AdventureWorks_Data,
        FILENAME =
         "C:\MySnapshotData\AdventureWorks_SBSExample1.snapshot" ) 
      AS SNAPSHOT OF AdventureWorks; 
    GO
  • Первое, что следует отметить – это то, что инструкция CREATE представляет собой ту же инструкцию, которая используется для создания базы данных. Это значит, что пользователь, который выполняет инструкцию, должен иметь необходимые разрешения на создание баз данных на сервере, с которым он работает. Далее следует отметить, что моментальный снимок должен отражать все файлы, которые содержатся в исходной базе данных. В данном случае, база Adventure Works имеет только один файл – Adventure Works_Data. Но если в исходной базе данных используется более одного файла или группы файлов, вам придется добавить предложение NAME и FILENAME для каждого файла.

    Важно. При создании моментального снимка логическое имя файла должно соответствовать имени файла исходной базы данных. Если используется несколько файлов, то логические имена файлов также следует создавать в соответствии с исходными логическими именами.

    Последний фрагмент кода уведомляет SQL Server о том, что нужно создать моментальный снимок определенной базы данных. Не забывайте, что моментальные снимки и исходные базы данных должны размещаться на одном сервере.

    Что еще следует учитывать при создании моментального снимка

    Имена моментальных снимков

    При назначении имени моментального снимка следует выбирать понятные имена. В нашем примере SBSExample1 –это производное от названия книги, Step-by-Step. Однако, возможно, вам покажется более удобным использовать в имени дату и время создания снимка, чтобы пользователи могли легко понять, какие данные в нем содержатся.

    Имена файлов

    Обычно удобно создать имя файла, исходя из имени базы данных или логического имени файла. Более того, расширение имени файла тоже может что-то означать. В Электронной документации SQL Server 2005 используется расширение .ss, а в нашем примере - расширение .snapshot. Используйте то соглашение о назначении имен, которое вам лучше подходит.

    Использование дискового пространства

    Необходимо учитывать размер дискового пространства, необходимого для моментального снимка. Моментальные снимки содержат только изменения исходной базы данных на момент создания снимка. Это значит, что чем больше изменений было сделано в исходной базе данных, тем больше пространства потребуется для хранения моментальных снимков с записью этих изменений. Учтите также и то, сколько снимков нужно хранить.

    Возврат к моментальному снимку базы данных

    Как и в случае создания моментальных снимков, чтобы вернуться к моментальному снимку базы данных, придется использовать T-SQL. Для возврата к снимку базы данных в T-SQL используется команда RESTORE DATABASE.

    Предупреждение.При возврате к моментальному снимку ВСЕ изменения схемы и данных, сделанные после этого момента, будут потеряны. Если нужно отслеживать сделанные изменения, обязательно перед возвращением к моментальному снимку создайте резервную копию исходной базы данных.

    Возвращаемся к моментальному снимку базы данных

  • Сначала нужно выбрать моментальный снимок, к которому нужно вернуться. Доступные снимки можно просмотреть в SQL Server Management Studio в папке Database Snapshot (Моментальные снимки базы данных). Расположение этой папки показано на следующем рисунке:
  • После того, как вы выбрали нужный моментальный снимок, следует удалить все моментальные снимки, которые были сделаны после выбранного снимка. После того, как возврат будет выполнен, они станут бесполезными, поэтому SQL Server не позволит вам выполнить возврат до тех пор, пока вы их не удалите. Подробную информацию об удалении моментальных снимков можно найти в разделе "Удаление моментальных снимков базы данных".
  • Введите и выполните следующий код, который использует команду RESTORE DATABASE, для возврата к выбранному моментальному снимку (этот код можно найти в файлах примеров под именем FromSnapshot.sql ).
    RESTORE DATABASE AdventureWorks 
    FROM DATABASE_SNAPSHOT = "AdventureWorks_SBSExample1"
    Совет. Если вы разрабатываете или тестируете базу данных, то можно сохранить этот моментальный снимок и попытаться снова вернуть изменения. Вы обнаружите, что можно возвращаться к этому моментальному снимку регулярно, и для этого требуется меньше времени, чем на восстановление данных из резервной копии, особенно если тестируется довольно большая база данных.
  • После завершения восстановления исходную базу данных можно использовать как обычно.Совет. Для хранения архивных данных можно также использовать секционирование таблиц. Это можно сделать при помощи метода раздвижного окна, при котором перемещаются и архивируются группы файлов. Подробную информацию об использовании секционирования таблиц можно найти в теме "Секционирование таблиц и индексов" Электронной документации SQL Server 2005/
  • Удаление моментального снимка базы данных

    В отличие от создания и возврата к моментальному снимку, удалить моментальный снимок можно и через T-SQL, и через интерфейс SQL Server Management Studio. Как вы уже успели заметить, для выполнения операций моментальные снимки используют варианты команды базы данных в T-SQL. То же происходит и при удалении моментального снимка.

    Удаление моментального снимка при помощи T-SQL

    При удалении моментального снимка с помощью T-SQL используйте команду DROP DATABASE. Для удаления моментальных снимков существуют те же ограничения, что и для удаления баз данных. Перед выполнением действия необходимо закрыть все соединения и иметь разрешение на удаление базы данных. Чтобы удалить созданный нами моментальный снимок, введите и выполните следующий код в окне нового запроса. (Этот код можно найти в файлах примеров под именем DeleteSnapshot.sql.)

    DROP DATABASE AdventureWorks_SBSExample1;

    Удаление моментального снимка базы данных через интерфейс SQL Server Management Studio

    В SQL Server Management Studio можно удалить снимок базы данных так же, как и обычную базу данных.

  • Запустите SQL Server Management Studio.
  • Разверните папку Database Snapshots (Моментальные снимки базы данных) в Object Explorer (Обозревателе объектов).
  • Выделите снимок, который нужно удалить.
  • Щелкните правой кнопкой мыши на этом снимке и выберите из контекстного меню команду Delete (Удалить). Откроется диалоговое окно Delete Object (Удаление объекта), показанное на рисунке.
  • В этом диалоговом окне можно указать, чтобы SQL Server закрыл соединения; для этого надо установить флажок Close Existing Connections (Закрыть существующие соединения). Преимущество этого подхода заключается в том, что операции удаления не придется ждать завершения транзакции. Это эквивалентно отправке инструкции KILL всем соединениям базы данных.
  • Нажмите кнопку ОК, чтобы удалить моментальный снимок.
  • Влияние на исходную базу данных

    При использовании моментального снимка базы данных имеют место следующие влияния на исходную базу данных:

  • Управление базой данных
  • Вы не сможете удалить или отсоединить исходную базу данных, пока существует снимок базы данных. Сначала нужно будет удалить снимок базы данных.
  • Вы не сможете восстановить исходную базу данных из резервной копии, пока существуют снимки базы данных.Примечание. Операции резервного копирования исходной базы данных продолжают функционировать как обычно. На эти операции наличие моментальных снимков не влияет.
  • Если происходит возврат к моментальному снимку, цепочка журналов разрывается, и восстановление данных из резервных копий журнала транзакций в полном объеме будет невозможным.
  • Нельзя удалить файлы из исходной базы данных, пока не будут удалены моментальные снимки.
  • Производительность базы данных
  • Неизбежно снижение производительности, потому что базе данных придется управлять и исходной версией, и связанными моментальными снимками. Базе данных придется копировать оригинальное значение в моментальный снимок, а затем записывать изменение в исходную базу данных. Это приводит к дополнительным операциям ввода/вывода до тех пор, пока используются моментальные снимки.
  • Обобщение информации в таблице хроник

    Перемещая данные в таблицы хроники, можно освободить систему транзакций от всплесков, имеющих место в том случае, когда к ней выполняются запросы для создания отчетов. Таблицы хроники могут быть оптимизированы для запросов и обслуживаться отдельно от всей остальной системы. Существует несколько способов создания таких таблиц и поддержания их в актуальном состоянии. Мы рассмотрим несколько примеров, которые используют для загрузки таблиц и T-SQL, и службу агент SQL Server.

    Затем мы создадим итоговую таблицу из базы данных Adventure Works, которая будет отслеживать продажи данного продукта с сортировкой по продавцам. Задача - выполнив запрос по фамилии продавца, быстро узнать, сколько единиц данного изделия он продал.

    Создаем и загружаем таблицу хроники

  • Для того, чтобы использовать эти примеры в полном объеме, придется создать таблицу в базе данных
    USE AdventureWorks;
    GO
    CREATE TABLE Sales.SalesPersonProductWeeklySummary
      (SalesPersonID INT
      ,SalesPersonFirstName NVARCHAR(50)
      ,SalesPersonLastName NVARCHAR(50)
      ,OrderWeekOfYear INT
      ,OrderYear INT ,ProductID INT
      ,ProductName NVARCHAR(50) 
      ,WeeklyOrderQty INT 
      ,WeeklyLineTotal MONEY ); 
    GO
    CREATE CLUSTERED INDEX cidx_SalesPersonProductWeeklySummary
      ON Sales.SalesPersonProductWeeklySummary(OrderYear, 
                                 OrderWeekOfYear, SalesPersonID);
    GO
  • Далее, нам потребуется хранимая процедура, которую можно использовать для выборки загружаемых в таблицу SalesPersonProductWeeklySummary данных. Следующий код (он включен в файлы примеров под именем CreateUspGetWeeklySalesSummary.sql ) создает процедуру. Введите и выполните код в окне нового запроса.
    USE AdventureWorks GO
    CREATE PROCEDURE Sales.uspGetSalesWeeklySummary 
            (@StartOfWeek DATETIME 
            ,@EndOfWeek DATETIME ) 
    AS 
    BEGIN
      SELECT hdr.SalesPersonID
            ,cntc.FirstName AS SalesPersonFirstName 
            ,cntc.LastName AS SalesPersonLastName 
            ,DATEPART(WEEK, hdr.OrderDate) AS OrderWeekOfYear 
            ,DATEPART(YEAR, hdr.OrderDate) AS OrderYear 
            ,prod.ProductID ,prod.Name AS ProductName 
            ,SUM(dtl.OrderQty) as WeeklyOrderQty 
            ,SUM(dtl.LineTotal) as WeeklyLineTotal 
        FROM Sales.SalesOrderHeader hdr
        INNER JOIN Sales.SalesOrderDetail dtl
          ON hdr.SalesOrderID = dtl.SalesOrderID 
        INNER JOIN HumanResources.Employee emp 
          ON hdr.SalesPersonID = emp.EmployeeID 
        INNER JOIN Person.Contact cntc
          ON emp.ContactID = cntc.ContactID 
        INNER JOIN Production.Product prod 
          ON dtl.ProductID = prod.ProductID 
        WHERE hdr.OrderDate BETWEEN @StartOfWeek AND @EndOfWeek 
        GROUP BY hdr.SalesPersonID 
                ,cntc.FirstName 
                ,cntc.LastName 
                ,prod.ProductID 
                ,prod.Name 
                ,hdr.OrderDate 
    END; 
    GO
    Совет. С помощью схемы Sales можно гарантировать, что разрешения на доступ к сведениям о продажах будут применяться и к новым объектам сводных данных.
  • Теперь можно загрузить таблицу при помощи хранимой процедуры uspGetWeeklySalesSummary, выполнив следующий код (его можно найти в файле примеров с именем LoadSalesPersonProduct WeeklySummary.sql ). Введите и выполните код в окне нового запроса.
    INSERT INTO Sales.SalesPersonProductWeeklySummary
       (SalesPersonID
       ,SalesPersonFirstName
       ,SalesPersonLastName
       ,OrderWeekOfYear
       ,OrderYear
       ,ProductID
       ,ProductName
       ,WeeklyOrderQty
       ,WeeklyLineTotal
       )
    EXEC Sales.uspGetSalesWeeklySummary 
         @StartOfWeek = "1/1/2004 00:00:00",
         @EndOfWeek = "1/7/2004 11:59:59"; 
    GO
  • Наконец, можно использовать варианты этого кода в агенте SQL Server, чтобы автоматизировать еженедельную загрузку данных.Совет. Для загрузки данных можно также использовать SQL Server Integration Services (Службы интеграции SQL Server).

    Если вам приходится выполнять больше одной операции загрузки, то это может быть наилучшим вариантом.

  • В SQL Server Management Studio откройте диалоговое окно New Job (Новое задание), развернув дерево узла SQL Server Agent в Object Explorer (Обозревателе объектов) и щелкнув правой кнопкой мыши на папке Jobs (Задания). Выберите из контекстного меню команду New Job (Создать задание).
  • На странице General (Общие) диалогового окна New Job (Новое задание) дайте заданию понятное имя. Здесь можно также добавить описание.
  • На странице Steps (Шаги) диалогового окна New Job (Новое задание) нажмите кнопку New (Создать), чтобы создать новый шаг задания. Откроется окно New Job Step (Новый этап задания), показанное ниже.
  • После того, как шагу будет присвоено понятное имя (здесь используется имя Load The Weekly Summary), нужно выбрать сценарий Transact SQL (T-SQL) из раскрывающегося меню Type (Тип), а из раскрывающегося меню Database (База данных) - Adventure Works.Совет. Для запуска задания можно выбрать другую учетную запись, задав параметр Run As (Запуск от имени). По умолчанию для выполнения команды используется учетная запись службы Агент SQL Server.
  • Затем введем код команды. Нам нужно, чтобы значение даты устанавливалось автоматически. Введите следующий код, чтобы определить переменные для запуска задания в любой день с воскресенья до субботы предыдущей недели и загрузки таблицы. На этом этапе мы предполагаем, что задание запланировано для запуска во вторник (этот код можно найти в файлах примеров под именем ScheduledJobStep.sql.)
    DECLARE @StartOfWeek datetime
           ,@EndOfWeek datetime 
    SET @StartOfWeek = CAST(ROUND(CAST(DATEADD(DAY, -2, GETDATE())
      AS FLOAT),0,1) AS DATETIME) 
    SET @EndOfWeek = DATEADD(DAY, 7, @StartOfWeek)
    
    INSERT INTO Sales.SalesPersonProductWeeklySummary
       (SalesPersonID
       ,SalesPersonFirstName
       ,SalesPersonLastName
       ,OrderWeekOfYear
       ,OrderYear
       ,ProductID
       ,ProductName
       ,WeeklyOrderQty
       ,WeeklyLineTotal
       ) 
     EXEC Sales.uspGetSalesWeeklySummary 
       @StartOfWeek, 
       @EndOfWeek
    Совет. Поскольку SQL Server не имеет типа данных, который поддерживал бы только дату, то для того, чтобы правильно настроить параметры, необходимо удалить время из DateTime. Это можно сделать следующим образом: SET @StartOfWeek = CAST(CONVERT(VARCHAR, DATEADD(DAY, -2, GETDATE()), 101) AS DATETIME).

    Можете попробовать сделать это по-другому. Один метод использует конверсию строк, в то время как другой код использует конверсию чисел и может выполняться быстрее.

  • Нажмите кнопку OK, чтобы завершить создание шага задания Load the Weekly Summary.
  • На странице Schedules (Расписания) диалогового окна New Job (Новое задание) можно определить, когда будет выполняться задание. В этом примере задайте запуск задания по еженедельному регулярному расписанию по вторникам в 2 часа ночи. Нажмите кнопку New (Создать) и введите соответствующие параметры в диалоговом окне New Job Schedule (Новое расписание задания). На рисунке показано диалоговое окно New Job Schedule (Новое расписание задания), настроенное на выполнение этого задания. Нажмите кнопку OK, чтобы сохранить новое расписание и применить его к текущему заданию.
  • Нажмите кнопку ОК, чтобы выйти из диалогового окна New Job (Новое задание) и создать новое задание.
  • Вывод итоговых данных в индексированных представлениях

    Еще одна возможность сохранить итоговые данные– это использование индексированных представлений. Индексированные представления также называют материализованными представлениями, потому что они вычисляют и хранят данные. От обычных представлений их отличает наличие уникальных кластеризованных индексов, реализованных в них для повышения производительности выполняемых запросов. Как правило, наилучший выигрыш в производительности достигается при создании индексированных представлений данных, которые являются итоговыми и не требуют для получения результата множественных соединений. Если данные, к которым нужно выполнить запрос, имеют несколько агрегатов или соединений или часто обновляются, индексированные представления дадут либо небольшой выигрыш, либо вообще никакого выигрыша не будет.

    Важно. Индексированные представления поддерживаются только в SQL Server Enterprise Edition (версии 2000 и 2005). Как и для всех функций, поддерживаемых только в версии Enterprise, можно использовать в разработке функциональные возможности Enterprise Edition, работая в SQL Server Developer Edition.

    Далее мы создадим индексированное представление, которое будет возвращать продажи отдельных изделий в 2004 году, сгруппированные по продавцам. Индексированные представления имеют много ограничений, которые препятствуют их созданию на основе изменяющихся значений. В этом случае мы используем диапазон данных, в котором данные, вероятнее всего, не будут изменяться. Если вам нужно показать эти данные по месяцам, то придется создать отдельное индексированное представление для каждого месяца.

    Совет. Если вы используете такой тип представлений главным образом для вывода итоговых данных, можно создать набор представлений, которые будут выводить итоговые данные сразу за целый год, используя месяцы только для текущего года. Например, можно иметь индексированные представления для 2004, 2005 годов, января 2006, февраля 2006 и так далее. В конце каждого года можно удалить ежемесячные представления за этот год и создать годовое представление.

    Создаем индексированное представление для итогов продаж

  • Создайте представление, выполнив следующий код (его можно найти в файлах примеров под именем Create View.sql ) в окне нового запроса в SQL Server Management Studio. Фрагменты кода, выделенные полужирным шрифтом, подробно объясняются на врезке "Параметры, обязательные при работе с индексированными представлениями". Они обязательны для применения индекса.
    USE AdventureWorks; 
    GO
    
    IF EXISTS(SELECT 1 FROM sys.objects WHERE name = 
           N'v_SalesPerson2004ProductSummary') 
      DROP VIEW Sales.v_SalesPerson2004ProductSummary 
    GO
    
    SET ANSI_NULLS ON
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE VIEW Sales.v_SalesPerson2004ProductSummary 
      WITH SCHEMABINDING
    AS  
      SELECT hdr.SalesPersonID
            ,cntc.FirstName AS SalesPersonFirstName 
            ,cntc.LastName AS SalesPersonLastName 
            ,prod.ProductID 
            ,prod.Name AS ProductName
            ,COUNT_BIG(*) AS OrderLineCount
            ,SUM(dtl.OrderQty) as OrderQty
            ,SUM(dtl.LineTotal) as LineTotal
        FROM Sales.SalesOrderHeader hdr
        INNER JOIN Sales.SalesOrderDetail dtl
          ON hdr.SalesOrderID = dtl.SalesOrderID 
        INNER JOIN HumanResources.Employee emp
          ON hdr.SalesPersonID = emp.EmployeeID 
        INNER JOIN Person.Contact cntc
          ON emp.ContactID = cntc.ContactID 
        INNER JOIN Production.Product prod
          ON dtl.ProductID = prod.ProductID
        WHERE hdr.OrderDate BETWEEN 
              CONVERT(DATETIME,  "1/1/2004 00:00:00",120)
          AND CONVERT(DATETIME,"12/31/2004 23:59:59",120)
        GROUP BY hdr.SalesPersonID
                ,cntc.FirstName
                ,cntc.LastName
                ,prod.ProductID
                ,prod.Name; 
    GO
  • Затем, чтобы представление стало индексированным, следует добавить к нему уникальный кластеризованный индекс. В этом случае мы не можем использовать тот же кластеризованный индекс, который уже использовался в таблице, потому что он не будет уникальным. Чтобы создать уникальный индекс, придется добавить в индекс столбец ProductID. Выполните следующий код (его можно найти среди файлов примеров под именем AddIndex.sql ).
    USE AdventureWorks
    GO
    CREATE UNIQUE CLUSTERED INDEX cidx_v_SalesPerson2004ProductSummary
      ON Sales.v_SalesPerson2004ProductSummary 
          (SalesPersonID 
          ,ProductID); 
    GO
  • Параметры, обязательные при работе с индексированными представлениями

    Хотя использование индексированных представлений способно повысить производительность при извлечении итоговых данных из среды, оно связано с некоторыми обязательными параметрами и ограничениями. Представление, созданное в разделе "Создаем индексированное представление для итогов продаж" было разработано для обхода некоторых из таких ограничений.

  • При создании представления параметры ANSI_NULLS и QUOTED_IDENTIFIER должны быть установлены на ON. Параметр ANSI_NULLS должен быть включен также и для базовой таблицы, лежащей в основе представления.
  • Необходимо создать представление, использующее параметр SCHEMA_BINDING. Оно объединит схему со схемами базовых таблиц.
  • При использовании агрегатов и предложений GROUP BY необходимо включить в список SELECT COUNT_BIG(*).
  • В синтаксисе представления допускается использовать только детерминированные функции. Нельзя использовать функцию GET-DATE(), поскольку она не является детерминированной. Необходимо также конвертировать даты в строковых форматах в даты в детерминированных форматах. В данном примере мы конвертируем строковое выражение в тип данных DATETIME при помощи канонического стандартного стиля ODBC (120).
  • Следует иметь в виду еще несколько параметров и ограничений. Полный список можно найти в Электронной документации по SQL Server 2005 в теме "Создание индексированных представлений". Обязательно ознакомьтесь с этим списком, прежде чем приступать к использованию индексированных представлений, поскольку окончательный проект может оказаться слишком усложненным и не даст желательных преимуществ.

    Отслеживание изменений при помощи столбцов и таблиц аудита

    В предыдущих двух разделах мы узнали, как хранить итоговые архивные данные и осуществлять к ним доступ. Теперь мы познакомимся с некоторыми методами отслеживания меняющихся данных в самой таблице и за пределами исходной таблицы. Уровень аудита, который следует выбирать, зависит от того, что в действительности требуется узнать.

    Можно выбрать простой уровень аудита, при котором будет записываться только дата изменения, или сложный уровень, при котором будет вестись полная запись изменения с возможностью восстановления, если возникнет необходимость. В последнем варианте используются столбцы аудита, таблицы аудита или их сочетание.

    Аудит при помощи столбцов

    Преимущество аудита с помощью столбцов заключается в том, что контрольная информация размещается в той же таблице, что и данные. В табл. 7.1 перечислены некоторые столбцы аудита, которые обычно добавляются в таблицы.

    Различные типы столбцов аудита
    Отслеживаемые события Типы данных Комментарии
    INSERT, UPDATE, или DELETE DATETIME Используется для отслеживания даты и времени выполнения отслеживаемого действия.
    Обычно используется с функцией GETDATE() как значение по умолчанию, но значение может задаваться и вызывающим приложением.
    INSERT, UPDATE или DELETE VARCHAR Используется для отслеживания имени пользователя или приложения, выполняющего отслеживаемое действие.
    DELETE BIT/TINYINT Используется для того, чтобы пометить данные как удаляемые. Это может с большой эффективностью применяться в индексировании и фильтрации.

    По этой таблице можно сделать вывод, что изменения данных в действительности не протоколируются. Наиболее эффективный способ использования столбцов аудита – это отслеживание факта внесения изменения, времени изменения и лица или приложения, выполнившего это изменение. Можно использовать эти столбцы в любой комбинации, чтобы отслеживать изменения в записях в реальной таблице. В зависимости от особенностей приложения и выбранного уровня аудита, вы поймете, что эти столбцы удовлетворяют большей части потребностей в аудите на уровне записей.

    Настраиваем столбцы аудита

  • Сначала нужно определить события, которые нужно отслеживать. В этом примере вы научитесь добавлять столбцы аудита для отслеживания инициатора изменений, даты и времени создания записи, даты и времени последнего обновления записи и того, была ли удалена запись из таблицы Person.Address базы данных Adventure Works.
  • Выбрав таблицу ( Person.Address ) и определив события, которые будут отслеживаться, нужно решить, какие столбцы добавить в таблицу.
  • Столбец ModifiedDate уже существует в таблице. Он будет отслеживать дату, показывающую, когда запись была в последний раз изменена или удалена.
  • Столбец CreatedDate будет отслеживать, когда была создана запись. Тип данных этого столбца DATETIME, с использованием функции GETDATE() для предоставления текущей даты как значения по умолчанию.
  • Столбец ModifiedBy —это столбец VARCHAR, который будет содержать имя пользователя или некоторые другие средства для идентификации пользователя или приложения, которые внесли изменения.
  • Столбец IsDeleted - столбец с типом данных BIT, который будет использоваться для записи об удалении строки. Дата и пользователь будут отслеживаться через столбцы ModifiedDate и ModifiedBy. Если запись была удалена, этот столбец будет помечен, а в измененном столбце будут сведения о том, кто и когда удалил запись.
  • Теперь можно выполнить представленный ниже сценарий, чтобы изменить таблицу Person.Address (этот код можно найти в файлах примеров под именем AlterTable.sql ).
    USE AdventureWorks
    GO
    ALTER TABLE Person.Address
      ADD CreatedDate DATETIME NULL DEFAULT GETDATE()
         ,ModifiedBy VARCHAR(50) NULL
         ,IsDeleted BIT DEFAULT (0)
  • Далее, если вы изменяете таблицу с уже имеющимися данными, следует задать в столбце CreatedDate значение, показывающее, что столбец был создан до того, как был начат аудит. Чтобы задать значение CreatedDate, выполните следующий код:
    UPDATE Person.Address 
    SET CreatedDate = "1/1/1980";
  • Теперь нужно изменить хранимые процедуры и код приложения для заполнения этих столбцов нужными результатами. Для обновления столбцов можно использовать триггеры, но обычно лучше контролировать изменение данных и использовать для обновления столбцов аудита код приложения.
  • Последнее действие в этом процессе – это добавление фильтра ко всем процедурам и программам, ссылающимся на данную таблицу, чтобы предотвратить возвращение удаленных записей. Вот фильтр, который нужно использовать:
    WHERE IsDeleted = 0
  • Аудит с помощью таблиц

    Теперь мы знаем, как использовать аудит для уведомления о сделанных изменениях. Однако единственное изменение, которое может быть легко отменено - это событие DELETE. Достаточно просто сбросить флаг IsDeleted, и данные будут снова доступны. Существует также возможность отменить событие CREATE, если об этом действии имеется достаточная информация. Однако если нужно иметь возможность полностью отслеживать состояние данных перед изменением, возможно, лучшим вариантом окажется использование таблиц аудита. Эту возможность следует использовать с осторожностью, потому что она может вызвать много проблем с обслуживанием и производительностью. Такие проблемы возникают потому, что приходится копировать данные в таблицу аудита и изменять их в исходной таблице. Для этого примера мы зададим аудит на базе таблицы в таблице Sales.Special Offer. Цель – отслеживание любых изменений в этой таблице и обеспечение возможности отменить изменения после того, как они были зафи ксированы.

    Настраиваем таблицы аудита

  • Запустите SQL Server Management Studio и найдите в Object Explorer (Обозревателе объектов) в базе данных Adventure Works таблицу Sales.SpecialOffer.
  • Сгенерируйте базовый сценарий аудита, щелкнув правой кнопкой мыши таблицу Sales.SpecialOffer и выбрав из контекстного меню команды Script Table As, Create To, New Query Editor Window (Создать сценарий для таблицы, Используя CREATE, В новом окне редактора запросов). После этого откроется новое окно запроса с готовым для редактирования сценарием CREATE TABLE.
  • Отредактируйте сценарий, выполнив перечисленные ниже действия. Для этого примера окончательная редакция сценария показана в действии 4.
  • Сначала удалите все дополнительные сценарии. Нужно удалить все строки кода, которые не входят в инструкцию CREATE.
  • Затем измените имя таблицы с Sales.SpecialOffer на Sales.SpecialOffer_Audit.
  • Теперь удалите все ограничения для таблицы и разрешите для всех столбцов значения NULL. Благодаря этому таблица будет больше похожа на журнальную таблицу. В этом случае таблица аудита не должна мешать обычным операциям в таблице с самого начала. Это также должно упростить управление таблицей.
  • Добавьте все дополнительные столбцы, которые будут помогать в определении типа изменений, даты изменений и других элементов аудита, которые нужно отслеживать. В данном примере нужно добавить столбцы, перечисленные в табл. 7.2.
    Столбцы, которые нужно добавить в таблицу аудита
    Имя столбца Тип данных
    AuditModifiedDate DATETIME
    AuditType NVARCHAR(20)
  • Выполните окончательный сценарий, представленный ниже, в базе данных AdventureWorks. (Этот код можно найти в файлах примеров под именем CreateAuditTable.sql.)
    USE AdventureWorks;
    GO
    CREATE TABLE Sales.SpecialOffer_Audit(
        SpecialOfferID INT NULL,
        Description NVARCHAR(255) NULL,
        DiscountPct SMALLMONEY NULL,
        [Type] NVARCHAR(50) NULL,
        Category NVARCHAR(50) NULL,
        StartDate DATETIME NULL,
        EndDate DATETIME NULL,
        MinQty INT NULL,
        MaxQty INT NULL,
        rowguid UNIQUEIDENTIFIER NULL,
        ModifiedDate DATETIME NULL,
        AuditModifiedDate DATETIME NULL,
        AuditType NVARCHAR(20) null 
    ); 
    GO
    Совет. Возможно, придется создать новую схему для объектов аудита.
  • Запись данных аудита в таблицу аудита

    Основные способы перемещения данных в таблицы аудита в SQL Server 2005 - это триггеры базы данных и новое предложение T-SQL OUTPUT. Однако новое предложение OUTPUT добавляет некоторые интересные возможности. В следующем разделе мы на примере изучим каждый из этих двух вариантов.

    Используем триггер UPDATE для заполнения таблицы аудита

  • Создайте в таблице Sales.SpecialOffer триггер, который будет записывать предыдущее состояние данных в созданную нами таблицу Sales.SpecialOffer_Audit. Код, приведенный ниже – это пример синтаксической конструкции, которую можно использовать. (Этот код можно найти в файлах примеров под именем CreateTrigger.sql.) Введите и выполните код в окне нового запроса SQL Server Management Studio.
    USE AdventureWorks
    GO
    CREATE TRIGGER SpecialOfferUpdateAudit ON Sales.SpecialOffer
    FOR UPDATE
    AS
    INSERT INTO Sales.SpecialOffer_Audit 
           (SpecialOfferID
           ,Description
           ,DiscountPct
           ,[Type]
           ,Category
           ,StartDate
           ,EndDate
           ,MinQty
           ,MaxQty
           ,rowguid
           ,ModifiedDate
           ,AuditModifiedDate
           ,AuditType) 
    SELECT TOP 1 d.SpecialOfferID
                ,d.Description
                ,d.DiscountPct
                ,d.[Type]
                ,d.Category
                ,d.StartDate
                ,d.EndDate
                ,d.MinQty
                ,d.MaxQty
                ,d.rowguid
                ,d.ModifiedDate
                ,GETDATE()
                ,'UPDATE' 
      FROM deleted d; GO
  • Примечание. Если вы не делали никаких изменений в таблице Sales.SpecialOffer, скорее всего, вам придется удалить триггер, который уже существует в таблице ( uSpecial Offer ). Необходимо сохранить сценарий для триггера, чтобы можно было использовать его в дальнейшем. Если этот триггер не удалить, то вы будете получать строки данных в таблице Sales.SpecialOffer_Audit при любом обновлении таблицы.

    Преимущество использования триггера заключается в том, что он будет захватывать любые обновления, которые произойдут в таблице, независимо от их источника. Это вариант аудита с полным охватом. Если речь идет о данных, которые изменяются без контроля с вашей стороны, то это превосходный вариант. Но если вы тщательно контролируете данные, которые заносятся в таблицу, особенно если это выполняется при помощи хранимых процедур, то в SQL Server 2005 есть новая возможность аудита изменений - предложение OUTPUT.

    Используем предложение OUTPUT для заполнения таблицы аудита

  • Чтобы эффективно использовать предложение OUTPUT, каждое событие, которое нужно отслеживать, потребует разработки хранимых процедур и инструкций SQL, которые будут использоваться для обновления ( UPDATE ), вставки ( INSERT ) или удаления ( DELETE ) данных в отслеживаемых таблицах. Предложение OUTPUT предоставляет доступ к вставляемым и удаляемым таблицам в этих процедурах и инструкциях SQL. Теперь не обязательно использовать триггеры для доступа к данным. Представленный ниже код показывает пример использования предложения OUTPUT для аудита обновления в таблице SpecialOffer в таблице SpecialOffer_Audit. (Этот код можно найти в файлах примеров под именем UsingOutputClause.sql.) Введите и выполните данный код в окне нового запроса SQL Server Management Studio.Важно. Предложение OUTPUT должно вставлять свои данные в табличную переменную, во временную таблицу или - как в данном случае - в постоянную таблицу.
    USE AdventureWorks
    GO
    UPDATE Sales.SpecialOffer
    SET description = "Big Mountain Tire Sale" 
    OUTPUT deleted.SpecialOfferID
          ,deleted.Description
          ,deleted.DiscountPct
          ,deleted.[Type]
          ,deleted.Category
          ,deleted.StartDate
          ,deleted.EndDate
          ,deleted.MinQty
          ,deleted.MaxQty
          ,deleted.rowguid
          ,deleted.ModifiedDate
          ,GETDATE()
          ,'UPDATE' INTO Sales.SpecialOffer_Audit 
      WHERE SpecialOfferID = 10
  • Предложение OUTPUT помещает измененные данные в рамках простого доступа в процессе изменения данных. В процессе операций UPDATE и DELETE доступен префикс DELETED. В процессе операций UPDATE и INSERT доступен префикс INSERTED. Обратите внимание на то, что оба префикса не могут быть доступными одновременно, в отличие от таблиц deleted и inserted, которые используются в триггерах. Эта взаимоисключающая доступность требует, чтобы различные операции обрабатывались по-разному для сбора нужных данных и помещения их в таблицы аудита.Совет. Предложение OUTPUT можно также использовать для возвращения значения из столбца IDENTITY в процессе операции INSERT.
  • Восстановление данных с помощью таблиц аудита

    Теперь, когда у нас есть два варианта загрузки данных в таблицу аудита, можно подумать, для чего использовать эти данные. Поскольку все изменения в таблице сохраняются в таблице аудита, можно восстановить любые изменения данных, перезаписав текущие данные изменением, которое нужно сохранить. Таблица аудита может хранить несколько версий данных, поэтому чаще всего это придется делать вручную. Однако можно также создать обслуживающую хранимую процедуру для отмены самого последнего изменения.

    Используем таблицу аудита для восстановления измененных данных

  • Определите, какую запись следует восстановить. Для этого нужно будет идентифицировать изменяемую запись и данные, которые ее заменят.
  • Воспользуйтесь приложением UPDATE для перезаписи текущих данных изменением, которое следует восстановить в этой таблице. В данном примере придется использовать либо свойство rowguid, либо столбец SpecialOfferID в сочетании с AuditModifiedDate в качестве критерия для инструкции UPDATE, как показано ниже. (Этот код можно найти в файлах примеров под именем RecoveringChangedData.sql.) Введите и выполните этот код в окне нового запроса SQL Server Management Studio.
    — В этом сценарии нужно заменить AuditModifiedDate на
    —AuditModifiedDate из таблицы SpecialOffer_Audit
    USE AdventureWorks
    GO
    UPDATE Sales.SpecialOffer
    SET Description = a.Description
       ,DiscountPct = a.DiscountPct
       ,Type = a.Type
       ,Category = a.Category
       ,StartDate = a.StartDate
       ,EndDate = a.EndDate
       ,MinQty = a.MinQty
       ,MaxQty = a.MaxQty
       ,rowguid = a.rowguid
       ,ModifiedDate = a.ModifiedDate 
      FROM Sales.SpecialOffer_Audit a 
      WHERE SpecialOffer.SpecialOfferID = 10
        AND a.SpecialOfferID = 10
        AND a.AuditModifiedDate = "2006-04-02 22:40:27.513"
  • Если у вас есть данные, которые нуждаются в регулярном восстановлении, можно инкапсулировать приведенный выше код в хранимую процедуру обслуживания. Однако если вы решите реализовать ее, у вас могут возникнуть проблемы с вводом восстановленных данных. Описанные варианты хорошо подходят для ограниченного количества строк в одной таблице. Если вы работаете с массовой высокопроизводительной загрузкой в нескольких таблицах, следует использовать моментальные снимки, о которых шла речь в первом разделе данной лекции.

    Заключение

    Вы научились создавать моментальные снимки данных. Моментальные снимки могут эффективно использоваться для решения различных задач в процессе разработки, тестирования и производства. Можно использовать архивные данные для подведения итогов и анализа данных на определенных отрезках времени. Вы также научились выполнять аудит изменений данных и восстанавливать отдельные записи при помощи данных аудита. Сохраняя архивные данные и отслеживая изменения в базе данных, можно обеспечить целостность данных, используя возможность отмены отдельных изменений, не восстанавливая всю базу данных.

    Чтобы Выполните следующие действия
    Создать моментальный снимок базы данных Воспользуйтесь инструкцией CREATE DATABASE с параметром AS SNAPSHOT OF.
    Вернуться к моментальному снимку базы данных Воспользуйтесь инструкцией RESTORE DATABASE с параметром FROM SNAPSHOT.
    Удалить моментальный снимок базы данных Воспользуйтесь инструкцией DROP DATABASE или удалите моментальный снимок базы данных через интерфейс SQL Server Management Studio.
    Запланировать загрузку архивных данных Создайте новое задание в агенте SQL Server и составьте расписание которое будет удовлетворять вашим потребностям.
    Вывести итоговую информацию за определенный отрезок времени Создайте индексированное представление для вывода итогов по одному или нескольким временным отрезкам.
    Вести аудит изменений данных Добавьте в таблицу столбцы аудита, в которых будет отслеживаться, кто и когда внес изменение.
    Отслеживать все изменения данных и иметь возможность восстановить данные после ошибки ввода Создайте и загрузите таблицу аудита либо при помощи триггеров, либо при помощи предложения OUTPUT.
    Вернуться к учебному плану