Oracle 12c。 新機能は新しい落とし穴をもたらします

みなさんこんにちは。



Oracle 12cの新機能を解析すると、すべてが期待どおりに動作しない、クラッシュする、または単に明らかでない場合に、落とし穴に遭遇します。 もちろん、これは、新しいバージョンの最初のリリースに多くの生データが含まれる場合の標準的な状況です...しかし、ご存じのように、警告は武装を意味します。 おそらく、私のレーキを繰り返さないために誰かが重宝します。



私は彼らを攻撃する順番でレーキを書いています。



PS:編集:最後に、すぐに書き忘れたバグを追加しました(PL / SQLで使用し、PL / SQLを使用するWITHのSQLコンストラクトを使用)。





ローカルリスナーを使用したPMONの紹介


単純なものから始めましょう。これはバグではなく、構成の問題です。

Oracle 12cの標準インストールおよび構成でインストールされます(私の場合-Oracle Linux上ですが、重要ではないと思います)。

-CDBデータベースを作成します。

-PDBベースを接続/作成します。

デフォルトでは、追加されたデータベースはリスナーに表示されません。 「すぐに使える」PMONは、同じサーバー上に住んでいるリスナーと友達にならず、自動登録は行われません。 しかし、悲劇ではありませんが、自分の手でlistener.oraに手を追加することは、新しいマルチテナントアーキテクチャ機能のコンテキストでは何とか面白くありません。

PMONとローカルで生きているリスナーを紹介しましょう。



ALTER SYSTEM SET local_listener='(ADDRESS = (PROTOCOL=TCP)(HOST=192.168.56.101)(PORT=1521))' scope=both; ALTER SYSTEM REGISTER;
      
      







ベースが登録され、リスナーは喜びが訪れたのを見ました。 この機能が正確に12-kiであるとは言えませんが、文字通り外出先でデータベースを追加/管理することが可能になり、マルチテナントアーキテクチャのフレームワーク内で、リスナーへのデータベースの自動登録がこれまで以上に重要になりました。 以前は、新しいデータベースの作成ははるかに大きな「イベント」であり、listener.oraに2、3行追加しても偏見はありませんでした。



再起動後のPDBの自動起動


サーバーを再起動します。 CDBは上昇しています。 PDB-開いていません(データベース接続がシャットダウンまたは起動中のエラーに失敗しました)。

サーバーの再起動後、管理者がCDBデータベースに接続して次のように言う必要があるかもしれません。

 alter pluggable database all open;
      
      





ベースは再起動しないようです(そうすべきではありません)...しかし、これを控えめに言っても便利ではないということがわかります。 そして、数十と数百のデータベースを同時にサポートするDBAは、明らかに感謝の意を表明しません。

PDB-shkiをすべて同じように起動する必要があることをOracleに確信させる設定またはコマンドは検出されませんでした(おそらく見た目が悪いかもしれません。誰かが見つかったらコメントで教えてください)。

全知インターネットでは、この瞬間はもはやニュースではなく、最も一般的な推奨事項です。

 create or replace trigger open_all_pdb after startup on database BEGIN  execute immediate 'alter pluggable database all open'; END open_all_pdbs;
      
      







個人的な信念のために、私はトリガーが本当に好きではありませんが、この場合、これは利用可能な最小の悪のようです。



非表示の列


この機能はOracleではなく、PL / SQL開発者(バージョン10.0.1.1694-最近PL / SQL Developerサイトからダウンロードされました)ですが、まだです。

非表示のsqlplus列の動作を比較します(ドキュメントによるとリード):

 SQL> descr test_invisible; Name Null? Type ------------------ -------- ----------- ID NUMBER(38) THIRD_COL NUMBER(38)
      
      







PL / QSL Developerコマンドウィンドウ:

 SQL> descr test_invisible; Name Type Nullable Default Comments --------- ------------ -------- ------- -------- ID INTEGER Y THIRD_COL INTEGER Y INV_COL VARCHAR2(20) Y
      
      





これまでのところ、Pl / Sql開発者は新機能については知りませんが、驚くことではありません。 しかし、PL / SQL開発者のコ​​マンドウィンドウが正直なsql *プラスではなく、単なるパイプのようなものであるだけでなく、擬似的なインターフェースであることに誰もが気づいていません。

彼らはすぐに自分の感覚に達すると思いますが、最初の瞬間、私はいくらか驚き、思慮深くなりました。



でのPL / SQLサポート


Oracleによると、この機能は主にパフォーマンスを向上させるために作成されたものであり(投稿のトピックを取り上げているため、機能の詳細な検討は括弧の外に残します)、プラグマUDFはこれらの目的で機能することを悪化させることはありませんが、...

「BUT」は、ジョナサンルイスによって発見され、彼のブログで説明されているバグです。

(場合によっては)ポラマリの1つのパフォーマンス「機能」を追加します-もう1つは決定的です。



次のコード例を検討してください。



 --         . CREATE TABLE all_ones AS SELECT 1 AS ID FROM dual CONNECT BY LEVEL<100; SET TIMING ON ARRAYSIZE 15 WITH FUNCTION slow_function(p_id IN NUMBER) RETURN NUMBER DETERMINISTIC IS BEGIN DBMS_LOCK.sleep(1); RETURN p_id; END; SELECT slow_function(ID) FROM all_ones WHERE ROWNUM <= 10; / …. 10 rows selected. Elapsed: 00:00:10.02
      
      







ただし、公平に言えば、これはすべての場合に現れるわけではありません。



 WITH FUNCTION slow_function(p_id IN NUMBER) RETURN NUMBER DETERMINISTIC IS BEGIN DBMS_LOCK.sleep(1); RETURN p_id; END; SELECT slow_function(1) FROM all_ones WHERE ROWNUM <= 10; / 10 rows selected. Elapsed: 00:00:01.01 WITH FUNCTION slow_function(p_id IN NUMBER) RETURN NUMBER DETERMINISTIC IS BEGIN DBMS_LOCK.sleep(1); RETURN p_id; END; SELECT (SELECT slow_function(id) FROM dual) FROM all_ones WHERE ROWNUM <= 10; / Elapsed: 00:00:01.02
      
      







SQLテキスト展開


もう1つの優れた革新は、新しいプロシージャDBMS_UTILITY.EXPAND_SQL_TEXTです-以前にハブで既に説明しました。

私がテストしたとき、VPDを使用してビューとテーブルの両方で素晴らしい動作をしました...そして、たとえばall_users ...で、all_objectsに適用しようとすると、dbms_utilityパッケージでエラーが発生しました。 その理由は、DBAロールを持つユーザーでさえ、一部の完全に内部的なシステムオブジェクトへのアクセスを表示しなかったからだと思われます...または、コードのバグだけかもしれません。



 DECLARE x CLOB; BEGIN dbms_utility.expand_sql_text(input_sql_text => 'select * from all_objects', output_sql_text => x ); dbms_output.put_line(x); END; ORA-00904: : invalid identifier ORA-06512: at "SYS.DBMS_UTILITY", line 1581 ORA-06512: at line 3
      
      







そして、私が遭遇しなかったいくつかの事柄がありますが、他の人から読むことも興味深いものでした:



DBMS_METADATAとセッションシーケンス


sql.ruのトピックの1つにあります。

DBMS_METADATAはまだ新しい機能を認識していないようです。



 --   sequence create sequence seq session; DECLARE x CLOB; begin x:=dbms_metadata.get_ddl( 'SEQUENCE', 'SEQ'); dbms_output.put_line(x); end; / --   seqence,   session.  . CREATE SEQUENCE "DENKREP"."SEQ" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOPARTITION;
      
      







取得のための行数のページネーション、配列、およびランタイム計算


ブログの人で発見

 SQL> declare 2 type table_tt is table of employees%rowtype; 3 v_tt table_tt; 4 5 v_limit_nr number:=10; 6 v_counter_nr number:=0; 7 begin 8 select * 9 bulk collect into v_tt 10 from employees 11 offset v_counter_nr*v_limit_nr rows 12 fetch next v_limit_nr rows only; -- variable 13 end; 14 / type table_tt is table of employees%rowtype; * ERROR at line 2: ORA-03113: end-of-file on communication channel Process ID: 3060 Session ID: 20 Serial number: 35307 SQL> --       ,   . ... 12 fetch next 10 rows only; -- hard-code 13 end; 14 / PL/SQL procedure successfully completed. SQL>
      
      







PS:ソースへのコメントで、彼らはOracleがすでにバグと金属製品のバグについて知っていると書いています#17404511



PPS:後で追加しました(もっと覚えておいてください)



PL / SQLでのSQLでのPL / SQLサポート


名前はバターです。 それを理解しましょう。

PL / SQLはSQL言語の拡張機能をまだ認識しておらず、そのようなSQL構造をまだサポートしていないようです:



 SQL> DECLARE dummy NUMBER; BEGIN WITH FUNCTION test_with (n_id IN NUMBER) RETURN NUMBER IS BEGIN dbms_output.put_line(n_id); RETURN n_id; END; SELECT test_with(ID) INTO dummy FROM t1 WHERE ROWNUM < 2; dbms_output.put_line(dummy); END; / WITH FUNCTION test_with (n_id IN NUMBER) RETURN NUMBER IS * ERROR at line 4: ORA-06550: line 4, column 17: PL/SQL: ORA-00905: missing keyword ORA-06550: line 4, column 3: PL/SQL: SQL Statement ignored ORA-06550: line 6, column 4: PLS-00103: Encountered the symbol "SELECT"
      
      







同時に、動的SQLでも正常に機能します(予想どおりですが、それでも):



 DECLARE dummy NUMBER; BEGIN EXECUTE IMMEDIATE 'WITH FUNCTION test_with (n_id IN NUMBER) RETURN NUMBER IS BEGIN dbms_output.put_line(n_id); RETURN n_id; END; SELECT test_with(ID) FROM t1 WHERE ROWNUM < 2' INTO dummy; END;
      
      







今のところすべてです。 面白かったと思います。



All Articles