PostgreSQL 10 partition Declerative Partition


   Merhabalar, PostgreSQL 10 'da Partition yapısı her versiyonunda değişiklik gösterdiği gibi diğer platformlar Oracle, MsSql gibi VeriTabanlarından da oldukça farklılık gösterir.
   Postgres 9.x versiyonlarında Tablonun partitionu bir trigger yardımı ile yapılmakta ve fiziksel olarak child tablolar yaratılmakta.
   Postgres 10 versiyonu ile önceki versiyonlarda Tabloları partition ve child tabloları adreslemek için kullanılan bu trigger yapısından kurtulmuş oluyoruz. (Kurtuluş tabi nereden baktığınıza bağlı :) )
   Declerative Partition yapısı ile yine fiziksel child tabloları manuel yaratıp Indexlerini de Local olarak bu fiziksel tablolara yaratıyoruz.
   Aşağıda bir örnekleme yaptım. Bu örnekte bir Log Tablosu ve günlere göre Range Partition yapısı mevcut.

CREATE TABLE Table_Log (
    id INTEGER NOT NULL,
    operation_date  timestamp without time zone NOT NULL,
    response_time integer
)PARTITION BY RANGE (operation_date)
TABLESPACE pg_default;

Child tabloları oluşturuyoruz.. Oracle ve MSSQL den tamamen farklı bir mantık.

CREATE TABLE Table_Log_20180131 PARTITION OF Table_Log FOR VALUES FROM ('31-JAN-18') TO ('01-FEB-18');
CREATE TABLE Table_Log_20180201 PARTITION OF Table_Log FOR VALUES FROM ('01-FEB-18') TO ('02-FEB-18');
CREATE TABLE Table_Log_20180202 PARTITION OF Table_Log FOR VALUES FROM ('02-FEB-18') TO ('03-FEB-18');
CREATE TABLE Table_Log_20180203 PARTITION OF Table_Log FOR VALUES FROM ('03-FEB-18') TO ('04-FEB-18');

Şimdi bu tablolara birer index tanımı yapalım.

CREATE TABLE Table_Log_20180131 PARTITION OF Table_Log FOR VALUES FROM ('31-JAN-18') TO ('01-FEB-18');

CREATE TABLE Table_Log_20180201 PARTITION OF Table_Log FOR VALUES FROM ('01-FEB-18') TO ('02-FEB-18');
CREATE TABLE Table_Log_20180202 PARTITION OF Table_Log FOR VALUES FROM ('02-FEB-18') TO ('03-FEB-18');
CREATE TABLE Table_Log_20180203 PARTITION OF Table_Log FOR VALUES FROM ('03-FEB-18') TO ('04-FEB-18');

Evet Range partition tablomuz basic olarak hazır. Bunun yanında List partitionda kullanabilirsiniz. Pk kullanmak isterseniz bunu child tabloları yaratırken oluşturmanız gerekiyor.

CREATE TABLE Table_Log_20180131 PARTITION OF Table_Log (operation_date, PRIMARY KEY (id)) FOR VALUES FROM ('31-JAN-18') TO ('01-FEB-18');

Aynı şekilde konstraint gerekiyorsa bunu child tablo üzerinden yapabilir siniz.

ALTER TABLE table_log_20180202 ADD CONSTRAINT check_date CHECK (operation_date >= '02-FEB-18' AND operation_date < '03-FEB-18');

Yine partition kısmını dettach-attach edebiliriz.

ALTER TABLE Table_Log DETACH PARTITION Table_Log_20180131;

ALTER TABLE Table_Log ATTACH PARTITION Table_Log_20180131 FOR VALUES FROM ('31-JAN-18') TO ('01-FEB-18');

Özetlemek gerekiyorsa bahsettiğimiz gibi Partition tabloları & Indexleri manuel yaratmamız gerekiyor. Yeni bir partition eklemek için ayrı bir rutin yazmanız yada takviminize eklemeniz gerekiyor.
Ana tablo üzerinde Primary Key ve Unique Key MASTER Tablo üzerinden olmuyor bunu child tablolardan yapmanız gerekli.
Partition tabloları şu şekilde listeyebilir siniz.

SELECT
    nmsp_parent.nspname AS parent_schema,
    parent.relname      AS parent,
    nmsp_child.nspname  AS child_schema,
    child.relname       AS child
FROM pg_inherits
    JOIN pg_class parent         ON pg_inherits.inhparent = parent.oid
    JOIN pg_class child          ON pg_inherits.inhrelid   = child.oid
    JOIN pg_namespace nmsp_parent ON nmsp_parent.oid  = parent.relnamespace
    JOIN pg_namespace nmsp_child    ON nmsp_child.oid   = child.relnamespace
WHERE parent.relname='table_log';

parent_schema | parent | child_schema | child
---------------+-----------+--------------+--------------------
public | table_log | public | table_log_20180131
public | table_log | public | table_log_20180201
public | table_log | public | table_log_20180202
public | table_log | public | table_log_20180203
(4 rows)

postgres=#

ORA-06502 PL/SQL numeric or value error utl_file.put_line()

ORA-06502: PL/SQL: numeric or value error ORA-06512: at line XX


Bu hatayı utl_file.put_line  paketi ile db link kullanarak remote database den aldığım kodun yazımında yaşadım..

SQL> declare
2    l_clob clob;
3    l_tmp long;
4    l_offset number := 1;
5    lFile UTL_FILE.file_type;
6   begin
7     loop
8      select dbms_lob.substr@DB_TESTDB(dbms_metadata.get_ddl@DB_TESTDB('PACKAGE BODY','ILKER','PKG_ADMIN'), 4000, l_offset )
9      into l_tmp
10     from dual@DB_TESTDB;
11
12     exit when l_tmp is null;
13     l_clob := l_clob || l_tmp;
14     l_offset := l_offset + length(l_tmp);
15    end loop;
16   lFile := UTL_FILE.fopen('EXPORT_DIR', 'createscr.sql','w');
17   UTL_FILE.put(lFile, l_clob);
18   UTL_FILE.fclose(lFile);
19 -- dbms_output.put_line( 'l_clob length is ' || length(l_clob) );
20 end;
21 /
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 17

Normal şartlarda ORA-06502: PL/SQL: numeric or value error hatası için farklı düşünebiliriz. Fakat utl_file için bu hata veriliyorsa durum biraz farklılaşıyor.
Bunun sebebi UTL_FILE.PUT_LINE paketinin maximum alabileceği değer 32767 bytes Bknz https://docs.oracle.com/utl_file

Eğer çektiğiniz datanın boyutuna bakarsanız bu değerden büyük olduğunu göreceksiniz.

Bu sorunu ben DBMS_XSLPROCESSOR paketi ve CLOB2FILE procedure kullanarak aştım.

SQL> declare
2     l_clob clob;
3     l_tmp long;
4     l_offset number := 1;
5     lFile UTL_FILE.file_type;
6   begin
7    loop
8      select dbms_lob.substr@DB_TESTDB(dbms_metadata.get_ddl@DB_TESTDB('PACKAGE BODY','ILKER','PKG_ADMIN'), 4000, l_offset )
9      into l_tmp
10     from dual@DB_TESTDB;
11
12    exit when l_tmp is null;
13    l_clob := l_clob || l_tmp;
14    l_offset := l_offset + length(l_tmp);
15   end loop;
16 -- lFile := UTL_FILE.fopen('EXPORT_DIR', 'createscr.sql','w');
17 -- UTL_FILE.put(lFile, l_clob);
18 -- UTL_FILE.fclose(lFile);
19 -- dbms_output.put_line( 'l_clob length is ' || length(l_clob) );
20 DBMS_XSLPROCESSOR.clob2file(l_clob,'EXPORT_DIR','createscr1.sql';
21 end;
22 /

Buna dair farklı bir kaydı support üzerinden de  inceleyebilir siniz. 


ORA-22992: cannot use LOB locators selected from remote tables


Ben bu hatayı remote db üzerinden, DDL scriptini almak istediğimde yaşadım.
Buda Remote db üzerinden CLOB bir datayı alamayacağım anlamına geliyor

SELECT DBMS_METADATA.GET_DDL@DB_TESTDB('TABLE','T','ILKER') FROM DUAL@DB_TESTDB;
ERROR:
ORA-22992: cannot use LOB locators selected from remote tables

no rows selected

SQL>

Workaround olarak substring'e çevirerek bir çözüm sağlayabilir siniz.

Select DBMS_LOB.SUBSTR@DB_TESTDB(DBMS_METADATA.GET_DDL@DB_TESTDB('TABLE','T','ILKER'),4000,1) from dual@DB_TESTDB;

ORA-06553 PLS-564 DB link CLOB Column ERROR


ORA-06553: PLS-564: lob arguments are not permitted in calls to remote server

Bu hatayı clob içeren DDL 'i Veritabanımdan db Link ile remote Veritabanı üzerinden almak isterken yaşadım.

insert into LocalTempTableWithClob1 SELECT DBMS_METADATA.GET_DDL@DB_TESTDB('PACKAGE BODY', 'PKG_ADMIN_DBA', 'ILKER') FROM DUAL@DB_TESTDB;

*ERROR at line 1:ORA-06553: PLS-564: lob arguments are not permitted in calls to remote server

Başka bir örnek:

create table LocalTempTableGetDDL as SELECT DBMS_METADATA.GET_DDL@DB_TESTDB('PACKAGE BODY', 'PKG_ADMIN_DBA', 'ILKER') FROM DUAL@DB_TESTDB;
*
ERROR at line 1:
ORA-06553: PLS-564: lob arguments are not permitted in calls to remote server

DB link ile remote veri tabanı üzerinde yapabileceklerimizin sınırlı. Bazı limitleri var. Bu şekilde bir seferde ancak 4000 bayt alabileceğimiz için workaround olarak bir loop içerisinde tekrar tekrar almayı deneyebilirsiniz.

declare
    l_clob clob;
    l_tmp long;
    l_offset number := 1;
begin
    loop
      select dbms_lob.substr@DB_TESTDB(DBMS_METADATA.GET_DDL@DB_TESTDB('ILKER','PKG_ADMIN_DBA','PACKAGE BODY'), 4000, l_offset )
      into l_tmp
      from dual@DB_TESTDB;
   exit when l_tmp is null;
   l_clob := l_clob || l_tmp;
   l_offset := l_offset + length(l_tmp);
  end loop;
 dbms_output.put_line( 'l_clob length is ' || length(l_clob) );
end;
/


Burada dikkat edilmesi gereken konu tekrar tekrar gidilmesi gerektiği. Her ortam ve DB için uygun olmayabilir. 

Oracle Opatch Conflict ERROR


Merhaba,

Geçtiğimiz gün, son çıkan PSU Jul2017 - patch 26030799 - Oracle Grid Infrastructure Patch Set Update 11.2.0.4.170718 'nı Oracle 2 Node RAC Veritabanıma uygularken (GRID & ORACLE_HOME) aşağıdaki gibi conflic hatası aldım.. Yani başka bir patch ile conflic oldum.

### Patching.sh ./opatch auto Grid Home & DB Home Automaticly ###


Grid Home : /u01/app/11.2.0/grid
DB Home : /u01/app/oracle/product/11.2.0/dbhome_1

Executing /u01/app/11.2.0/grid/perl/bin/perl /u01/app/11.2.0/grid/OPatch/crs/patch11203.pl -patchdir /u01/stage -patchn 26030799 -ocmrf /u01/stage/ocm.rsp -paramfile /u01/app/11.2.0/grid/crs/install/crsconfig_params

This is the main log file: /u01/app/11.2.0/grid/cfgtoollogs/opatchauto2017-08-08_01-48-19.log

This file will show your detected configuration and all the steps that opatchauto attempted to do on your system:
/u01/app/11.2.0/grid/cfgtoollogs/opatchauto2017-08-08_01-48-19.report.log

2017-08-08 01:48:19: Starting Clusterware Patch Setup
Using configuration parameter file: /u01/app/11.2.0/grid/crs/install/crsconfig_params

Unable to determine if /u01/app/oracle/product/11.2.0/dbhome_1 is shared oracle home
Enter 'yes' if this is not a shared home or if the prerequiste actions are performed to patch this shared home (yes/no):yes

Unable to determine if /u01/app/11.2.0/grid is shared oracle home
Enter 'yes' if this is not a shared home or if the prerequiste actions are performed to patch this shared home (yes/no):yes
The opatch Conflict check failed for /u01/app/oracle/product/11.2.0/dbhome_1. The patch /u01/stage/26030799/25869727 is either already applied or conflicting with another patch applied in the home
Conflict check failed for oracle home /u01/app/oracle/product/11.2.0/dbhome_1
Conflict check failed
ERROR: Conflict-Check has failed . Please refer to /u01/app/11.2.0/grid/cfgtoollogs/opatchauto2017-08-08_01-48-19.log for details

opatch auto failed.


Aksiyon olarak Oracle_Home opatch üzerinden ./opatch lsinventory ile ne geldiyse silip psu yu yeniden uyguladım.

[oracle@DB1]/u01/app/oracle/product/11.2.0/dbhome_1/OPatch> ./opatch lsinventory


opatch rollback -id 19285025
opatch rollback -id 22502549
opatch rollback -id 22502456

Local ile çalıştırdım...

opatch rollback -id 19285025 -local -oh /u01/app/oracle/product/11.2.0/dbhome_1

opatch rollback -id 22502549 -local -oh /u01/app/oracle/product/11.2.0/dbhome_1
opatch rollback -id 22502456 -local -oh /u01/app/oracle/product/11.2.0/dbhome_1


En son ne kaldı diye kontrol ediyorum...

[oracle@DB1]/u01/app/oracle/product/11.2.0/dbhome_1/OPatch> ./opatch lsinventory
Oracle Interim Patch Installer version 11.2.0.3.16
Copyright (c) 2017, Oracle Corporation. All rights reserved.


Oracle Home : /u01/app/oracle/product/11.2.0/dbhome_1
Central Inventory : /u01/app/oraInventory
from : /u01/app/oracle/product/11.2.0/dbhome_1/oraInst.loc
OPatch version : 11.2.0.3.16
OUI version : 11.2.0.4.0
Log file location : /u01/app/oracle/product/11.2.0/dbhome_1/cfgtoollogs/opatch/opatch2017-08-08_03-36-20AM_1.log

Lsinventory Output file location : /u01/app/oracle/product/11.2.0/dbhome_1/cfgtoollogs/opatch/lsinv/lsinventory2017-08-08_03-36-20AM.txt

--------------------------------------------------------------------------------
Local Machine Information::
Hostname: DB1
ARU platform id: 226
ARU platform description:: Linux x86-64

Installed Top-level Products (1):

Oracle Database 11g 11.2.0.4.0
There are 1 products installed in this Oracle Home.


There are no Interim patches installed in this Oracle Home.


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

OPatch succeeded.


ORACLE_HOME Opatch altında daha önce uygulanan tüm patch'leri rollback yaptıktan sonra ./opatch auto ile hem GI_HOME hem ORACLE_HOME için yeniden PSU uygulayabildim. 



Ara