19 Ocak 2015 Pazartesi

Oracle 12C In-memory Opsiyonu

Oracle 12.1.0.2 sürümüyle yeni gelen özelliklerden birtanesi In-Memory opsiyonudur.Tablo, partition yada diğer database objelerinin memory'de tutulmasını sağlar. SGA içerisinde data alışılageldik row formatında değil, Column based olarak tutulur. Tek database üzerinde verilerimizin hem row hem de in memory opsiyonu sayesinde column based olarak tutulması, bize OLTP işlemlerinin yanısıra Analitik işlemleri de performanslı biçimde yapma avantajı kazandırır. Oracle Exalytics ürününü piyasaya çıkardığı yıllarda timesten adı verilen in-memory database sayesinde raporlama datasını memory'den çekerek BI alanında performans bakımından büyük bir adım atmıştı. Exalyticsin bir engineered system olması sebebiyle maliyeti çok yüksekti. 12C ile gelen in-memory opsiyonu sayesinde raporlama işlemlerimizde OLTP veritabanımızı kullanırken Performans bakımından büyük kazanımlar elde etmiş oluyoruz.

In-memory opsiyonu kullanırken DB buffer cachede tutulan data değiştirilmez,SGA içerisinde yeni bir pool'a istenilen data columnar formatta tutulacak şekilde depolanır. In-memory opsiyonuyla, memoryde tutulan objelerin tekrar DBbuffer cache load edilmesi gereksizdir. Bu opsiyonla sıkıştırılmış veri içerisinde arama yapılabiliyor. Column format sıkıştırma işlemlerini çok performanslı yapabildiği gibi, bir değer önemli avantajıda; donanımın uyumlu olması halinde SIMD vector proccessing'i kullanmasıdır.
SIMD vector Proccessing (Single Instraction Proccessing Multiple Data Value) : SIMD destekli işlemcilerde 32 bitlik 1 register, 8bitlik 4 register gibi davranır.

In-memory özelliği ile SGA içerinde önceden varolan buffercahce vb memory alanlarında bir değişiklik olmazken,bu özellik için oracle mimarisine dahil edilen ekstra proces, parametre ve memory alanları mevcuttur. INMEMORY_SIZE parametresini 0'dan farklı bir değere set ettiğimiz zaman bu özellik database'imiz için aktif hale gelmekle birlikte bu parametre, SGA içerisinde memory'e alınacak dataların tutulduğu IN-MEMORY COLUMN STORE alanının size'ını da belirlemiş olur. IMCO(in-memory coordinater) backgorund process'i ise memory'de tutulmasını istediğimi dataları SGA'nın ilgili in-memory column store alanına load eder,her iki dakikada memoryde tutulan datanın refresh edilmesini sağlar, bu processe bağlı SMCO(Space Management Coorinater Process) background processi ve workerlar bulunur.
Datanın memory'e alınması instance restart edildiğinde yada ilgili dataya erişildiğinde yapılabilir. Database instance başlatıldığı sırada memory'e alınmış data diskten tekrar okunarak in-memory column alanına yeniden yüklenmesi gerekir. Rac databaselerde birden fazla instance mevcuttur ve dolayısıyla instance sayısı kadar IMcolumn store alanı olacaktır. Bir tabloyu memory de tutmak istediğimiz zaman default olarak NO DUPLICATE opsiyonuyla tablonun datası instance'lardan sadece birtanesinin IMcolumn store alanında tutulmak üzere memory'e alınır. Bu sayede partition'lı bir tablomuzun bir partition'ını instance 1'de tutarken, diğer partition'ını ise instance 2'de depolanacak şekilde memory alanına alabiliriz. Yada DUPLICATE opsiyonuyla tabloyu memory'e aktarırken tüm instancelardaki IMcolumn store alanına aynı datanın yüklenmesini sağlayabiliriz.

Hangi Datanın memroy'e daha önce alınacağını Priorty özelliğini set ederek belirleyebiliriz. Bir objeyi memory'e almak için ilk önce INMEMORY_SIZE parametresini set ederek bu opsiyonu aktif hale getiriyoruz. Statik bir parametre olduğundan restart ettikten sonra bu değişiklik aktif hale gelecektir. Bu tanımlamayı yaparken SGA boyutuna dikkat etmemiz gerekiyor.
ALTER SYSTEM SET INMEMORY_SIZE=200M SCOPE=SPFILE


Yukarıda gördüğümüz gibi, bu opsiyonu aktif hale getirdikten sonra databasei açtığımızda SGA altında artık In-Memory Area adı altında bir alanımız da bulunuyor.Şu anda bu bellek bölgesinde herhangi bir data store edilmemektedir. Instance startup'ında bu alana istediğimiz obje datasının load edilmesi için PRIORITY özelliğini set etmeliyiz demiştik. PRIORITY seçeneklerine bakacak olursak;
NONE: Hiçbir öncelik tanımlamazsak full scan yapan bir sorgu gelmeden memory'ye alınmayacaktır.
LOW:instance başlatıldığı anda memory'ye yüklenecektir.
MEDIUM:instance başlatıldığı anda memory'ye yüklenecektir.
HIGH:instance başlatıldığı anda memory'ye yüklenecektir.
CRITICAL:instance başlatıldığı anda memory'ye yüklenecektir.  İnstance başlangıcında memorye alınma önceliği tahmin edileceği gibi CRITICAL, HIGH, MEDIUM, LOW şeklindedir

Inmemory opsiyonunu aktif hale getirdikten sonra bir tabloyu nasıl inmemory'e alabileceğimize bakalım. v$im_segments'den memory'deki objeleri sorgulayabiliriz.
SQL> select owner,segment_name,inmemory_size,bytes,bytes_not_populated,populate_status from v$im_segments;
no rows selected

SQL> alter table oe.customers inmemory priority critical;
Table altered.
SQL> select owner,segment_name,inmemory_size,bytes,populate_status from v$im_segments;

OWNER    SEGMENT_NAME   INMEMORY_SIZE BYTES      POPULATE_STATUS
------------
OE                  CUSTOMERS 1179648   131072        COMPLETED
Priorty özelliğini none olarak tanımladığımızda ise tabloya full table scan yapan bir sorgu geldikten sonra tablo memoryye alınır..Burda instance restart edildiği zaman memory sıfırlanacak, tekrar bir sorgu gelemeyene kadar oe.customers tablosu memorye load edilmeyecektir.
SQL> alter table oe.customers inmemory priority none;
Table altered.
SQL> select owner,segment_name,inmemory_size,bytes,bytes_not_populated,populate_status from v$im_segments;
no rows selected

SQL> select * from oe.customers;

SQL> select owner,segment_name,inmemory_size,bytes,populate_status from v$im_segments;

OWNER    SEGMENT_NAME   INMEMORY_SIZE BYTES      POPULATE_STATUS
------------
OE               CUSTOMERS 1179648   131072        COMPLETED

Memoryde tutulan bir objenin priority'sinin ne olduğunu öğrenmek için ise aşağıdaki sorguyu kullanabiliriz.

SQL> SELECT OWNER, SEGMENT_NAME, INMEMORY_PRIORITY, INMEMORY_COMPRESSION FROM V$IM_SEGMENTS;

Bir objenin artık memory'de tutulmasını istemiyorsak  NO INMEMORY sql'ini kullanabiliriz.

SQL> alter table oe.customers  NO INMEMORY;

Memory'de tutulacak datayı table olarak belirleyebildiğimiz gibi,bu seçimi kolon bazında da yapabiliriz. İstediğimiz tablonun sadece tutulmasını istediğimiz kolonları için in-memory özelliğini aktif hale getirebiliriz.Önce ilgili tabloyu memory'ye almamız gerekiyor.

SQL> alter table oe.customers INMEMORY;

 SQL> alter table oe.customers
(CUST_ADDRESS,PHONE_NUMBERS,NLS_LANGUAGE,NLS_TERRITORY,CREDIT_LIMIT,CUST_EMAIL)
 INMEMORY MEMCOMPRESS FOR CAPACITY HIGH (CUSTOMER_ID,CUST_FIRST_NAME,CUST_LAST_NAME)
 INMEMORY MEMCOMPRESS FOR QUERY HIGH (ACCOUNT_MGR_ID,CUST_GEO_LOCATION,DATE_OF_BIRTH)
 NO INMEMORY (MARITAL_STATUS,GENDER,INCOME_LEVEL);

Memory'ye aldığımız tablonun kolonlarını aşağıdaki sorgu ile v$im_column_level'dan sorguladığımız zaman aşağıdaki sonucu elde ediyoruz.

Compression metodlarından bahsedecek olursak;
NO MEMCOMPRESS: Memoryde tutulacak data üzerinde herhangi bir sıkıştırma uygulanmaz
MEMCOMPRESS FOR DML: Datayı DML operasyonları için optimize edecek şekilde sıkıştırır. En az sıkıştırma oranı bu metodda uygulanır.
MEMCOMPRESS FOR QUERY LOW: En iyi query performasını elde edecek şekilde sıkıştırma yapar.Datayı MEMCOPRESS FOR DML'den daha fazla sıkıştırır.
MEMCOMPRESS FOR QUERY HIGH: QUERY LOW'dan daha yüksek performans sağlar. Datayı query lowdan fazla, memcompress for capacity low metodundan daha az bir sıkıştırma oranı ile sıkıştırır.
MEMCOMPRESS FOR CAPACITY LOW: İyi bir query performansına sahip olmasının yanında yüksek bir sıkıştırma oranına da sahiptir. Memcompress For query high'dan fazla, memcompress for capacity high'dan daha az sıkıştırma yapar.
MEMCOMPRESS FOR CAPACITY HIGH: Bu metodda ise en yüksek oranda data sıkıştırması yapılır.

Aşağıdaki sorgu yardımıyla memorydeki tablonun sıkıştırma methodu ve sıkıştırma oranı hakkında bilgi edinebiliriz..

SQL> select segment_name, bytes Disk, inmemory_size, populate_status, inmemory_compression COMPRESSION,  bytes / inmemory_size comp_ratio from v$im_segments;

inmemory_clause_default parametresi IN MEMORY sql'ini kullandığımız zaman default olarak hangi opsiyonlarla bu özelliği aktif hale getireceğimizi belirler. Yani bu parametreyi aşağıdaki gibi set ettiğimizi düşünürsek her bir IN MEMORY cümlesinde default olarak sıkıştırma methodunu query high olarak belirleyecektir..

SQL> alter system set inmemory_clause_default="INMEMORY MEMCOMPRESS FOR QUERY HIGH" ;


12C In-memory opsiyonunun karşılaştırmalı performans incelemesi için ise Gökhan Atıl'ın 12C In-Memory sunumunu bu linkten ineceleyebilirsiniz..


Kaynaklar:
http://docs.oracle.com/database/121/ADMIN/memory.htm#ADMIN00207
Gökhan ATIL 12C IN-MEMORY Sunumu (Troug Ankara Etkinliği - http://www.slideshare.net/gokhanatil/oracle-12c-database-in-memory)
http://oracle-base.com/articles/12c/in-memory-column-store-12cr1.php


12 Ocak 2015 Pazartesi

Oracle 12C Yeni CDB ve PDB Oluşturma

Oracle 12C'de kurulum esnasında bir CDB ve PDB oluşturabildiğimiz gibi kurulumdan sonra da birden çok yöntemle Container Database ve Pluggable Database oluşturabiliriz.

1) Kurulum Esnasında OUI ile;
Bildiğimiz 11gR2 OUI'ından farklı olarak aşağıdaki ekranlar eklenmiş ve burdaki seçenekler yardımıyla multitenant özelliğini kullanıp kullanmayacağımızı belirleyebiliyoruz..Kuruluma başladığımız sırada Create and Configure Database seçimiyle devam ettiysek, database oluşturma adımında bizden bir SID istiyor ve bunu Container Database (CDB) olarak kullanıp kullanmayacağımızı soruyor. Eğer CDB olarak oluşturacaksak, altında bir Pluggable database de oluşturuyoruz..



2) DBCA ile CDB yaratılması
Aynı şekilde komut satırından dbca komutu ile database configuration assistant'ı çalıştırdığımız zamanda OUI'da yarattığımız şekilde CDB ve PDB oluşturuyoruz. Ancak dbca aracı bize database hakkında daha fazla seçenek sunuyor. DBCA'yı çalıştırdıktan sonra create database seçeneğiyle ilerlediğimizde aşağıdaki ekranda database'in özelliklerini belirliyoruz.CDB yada non-CDB bir database oluşturabiliyoruz.


Bunun haricinde advance modu seçtiğimiz zaman ise Oluşturacağımız container Database içinde birden fazla Pluggable database oluşturabiliyoruz.Yine burdan istersek boş bir container Database yaratma seçeneği ile devam edebiliyoruz..


3) CDB'nin Manuel Yaratılması
Oracle tarafından önerilen, bu işlemin DBCA ile  yapılmasıdır. Ancak manuel olarak sqlplus yardımı ile CDB oluşturmak mümkündür..Sqlplusa bağlanıp nomount adımda database'i başlattıktan sonra CREATE DATABASE keywordü ile CDB'yi yaratıyoruz. Burda system,sysaux,temp ve undo tablespaceleri için Datafileları tanımlıyoruz.Daha sonra karakter seti ve log dosyaları set ediliyor.Bunlar zaten şimdiye kadar manuel DB yaratırken kullandığımız parametrelerdi. Non-CDB veritabanı yaratırken yaptığımız işlemlerden farkı ise;
ENABLE PLUGGABLE DATABASE cümlesiyle yaratıığımız database'in bir container DB olduğunu söylüyor ve multitenant özelliğini kazandırıyoruz..

SET VERIFY OFF
connect "SYS"/"&&sysPassword" as SYSDBA
set echo on
spool /u01/app/oracle/admin/cdb1/scripts/CreateDB.log append
startup nomount pfile="/u01/app/oracle/admin/cdb1/scripts/init.ora";
CREATE DATABASE "cdb1"
MAXINSTANCES 8
MAXLOGHISTORY 1
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 1024
DATAFILE '/u01/app/oracle/oradata/cdb1/system01.dbf' SIZE 700M REUSE
  AUTOEXTEND ON NEXT  10240K MAXSIZE UNLIMITED
  EXTENT MANAGEMENT LOCAL
SYSAUX DATAFILE '/u01/app/oracle/oradata/cdb1/sysaux01.dbf' SIZE 550M REUSE
  AUTOEXTEND ON NEXT  10240K MAXSIZE UNLIMITED
SMALLFILE DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE '/u01/app/oracle/oradata/cdb1/temp01.dbf' SIZE 20M REUSE
  AUTOEXTEND ON NEXT  640K MAXSIZE UNLIMITED
SMALLFILE UNDO TABLESPACE "UNDOTBS1" DATAFILE  '/u01/app/oracle/oradata/cdb1/undotbs01.dbf' SIZE 200M REUSE
  AUTOEXTEND ON NEXT  5120K MAXSIZE UNLIMITED
CHARACTER SET AL32UTF8
NATIONAL CHARACTER SET AL16UTF16
LOGFILE GROUP 1 ('/u01/app/oracle/oradata/cdb1/redo01.log') SIZE 50M,
GROUP 2 ('/u01/app/oracle/oradata/cdb1/redo02.log') SIZE 50M,
GROUP 3 ('/u01/app/oracle/oradata/cdb1/redo03.log') SIZE 50M
USER SYS IDENTIFIED BY "&&sysPassword" USER SYSTEM IDENTIFIED BY "&&systemPassword"
enable pluggable database
seed file_name_convert=('/u01/app/oracle/oradata/cdb1/system01.dbf','/u01/app/oracle/oradata/cdb1/pdbseed/system01.dbf',
                        '/u01/app/oracle/oradata/cdb1/sysaux01.dbf','/u01/app/oracle/oradata/cdb1/pdbseed/sysaux01.dbf',
                        '/u01/app/oracle/oradata/cdb1/temp01.dbf','/u01/app/oracle/oradata/cdb1/pdbseed/temp01.dbf',
                        '/u01/app/oracle/oradata/cdb1/undotbs01.dbf','/u01/app/oracle/oradata/cdb1/pdbseed/undotbs01.dbf');
spool off

4)DBCA ile PDB oluşturulması
DBCA'yı başlattıktan sonra Seçeneklerden Manage Pluggable database seçeneği ile devam ediyoruz.Aşağıdaki ekran karşımıza çıkıyor.Burda Pluggable database ile alakalı, create, delete, unplug ve configure işlemlerimizi gerçekleştirebiliyoruz.Create PDB seçeneğini seçtikten sonraki ekranda Container Database'lerin bir listesi geliyor ve hangi CDB için PDB yaratacağımızı seçiyoruz. Daha sonra bize iki seçenek sunuyor ya unplug edilmiş bir PDB'yi plug ediyoruz, yada yeni bir PDB oluşturuyoruz.


PDB'nin manuel olarak yaratılması ise create pluggable database cümlesi ile olur..

Yukarıdaki şemada bir PDB'nin yaratılma yöntemleri gözlemlenebilir.Bir PDB yaratırken kopyalama yada plugin yöntemlerinden bir tanesi kullanılır. Kopyalama yönteminde CDB içerisindeki SEED'den dosyalar kopyalanır hazır bir templateden PDB oluşturulur. Yada Database Clone işlemlerinde olduğu gibi uzak bir sunucudan yada lokalde bulunan bir CDB yahut non-CDB'nin klonlanmasıyla PDB oluşturulabilir. Plugging in yönteminde ise başka bir ortamdan unplug edilen bir PDB plug edilebilir yada Non-CDB bir database PDB olarak plug edilir..

PDB$SEED'den Pluggable Database oluşturulması; 
Mimari ile ilgili yazımda (bu linkten ulaşabilirsiniz ) CDB içerisindeki root ve seed kavramlarından bahsederken PDB$SEED için yeni pluggable database'ler oluştururken bu templatedendosyalar kopyalanır demiştik. Yukarıda CDB'nin manuel yaratılması scriptinde seed file'lar içinde lokasyon belirtiliyor dikkat edilirse. Bu sayede rootun yanında PDB$SEED template'i de oluşturulmuş oluyor. CREATE PLUGGABLE DATABASE cümlesiyle oluşturduğumuz PDB, PDB$SEED' deki file'ların kopyalanması yani template yardımıyla oluşturulur.


CREATE PLUGGABLE DATABASE pdbnew ADMIN USER pdb_vy IDENTIFIED BY password FILE_NAME_CONVERT=('/u01/app/oracle/oradata/cdbvy/pdbseed/','/u01/app/oracle/oradata/cdbvy/pdbnew/');

Pluggable databaseleri aşağıdaki gibi sorguladığımızda yeni oluşturduğumuz PDB'yi göreceğiz

SELECT pdb_name, status
FROM   dba_pdbs
ORDER BY pdb_name;

PDB_NAME      STATUS
-------------------- -------------
PDB$SEED      NORMAL
PDB1       NORMAL
PDBNEW       NEW

Status NEW olarak geliyor, PDByi açtığımız zaman Status normal olarak değişecektir. PDB'yi read write mode'a çekmek için;

ALTER PLUGGABLE DATABASE pdbnew OPEN READ WRITE;

Bir PDB yada Non-CDB'nin Clone'u yardımıyla Pluggable Database oluşturulması
CREATE PLUGGABLE DATABASE pdb1new from pdbsource;
cümlesiyle bir PDB'den yada Remote non-CDB'den Pluggable database yaratabiliriz. Burda da  mantık olarak source dosyaların yeni bir lokasyona kopyalanması ile PDB yaratılıyor.

Plugging-Unplugging yöntemiyle bir PDB oluşturulması
PDB unplug durumdayken kendi datafilelarının yanında bir de XML metadata dosyası içerir.Bu XML dosyası yardımıyla yeni PDB'yi oluşturuyoruz..
PDB'yi manuel olarak unplug etmek için aşağıdaki komut kullanılır.

ALTER PLUGGABLE DATABASE pdbnew CLOSE;
ALTER PLUGGABLE DATABASE pdbnew UNPLUG INTO '/u01/app/oracle/oradata/cdbvy/pdbnew/pdbnew.xml';

Aşağıdaki komutla PDB'yi unplug edilmiş PDB'den oluşturuyoruz..

CREATE PLUGGABLE DATABASE pdbnew2 USING '/u01/app/oracle/oradata/cdbvy/pdbnew/pdbnew.xml'  FILE_NAME_CONVERT=('/u01/app/oracle/oradata/cdbvy/pdbnew/','/u01/app/oracle/oradata/cdbvy/pdbnew2/') ;


Non-CDB'den bir PDB oluşturulması; 
12c üzerine veritabanımızı multinenant özelliklerini kullanmadan oluşturduysak ve sonradan Multinenant yapısına geçmeye karar verdiysek bizim için en uygun seçenek bu olacaktır.
Var olan non-CDB database üzerinde DBMS_PDB.DESCRIBE fonksiyonunu çalıştırıyoruz ve bize bir XML metadata dosyası yaratıyor bu database ile ilgili. Yukarıdaki gibi bu xml dosyasındanPDB'yi oluşturuyoruz.
Başka bir yöntem olarak datapump'ı kullanarak datalarımızı oluşturduğumuz yeni bir PDB içerisine aktarıyoruz.
Veya Goldengate replikasyonu kullanarak bu işlemi yapabiliyoruz..
Bu yöntemlerin dışında PDB oluşturmak- taşımak için SQLdeveloper ve EM 12c'yi de kullanabiliriz.


Pluggable Database'lerin başlatılması;
12C'de Container database'i kapattığımız zaman öncesinde tüm PDB'ler kapatılıyor..Ancak Startup komutunu verdiğimiz zaman sadece container DB açılıyor. PDBler'in açılmasını ise aşağıdaki gibi bir trigger yazarak sağlayabiliriz..


CREATE OR REPLACE TRIGGER open_pdbs 
  AFTER STARTUP ON DATABASE 
BEGIN 
   EXECUTE IMMEDIATE 'ALTER PLUGGABLE DATABASE ALL OPEN'; 
END open_pdbs;
/

Kaynaklar:
Oracle Database Concepts 12c Release 1 (12.1)
http://oracle-base.com/articles/12c/multitenant-startup-and-shutdown-cdb-and-pdb-12cr1.php

7 Ocak 2015 Çarşamba

Oracle 12c Multitenant Mimarisi

Oracle veritabanı 12c sürümüyle gelen en önemli yeniliklerden birtanesi Multitenant mimarisidir.. Basitçe, container adı verilen bir instance'ın pluggable birden çok veritabanını barındırması mantığına dayanıyor. Multitenant container database sıfır,bir veya daha çok user created pluggable database'i barındırabilir. PDB(pluggable database) ise schemaların, schema objelerinin ve nonschema objelerin portable bir koleksiyonu olarak adlandırılabilir.

12c sürümünde kullanabileceğimiz 3 farklı konfigürasyon tipi vardır;

  • Multitenant özelliklerinden faydalanmak istemiyorsak eski mimari ile alıştığımız 11g database özellikleri ile databaseimizi kurup yönetebiliriz.
  • İleride bu mimariye geçiş yapma ihtilamine karşılık 12c kurulumu esnasında 1 CDB ve 1PDB ile kurulumu gerçekleştirip, Multitenant architecture in single tenant konfigürasyonunu kullanabiliriz..Bu opsiyon için Multitenant lisans ücreti ödemiyoruz.
  • Son olarak ise multiple PDB per CDB olarak adlandırılan konfigürasyonla Multitenant özelliğini tam olarak kullanabiliriz,bu konfigürasyon için Multitenant lisansının olması gerekiyor..


CDB içerisindeki Container, PDB yada root container(root olarak da adlandırılır) olabilir..Container; schema, obje ve CDB içerisindeki ilişkisel yapılardan oluşur. CDB içerisindeki her container unique bir ID ve isme sahiptir..Container aynı zamanda tenant olarak da adlandırılır. Her CDB aşağıdakilere sahiptir;
  • Root; oracle-supplied metadata ve common userları tutar..Root container CDB$ROOT olarak adlandırılır..Root user datasını tutmaz.
  • Seed PDB; yeni PDB yaratmak için kullanılabilen system-supplied templatedir. PDB$SEED olarak adlandırılır. Seed PDBye obje eklenemez ve var olan objeleri değiştirilemez..
  • Zero or more user-created PDB; Pluggable dblerdir. CDB oluşturulduğunda otomatik olarak oluşturulmaz, kendi gereksinimimize göre PDB'ler yaratabiliriz. PDBler application datasını tutmak, datayı farklı bir CDB'ye taşımak amacıyla kullanılabilir..
Aşağıdaki şemada gördüğümüz CDB altında root, seed ve iki adet PDB bulunmaktadır. Her PDB'i kendi uygulamasına hizmet vermektedir. Her PDB'nin kendi administrator'ı bulunmaktadır. CDB administrator user'ı herbir PDB'yi yönetebilir..Fiziksel seviyede bakıldığı zaman CDB önceden var olan non-cdb databaseler gibi bir instance ve databasefile'lara sahiptir..Multitenant yapıda Background processleri, shared memory ve Oracle Metadata, redolog,controlfile ve undo tablespaceleri ortaktır. PDBlerde ise application data ve tablespaceleri,Local user ve roller ve local metada tutulur.Gerekli görüldüğü takdirde PDB bazında temp tablespaceler tanımlanabilir.

The Root

Multitenant Mimarinin Sağladıkları 
  • Cost Reduction : Kaynakların PDBler arasında paylaşımlı kullanılması maliyeti azaltır.daha az fiziksel sunucu ve daha az yönetim maliyeti ortaya çıkar..
  • Easier and More rapid movement of data : PDB'yi unplug edip başka bir CDB altına plug ettiğimiz zaman datanın hızlı bir şekilde taşınmasını sağlamış oluruz. Plıg/ungplug tekniği transportable tablespace mantığına oldukça yakındır..
  • Easier management and monitoring of the physical db : Non-cdb databaseler'de birçok fiziksel database'in yönetimi ve monitorü zorluğunu ortadan kaldırır. Fiziksel dosyaların ortak kullanımı sayesinde yönetimsel olarak daha az enerji harcanmasını sağlar..
  • Ease of performance tuning : Tek database'in performans metriclerinin toplanacağı için performans tuning işlemlerini kolaylaştırır.
  • Patches and Upgrade : CDB'ye uygulanacak patchler var olan tüm PDB'leri etkileyecektir.

Naming For PDB
Unique bir adı olmalıdır.PDB kendisiyle aynı isme ait servicename'e sahip olacaktır.PDB'ler ayrı namespace'lere sahiptir. Ayrı PDB'lerde aynı isme sahip şemalar bulunabilir. Objeler ise PDB içinde unique name'e sahip olmalıdır.

Data Dictionary Architecture
CDB içerisindeki her containerın data dictionarysi ayrıdır.Mesela DBA_OBJECTS viewine bir select attığımız zaman farklı PDB'ler için farklı sonuçlar döndürebilir.Dictionarylerin farklı olması sayesinde Her PDB'nin birbirinden ve roottan bağımsız yönetilmesi sağlanır.

Yeni yaratılmış henüz data içermeyen bir non-CDB databasede data dictionary sadece sistem metadatasını içerir. Örneğin  TAB$ tablosu şu an sadece oracle supplied table'ları içerir.Aşağıdaki grafikte kırmızı çizgiler bu sistem kayıtlarını göstermektedir.

Non-CDB bir database oluşturduktan sonra user kendi objelerini yaratmaya başladığı zaman, oracle-supplied kayıtların yanında user-created objeler içinde dictionary'de kayıtlar tutulmaya başlanacaktır.


Şimdi CDB bir databasede durumun nasıl olduğuna bakarsak; Data dictionary metadata root ve PDB'ler arasında ayrılmıştır.User data PDB'de tutulur. PDB'nin usercreated objelerin metadatası tutulurken, oracle-supplied objeler için root'un dictionarysini işaret eder..

Bu dictionary mimarisi temelde iki önemli avantaj sağlar..
  • Duplication'ı azaltır ; Örneğin DBMS_ADVISOR PL/SQL paketinin her PDB için tutulmasına gerek kalmaz.sadece CDB$ROOT'ta tutulur ve böylece diskten tasarruf sağlanır..
  • Database upgradeini kolaylaştırır ; Yeni sürümlerde meydana gelen değişiklikleri her PDB'ye ayrı ayrı uygulama zahmetinden kurtarır bizi..

CDB'de servis yaratılması
Bir PDB yarattığımız zaman database otomatik olarak CDB içerisinde bir servis yaratır ve başlatır.PDB ile aynı isme sahip olan bu servis defaultdur ve drop edilemez.Bu PDB için ayrıca servisler de yaratabiliriz.Servis yaratma işlemi non-CDBlerdeki ile aynı şekilde yapılmaktadır..


CDB administrator CBD altındaki herhangi bir container'a bağlanabilir.Containerlar arasında geçiş yapmak için ise aşağıdaki komut kullanılır.
ALTER SESSION SET CONTAINER = ContainerName;

SQL plus ile databaseimize bağlandığımız zaman default olarak roota bağlanıyor..

SQL> SHOW CON_NAME

CON_NAME
------------------------------
CDB$ROOT

Servisleri sorgulamak için;
SQL> SELECT NAME, PDB FROM V$SERVICES
ORDER BY PDB, NAME;    

NAME                  PDB
---------------------------------------------------------------- ------------------------------
SYS$BACKGROUND CDB$ROOT
SYS$USERS                  CDB$ROOT
cdb1                  CDB$ROOT
cdb1XDB                   CDB$ROOT
pdborcl                          PDBORCL



Şuan CDB üzerindeki containerları görmek için aşağıdaki sorguyu kullanabiliriz.

SQL> SELECT NAME, CON_ID, DBID, CON_UID, GUID FROM V$CONTAINERS ORDER BY CON_ID;

NAME        CON_ID  DBID    CON_UID    GUID
--------            ----------    ----------        ----------     --------------------------------
CDB$ROOT  1         841923413            1   FD9AC20F64D344D7E043B6A9E80A2F2F
PDB$SEED  2        1497111388 1497111388   0BE96D62907A1C0EE0538338A8C04659
PDBORCL  3        2980990456 2980990456   0BE9A9F319561EE4E0538338A8C09583



CDB'de Common Ve Local Userlar
CDB üzerinde yaratılan common userlar root dahil tüm PDB'lere bağlanabilir ve işlemler yapabilir.Oracle-supplied yada user-created common userlar vardır. Örneğin SYS and SYSTEM oracle-supplied common userlardır..User created common userlar C## veya c## ile başlayan isimlere sahip olmalıdır.Aşağıdaki şemada hrpdb ve salespdb pluggable databaseleri bulunmaktadır, SYS ve c##dba common userlardır.hr ve rep userları ise iki PDB'de de local user olarak bulunmaktadırlar..


  • Common user root dahil create session privilegine sahip olduğu tüm containerlara login olabilir. Common user her container için aynı haklara sahip olmak zorunda değildir. Örneğin hrpdb ve roota bağlanabilirken, salespdb için create session hakkı vermeyebiliriz..
  • Unique ve c## yada C## ile başlayan bir isme sahip olmalıdır. Root içinde bulunur fakat tüm PDBlere aynı kimlikle bağlanır..
  • Common user birden çok PDBye bağlanma hakkına sahip ise o herbir c#dba şeması farklı objeler içerebilir.
Local User ; yalnızca yaratıldığı  PDB için operasyonları gerçekleştirebilecek userdır.
  • PDB altında kendi şemasına sahiptir.Başka bir PDB yada roota login olamaz.
  • Local user rootda yaratılamaz.Yaratıldığı PDB içerisinde unique bir ismi olmalıdır.
  • Common user  altındaki objelere izinlerine bağlı olarak erişebilir.Örneğin c##dba kullanıcısı kendi şemasında ve hrpdb üzerinde bir tablo yaratırsa, gerekli izinler verildiğinde hr kullanıcısı bu tabloya erişebilir.
Common  ve Local Roller


Common Roles oracle-supplied yada user created roller olabilir. DBA ve Public gibi oracle-supplied rollerin hepsi common roldür..User created common roller ,common userda olduğu gibi c## yada C## ile başlamak zorundadır. Common role yaratabilmek için common user create role yetkisine sahip olmalıdır ve SET CONTAINER hakkında sahip olmalıdır.. CREATE ROLE statementında CONTAINER=ALL olarak set edilir ve common role yaratılmış olur.
Local Roller ise yaratıldıkları PDB içerisinde geçerlidirler.Yine local userlarda olduğu gibi aynı isme sahip roller farklı PDBler altında yaratılabilir..

Grant işlemleri ise non-CDBlerde olduğu gibi yapılır. Aradaki temel fark ise; local ve common durumudur..Localde bir yetkilendirme yapılacaksa CONTAINER=CURRENT, common bir yetkilendirme işlemi yapılacaksa CONTAINER=ALL opsiyonuyla yapılır.


CDB'de Database Dosyları
Fiziksel olarak bakıldığı zaman, her pluggable database kendi tablespace ve data dosyalarına sahiptir.
Redolog files,Undo tablespace ve control file ise ortaktır..Default olarak CDB içerisinde temp file bulunur ve PDB'ler bunu kullanır. Ancak ihtiyac durumunda local bir temp file yaratılarak ilgili PDB'nin onu kullanması sağlanılabilir.Her PDB kendi SYSTEM ve SYSAUX tablespaceine sahiptir.



Kaynaklar:
Oracle Database Concepts, 12c Release 1 (12.1)
TROUG-LOG Oracle 12c Veritabanının Yeni Özellikleri / Zekeriya Beşiroğlu
https://blogs.oracle.com/Multitenant/entry/single_tenant_configuration