С этим механизмом связано несколько неизбежных проблем. Для начала, в 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. Простой запрос к этому представлению может дать следующую информацию:
По значениям столбцов 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-блоке, который не слишком способствует параллелизму и масштабируемости .
Я подозреваю, что это изменение было сделано как "аварийное" в ответ на обнаружившееся отсутствие необходимой перегенерации условий защиты, связанных с моментом времени. Ответ, однако, несколько экстремальный. Проблема была решена несколько более тонко в версии 10g сервера Oracle, где появилось несколько уровней "изменяемости" в качестве типа набора правил.
Завершающее соображение - есть рекомендация Oracle не использовать, по возможности, соединения с таблицами, для которых предполагается подобная защита (подумайте, к чему могут привести все эти вложенные представления) и постараться свести условия защиты к простому использованию функции sys_context(). Но посмотрите, что говорит руководство SQL Reference
(версия 9.2, стр. 6-154) о функции sys_context():
Примечание: SYS_CONTEXT возвращает атрибуты сеанса. Поэтому ее нельзя использовать в параллельных запросаз или в среде Real Application Clusters.