Проблемы
С этим механизмом связано несколько неизбежных проблем. Для начала, в Oracle 8.1 нигде в системе вообще нельзя увидеть сгенерированное условие- ни в представлении v$sql, ни в трассировочных файлах
измененного SQL-оператора просто нет. Эту проблему можно обойти, установив для sql_trace значение true, а затем установив событие 10730
в сеансе, использующем RLS. После этого каждый полный разбор (hard parse) оператора будет генерировать раздел в трассировочном файле, который будет иметь примерно следующий вид:
Logon user : U1 Table/View : TEST_USER.STOCK_LEVEL Policy name : STOCK_RESTRICT Policy function: TEST_USER.STOCK_PREDICATE RLS view : SELECT "STOCK_DATE","PRODUCT_ID","QTY","DEPT_ID","SUPPLIER_CODE" FROM "TEST_USER". "STOCK_LEVEL" "STOCK_LEVEL" WHERE (supplier_code = 'Hershey')
Эта проблема была решена в Oracle 9 (хотя эффективность решения вызывает некторые сомнения) путем добавления представления v$vpd_policy. Простой запрос к этому представлению может дать следующую информацию:
ADDRESS : 6F5664F0 PARADDR : 6F5638AC SQL_HASH : 1816753535 CHILD_NUMBER : 0 OBJECT_OWNER : TEST_USER OBJECT_NAME : STOCK_LEVEL POLICY_GROUP : SYS_DEFAULT POLICY : STOCK_RESTRICT POLICY_FUNCTION_OWNER : TEST_USER PREDICATE : supplier_code = 'Hershey'
По значениям столбцов paraddr, sql_hash и child_number
из этого представления можно сделать примерно такой запрос к представлению v$sql, находящий соответствующий SQL-оператор:
Select sql_text from v$sql where address = '6F5F0020' and hash_value = 2621366196 and child_number= 0
Неэффективность здесь в том, что представление v$vpd_policy строиться, в том числе, по объекту x$kglcursor, который и так является базовым для представления v$sql - так что вы вполне можете задать собственную версию представления v$vpd_policy во избежание бессмысленного дополнительного соединения. Но и в этом случае нет эффективной связи между двумя объектами x$, лежащими в основе представления.
Но есть и другие проблемы - я обещал еще раз упомянуть о параметре
static_policy процедуры
add_policy. Этот булев параметр появился в Oracle 9, чтобы вы могли выбрать из двух зол. Если установить этому параметру значение
true, то обеспечивающее защиту условие, похоже, будет генерироваться только один раз, при первом полном разборе, а это означает, что пользователь
u2 в конечном итоге сможет выполнять в точности тот же запрос, что и пользователь
u1, если окажется, что пользователь
u1
первым выполнил запрос.
С другой стороны, если установить этому параметру значение
false, то функция защиты выполняется (предположительно, дважды) при каждом
выполнении (а не только
разборе) запроса, и выполняется она в следующем, достаточно объемном анонимном pl/sql-блоке, который не слишком способствует параллелизму и масштабируемости .
begin p := STOCK_PREDICATE(:sn,:on); :v1 := substr(p,1,4000); :v2 := substr(p,4001,4000); :v3 := substr(p,8001,4000); :v4 := substr(p,12001,4000); :v5 := substr(p,16001,4000); :v6 := substr(p,20001,4000); :v7 := substr(p,24001,4000); :v8 := substr(p,28001,4000); :v9 := substr(p,32001,767); :v10 := substr(p, 4000, 1); :v11 := substr(p,8000,1); :v12 := substr(p, 12000, 1); :v13 := substr(p,16000,1); :v14 := substr(p, 20000, 1); :v15 := substr(p,24000,1); :v16 := substr(p, 28000, 1); :v17 := substr(p,32000,1); end;
Я подозреваю, что это изменение было сделано как "аварийное" в ответ на обнаружившееся отсутствие необходимой перегенерации условий защиты, связанных с моментом времени. Ответ, однако, несколько экстремальный. Проблема была решена несколько более тонко в версии 10g сервера Oracle, где появилось несколько уровней "изменяемости" в качестве типа набора правил.
Завершающее соображение - есть рекомендация Oracle не использовать, по возможности, соединения с таблицами, для которых предполагается подобная защита (подумайте, к чему могут привести все эти вложенные представления) и постараться свести условия защиты к простому использованию функции
sys_context(). Но посмотрите, что говорит руководство SQL Reference
(версия 9.2, стр. 6-154) о функции
sys_context():
Примечание: SYS_CONTEXT возвращает атрибуты сеанса. Поэтому ее нельзя использовать в параллельных запросаз или в среде Real Application Clusters.
Содержание раздела