Welcome to TechNet Blogs Sign in | Join | Help

SQL Server 2005: права доступа типа - Control

Знаете ли Вы что

 

В SQL Server 2005 возможно дать пользователю права доступ типа Control к объекту (таблице, виду и т.д.), который фактически дает те же права, что и у собственника объекта.

 

Пример:

GRANT CONTROL

ON t_Table TO Uesr1

GO

 

Control имеет некоторые особенности.

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

 

Например:

1. пользователь User1 дал права доступа типа Select к объекту Table пользователю User2;

2. права пользователя User1 по доступу к объекту Table были отменены с использованием опции Cascade;

3. в результате User2 также лишился прав доступа к объекту.

 

С Control ситуация выглядит иначе.

 

Пример:

 

1.владелец объекта дал права доступа к объекту типа Control пользователю User1 с использованием опции GRANT OPTION;

2.пользователь User1 дал права доступа типа Control пользователю User2;

3.права пользователя User1 по доступу к объекту были отменены с использованием опции Cascade;

4.пользователь User2 по-прежнему имеет права Control на объект.

 

Grant Control on T

to usr1

WITH GRANT OPTION

go

 

Execute as user = 'usr1'

go

 

Grant Control on T

to usr2

go

 

REVERT

go

 

Revoke Control on T

from usr1 Cascade

go

 

--Usr2 по-прежнему имеет права Control на T

 

Как обойти эту ситуацию

Если требуется, чтобы права Control были отменены у всех пользователей, которым их дал User1, User1 должен быть явно указан в момент предоставления прав другому пользователю:

 

Grant Control on T

to usr2

as usr1

go

Использование оператора OUTPUT для отслеживания изменений DML

Знаете ли вы, что…

 

Вы можете отслеживать изменения данных без использования триггеров:

 

В SQL Server 2005 оператор OUTPUT является частью синтаксиса DML предложений.

Например:

 

INSERT

    [ TOP ( expression ) [ PERCENT ] ]

    [ INTO ]

    { <object> | rowset_function_limited

      [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]

    }

{

    [ ( column_list ) ]

    [ <OUTPUT Clause> ]

    { VALUES ( ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n ] )

    | derived_table

    | execute_statement

    | <dml_table_source>

    | DEFAULT VALUES

    }

}

 

Оператор OUTPUT может сохранять результирующее множество строк затронутых DML оператором в таблицу или переменную типа таблица.

Например, сохранить все добавленные (или удаленные) строки.

 

Функционально это похоже на промежуточные таблицы INSERTED и DELETED, используемые триггерами.

 

Пример:

--Создадим таблицу Address

Create Table Address (ProductID Int, SupplierID Int, Address Varchar(255))

 

--Вставим данные в таблицу

Insert into Address Values (234,567,'1234 One SQL Way, Microsoft City, U.S.')

Insert into Address Values (345,678,'1234 One Windows Way, Microsoft City, WA')

 

--Объявим табличную переменную

Declare @Recordchanges table (change Varchar(255))

 

--Обновим данные в таблице

Update Address

Set Address=reverse(address)

--Запишем изменения в табличную переменную

OUTPUT 'Изначальные данные:' + DELETED.Address+' изменены на: '+ INSERTED.Address+'' into @RecordChanges

 

--Читаем изменения из табличной переменной

Select * from @RecordChanges

 

На выходе имеем:

 

Change

------------------------

Изначальные данные:'1234 One SQL Way, Microsoft City, U.S.' has been изменены на: '.S.U ,ytiC tfosorciM ,yaW LQS enO 4321'

 

Изначальные данные:'1234 One Windows Way, Microsoft City, WA' has been изменены на: 'AW ,ytiC tfosorciM ,yaW swodniW enO 4321'

 

Извещение об изменениях в результатах запроса (Query Notification)

Знаете ли вы, что…

 

Query Notification в SQL 2005 – новая функциональность, позволяющая отправить запрос на SQL Server и потребовать генерации извещения в случае, если исполнение этого запроса вернет результат отличный от полученного изначально. Это значит, что если произошли какие-то изменения в данных таблиц, включенных в запрос, .NET код будет автоматически извещен.

 

Команды, посылаемые на сервер через клиентский API(ADO.NET, OLE DB, ODBC, SOAP) могут содержать свойство Notification, которое создать «подписку» на оповещение об изменении данных.

 

Например:

……………………………………………………………………………

SqlConnection c = new SqlConnection(…………………………);

SqlCommand cm = c.CreateCommand();

 

cm.CommandText = "Select id, time from dbo.t_table";

 

SqlString notifyId = "Notification_Id";

SqlString notifOpt = "service = service_name; local database = database_name";

int timeOut = 50000;

 

cm.Notification = new SqlNotificationRequest (notifyId.ToString(), notifOpt.ToString(), timeOut);

……………………………………………………………………………

 

Теперь, если результат, возвращаемый запросом Select id, time from dbo.t_table изменится, приложение получит извещение.

 

Эта технология может быть особенно полезна для кэширования результатов для web-сайтовских приложений.

 

Более подробно (но на английском J) можно почитать, например, здесь:

http://msdn2.microsoft.com/en-us/library/ms379594(VS.80).aspx

 

Исполнения T-SQL команд на удаленном сервере с помощью EXECUTE AT

Ну, вот. С индексами разобрались. Теперь, как и обещала, короткие (и не очень) сообщения в стиле «Tips & Tricks».

 

Знаете ли вы, что…

 

В предыдущих версиях SQL Server (до SQL Server 2005) команду EXECUTE можно было выполнять только на локальном сервере. В SQL Server 2005 команда EXECUTE имеет параметр AT, который используется для выполнения EXECUTE на удаленном linked сервере.

 

Пример:

--------

 

--Добавим linked сервер на локальной машине:

EXEC sp_addlinkedserver 'SQLSERVER2', 'SQL Server'

 

--Разрешим RPC вызовы

Exec SP_Serveroption 'SQLSERVER2','RPC OUT',TRUE

 

Все готово для выполнения T-SQL команд на linked сервере:

 

EXEC('Select * from AdventureWorksDW..DatabaseLog') AT SQLSERVER2

Построение индексов – часть 7: Фоновое построение индексов (Часть 2)

Последовательность фонового построения индекса:

    1.   Ждем пока завершаться исполняющиеся на данный момент DML операции;

  1. Берем Intend Share (IS) блокировку на таблицу - эта блокировка будет держаться до конца построения индекса, что ограничивает набор операций выполняемых в параллель с построением индекса. (Например: truncate table, BCP операции будут недоступны); 
  2. Берем Share (S) блокировку, чтобы просканировать таблицу. Эта блокировка держится в течении короткого времени; любые параллельные операции на данных невозможны в этот период;
  3. Отпускаем Share блокировку; 
  4. Собственно построение индекса – сканирование, сортировка, построение индексного дерева; 
  5. Если нужно перестроит некластерные индексы* – возвращаемся к шагу 2 и повторяем для каждого индекса;
  6. Заканчиваем построение:

а. Если удаляется существующий индекс берем Schema Modification блокировку (SCH_M). Например: построение кластерного индекса требует удаления кучи – следовательно необходимо взять SCH_M блокировку**. Эта блокировка конфликтует с любой параллельной деятельностью, включая чтение данных (Select);

б. Если просто создается некластерный индекс – берется S блокировка;

в. Изменяем версию метаданных для таблицы;

г. Отпускаем блокировки;

д. Отложенное удаление старых индексов.

 

** Когда кластерный индекс модифицируется в фоновом режиме, все некластерные индексы, существующие на таблицы также перестраиваются. 

*** Когда мы держим S или Sch_M блокировки, которые конфликтуют с параллельными операциями на таблице, параллельно исполняющаяся транзакция не будет отвергнута. Она будет ждать, пока

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

 

Некоторые соображения об использовании дискового пространства:

 

            Построение/ перестроение кластерного индекса в фоновом режиме требует дополнительного дискового пространства для хранения промежуточных данных. В некоторых  (экстремальных) случаях  - больше размера самого индекса. Эти промежуточные данные будут храниться там же где хранятся промежуточные структуры сортировки (либо tempdb, либо пользовательская база данных) – см. предыдущие посты. Это дополнительное пространство будет освобождено после завершения построения индекса.

 

Некоторые соображения производительности:

 

            Производительность фонового построения некластерных индексов  не должна сильно отличаться от производительности автономного построения некластерных индексов (предполагая, что нет параллельно исполняющихся DML).  

Производительность фонового построения кластерных индексов хуже производительности автономного построения кластерных индексов (даже без параллельно исполняющихся DML).

При наличии параллельно исполняющихся DML, производительность, как построения индекса, так и DML, будет хуже. Конкретные цифры можно посмотреть в документе, который мы недавно опубликовали, и который посвящен фоновому построению индексов. Документ на английском, так что, если будут вопросы – задавайте. Документ здесь: http://download.microsoft.com/download/8/5/e/85eea4fa-b3bb-4426-97d0-7f7151b2011c/OnlineIndex.doc

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

Построение индексов – часть 7: Фоновое построение индексов (Часть 1)

В SQL Server 2005 стало возможно строить, перестраивать и удалять* индексы фоновом режиме. Это позволяет проводить текущее обслуживание, не прерывая основной работы. Опция «ONLINE» делает возможным параллельный доступ к данным таблицы/индекса во время построения/перестроения индекса. Например, когда один пользователь перестраивает кластерный индекс, другой пользователь может получать и обновлять данные таблицы, для которой перестраивается индекс. Для сравнения: при автономном построении индекса, построитель индекса держит эксклюзивную блокировку на таблицу и индекс в течение всего времени построения, что не дает получать или обновлять данные таблицы/индекса.

*Операция фонового удаления индекса возможна только для кластерного индекса (см. также «соображения производительности» в следующем сообщении).

 

Пример:

 

Create clustered Index idx_01 on t_01(c1)

WITH(ONLINE = ON)

go

 

Фоновое построение индексов имеет определенные ограничения:

 

·         Если таблица имеет солонки типа:  image, ntext, text, varchar(max), nvarchar(max), varbinary(max), xml - кластерный индекс на такой таблице может быть построен только в автономном режиме (Offline).

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

·      Индексы на локальных временных таблицах не могут быть построены, перестроены или удалены в фоновом режиме. Однако, это ограничение не распространяется на глобальные временные таблицы.

(подробный список ограничений для фоновых индексных операций см. документацию)

Таблица, для которой строится (перестраивается, удаляется) индекс не может модифицироваться (Alter table), удаляться и для нее нельзя выполнять операцию Truncate во время фоновой индексной операции.

Когда кластерный индекс таблицы перестраивается, то все не-кластерные индексы, существующие на той же таблице, также перестраиваются в фоновом режиме.

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

Несколько не-кластерных индексов могут строиться в фоновом режиме для одной таблицы параллельно.  Все остальные фоновые операции индексирования не могут выполняться параллельно друг с другом на одной таблице.

Читайте продолжение о фоновом построении индексов в следующих  постах J

Построение индексов – часть 6: построение секционированного индекса (Продолжение – Невыровненные индексы)

Параллельное построение невыровненных секционированных индексов (продолжение)

 

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

 

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

 

Пример:

 

Create Partition Function pf (int)

as range right for values (1,  100, 1000)                 

 

Create Partition Scheme ps as Partition pf

TO ([PRIMARY], [FG1], [FG2], [FG3])

 

Create table t (c1 int, c2 int)

on ps(c2)

 

Create clustered Index idx_t on t(c1)

on ps(c1)

 

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

 

Построитель