SVN Repository i Başka Sunucuya Taşıma

Merhabalar,

Bu yazımda SVN sunucumuzda bulunan repository i başka bir sunucuya nasıl aktaracağımdan bahsedeceğim. Aslında burda yapacağımız iş basit olarak yedek alma ve aldığımız yedeği başka sunucuda geri yükleme işidir.

  1. Repository inizin yedeğini alın.
  2. Yedek alma işlemini, svn in komutlarından “svnadmin” i kullanarak yapıyoruz. Aşağıdaki komutu kullanarak yedeğinizi alabilirsiniz.

    svnadmin dump /path/to/repository > repo_name.svn_dump
    

    Bu komut repository de bulunan tüm revizyonların da yedeğini alacaktır.

  3. Taşıyacağınız sunucuda aynı isimde bir repository oluşturun.
  4. Not: İlk önce taşıyacağınız sunucuya svn kurmanız gerekmektedir. Kurulum için buraya bakabilirsiniz.
    Aşağıdaki komutu çalıştırarak yeni bir repository oluşturabilirsiniz.

    svnadmin create /path/to/repository
    
  5. Almış olduğunuz yedeği Yeni sunucudaki boş repository e geri yükleyin.
  6. Almış olduğumuz yedeği yeni sunucuya taşıyoruz ve aşağıdaki komutu çalıştırıyoruz.

    svnadmin load /path/to/repository < repo_name.svn_dump
    

Artık repository miz yeni sunucuda aynı özelliklerle ve içeriklerle çalışmaktadır.

Oracle Enterprise Linux e SVN Sunucu Kurulumu

Merhabalar,

Bu yazımda Oracle Enterprise Linux e SubVersioN (SVN) kurulumunu anlatacağım. SVN, bir grup insanın aynı proje üzerinde ortak çalışmasını sağlayan ve geliştirdikleri kodları ortak bir makinede tutarak birbirleriyle çakışmasını önleyen, kodların başka kullanıcılar tarafından ezilmesini önleyen ve geçmişe dönük olarak kodları tutabilen bir uygulamadır.
Şimdi kuruluma başlayabiliriz:

  • RHEL tabanlı bir işletim sisteminde öncelikle SVN için gerekli olan paketleri kurun.
  • # yum install httpd mod_dav_svn subversion
    
  • SVN repository oluşturmak için aşağıdaki komutları çalıştırıyoruz:
    # mkdir /var/www/svn/
    # cd /var/www/svn/
    # svnadmin create testRepo
    
  • Bu repository i apache kullanıcısına atıyoruz.
  • # chown -R apache:apache testRepo
    
  • SVN konfigurasyon dosyasında bazı tanımlamalar yapmamız gerekiyor.
    /etc/httpd/conf.d/subversion.conf dosyasına aşağıdaki bilgileri girin.
  • # vi /etc/httpd/conf.d/subversion.conf
    
       DAV svn
       SVNParentPath /var/www/svn  
       AuthType Basic
       AuthName "Subversion repositories"
       AuthUserFile /etc/httpd/conf.d/svn.users 
       AuthzSVNAccessFile /var/www/svn/testRepo/conf/authz 
       Require valid-user
    
    

    Yukarıdaki dosyada bulunan,
    SVNParentPath parametresi svn repository lerinin kurulacağı klasörü gösteriyor.
    AuthUserFile parametresi ise svn repository sine erişecek olan kullanıcıların kayıt edileceği dosyayı gösteriyor.
    AuthzSVNAccessFile dosyası ise kayıtlı kullanıcıların repository olan yetkilendirilmesini yapıyor.

  • Repository erişecek kullanıcıları aşağıdaki kod ile oluşturuyoruz.
    Eğer parola dosyası yoksa “htpasswd -cm” parametresiyle çalıştırıyoruz.
  • # htpasswd -cm /etc/httpd/conf.d/svn.users oracle
    New password:
    Re-type new password:
    Adding password for user oracle
    
  • Eğer mevcut kullanıcıyı güncellemek istiyorsak ya da yeni kullanıcı ekleyeceksek “htpasswd -m” parametresiyle çalıştırıyoruz.
  • htpasswd -m /etc/httpd/conf.d/svn.users oracle2
    New password:
    Re-type new password:
    Adding password for user oracle2
    
  • Konfigurasyon dosyasında belirttiğimiz kullanıcı listesi dosyasını sorguladığımızda eklediğimiz kullanıcıları görebiliriz.
  • # cat /etc/httpd/conf.d/svn.users
    oracle:$apr1$9t19J…$hCF2GJTlizZfnPjKyk9rk/
    
  • Repository erişecek kullanıcıların yetkilendirilmesi için aşağıdaki kodu çalıştırıyoruz:
  • # vi /var/www/svn/testRepo/conf/authz
    ## grup oluşturmak için
    ## group_adi = kullanici_adi
    [groups]
    developer = oracle
    other = onur.cinar
    
    ##repository ye tanımlı kullanıcılara yetki vermek için
    ## [repository_adi/ repository klasörü]
    ## kullanıcı ya da group adı = (r,rw) yetkilerinden biri
    ## r = read, rw = read – write
    
    [/]
    @other = r
    @developer = rw
    
  • Httpd servisini restart edip, başlangıçta çalışması için chkconfig e yazıyoruz.
  • # /etc/init.d/httpd restart
    # chkconfig httpd on
    

SVN sunucumuz hazırdır. Kendi locallerinizde olan SVN clientlarla sunucuya bağlanabilirsiniz.

Linux sunucularda otomatik olarak Huge Page Değeri hesaplamak

Merhabalar,
Büyük SGA e sahip olan veritabanlarımızda huge page ayarı yapmak sanal bellek yönetimi konusunda bize çok büyük kolaylık sağlar. Huge page ayarlamadan önce veritabanımızda Automatic Memory Management (AMM) ayarının yapılmamış olması gerekiyor. Çünkü AMM ve Huge Page Linux sunucularda uyumlu çalışmamaktadır. Onun yerine Huge Page kullanmak istediğiniz sunucularda, Automatic Shared Memory Management ve Automatic PGA Management yapmanız gerekecektir. Diğer önemli nokta ise bu scripti çalıştırmadan önce veritabanınızın çalışır halde olması gerekmektedir.
İlk önce sunucumuzdaki “memlock” değerlerini RAM miktarına göre ayarlamamız gerekmektedir. Örneğin 64 GB RAM imiz varsa, bu değeri KB olarak hesaplayıp, bu değerden küçük bir değer vermemiz gerekecektir. Bu değeri de “/etc/security/limits.conf” dosyasına yazmamız gerekiyor.

vi /etc/security/limits.conf

* soft memlock 60397977
* hard memlock 60397977

Bu ayarı yaptıktan sonra scriptimizi çalıştırabiliriz.
Aşağıdaki scripti veritabanı sunucumuzda oluşturup, çalışma yetkisi verelim.

Scripti buradan indirebilirsiniz.
hugepages.sh

$ chmod +x hugepages_settings.sh
$ ./hugepages_settings.sh
Recommended setting: vm.nr_hugepages = 1496

Gördüğünüz üzere script otomatik olarak bize huge page değerini vermektedir.
Peki buradaki 1496 değerini ne yapacağız?
“/etc/sysctl.conf” dosyasını root kullanıcısıyla açıp uygun bir yere aşağıdaki satırı yazmamız gerekiyor.

....
vm.nr_hugepages = 1496
...

Bu eklemeyi yaptıktan sonra veritabanımızı durdurup, sunucumuzu yeniden başlatmamız gerekecektir.
Sunucuyu yeniden başlattıktan sonra aşağıdaki komutu çalıştırdığımızda Huge Page ayarının yapılmış olduğunu göreceksiniz.

# grep HugePages /proc/meminfo
HugePages_Total: 1496
HugePages_Free: 485
HugePages_Rsvd: 446
HugePages_Surp: 0

Oracle Veritabanında Eksik Foreign Key Indexlerini Bulmak

Merhabalar,

Bazen veritabanında foreign key eksikliği nedeniyle ( enq: TM – contention wait ) beklemeler yaşayabilirsiniz. Supportta bununla ilgili bir döküman var (Doc ID 1019527.6). Bu yazımda bu scripti çalıştırıp eksik foreign key leri tespit etmekten bahsedeceğim.
Aşağıdaki scripti veritabanınızda TFSFKCHLK.SQL dosyası oluşturarak içine kopyalayın. Daha sonra eksik foreign keylerin olduğu schema ile veritabanınıza bağlanıp bu sorguyu çalıştırın.

$sqlplus onur/onur
@path/tfsfkchk

Bu sorguyu çalıştırdıktan sonra bulunduğunuz schemada “ck_log” diye bir tablo oluşturacaktır. Bu tabloyu sorguladığınızda yaratılacak indexlerin kolonları ve tablolarını görebiliriz.

select LineMsg from ck_log
where LineMsg NOT LIKE 'Checking%' AND
LineMsg NOT LIKE 'No foreign key%'
order by LineNum
/

Scripti buradan indirebilirsiniz. TFSFKCHLK.SQL

İsterseniz aşağıdaki scripti kopyalayarak sql dosyasını oluşturabilirsiniz.

SCRIPT

SET ECHO off
REM NAME: TFSFKCHLK.SQL
REM USAGE:"@path/tfsfkchk"
REM --------------------------------------------------------------------------
REM REQUIREMENTS:
REM None -- checks only the USER_ views
REM --------------------------------------------------------------------------
REM This file checks the current users Foreign Keys to make sure of the
REM following:
REM
REM 1) All the FK columns are have indexes to prevent a possible locking
REM problem that can slow down the database.
REM
REM 2) Checks the ORDER OF THE INDEXED COLUMNS. To prevent the locking
REM problem the columns MUST be index in the same order as the FK is
REM defined.
REM
REM 3) If the script finds and miss match the script reports the correct
REM order of columns that need to be added to prevent the locking
REM problem.
REM
REM
REM
REM -------------------------------------------------------------------------
REM Main text of script follows:

drop table ck_log;

create table ck_log (
LineNum number,
LineMsg varchar2(2000));

declare
t_CONSTRAINT_TYPE user_constraints.CONSTRAINT_TYPE%type;
t_CONSTRAINT_NAME USER_CONSTRAINTS.CONSTRAINT_NAME%type;
t_TABLE_NAME USER_CONSTRAINTS.TABLE_NAME%type;
t_R_CONSTRAINT_NAME USER_CONSTRAINTS.R_CONSTRAINT_NAME%type;
tt_CONSTRAINT_NAME USER_CONS_COLUMNS.CONSTRAINT_NAME%type;
tt_TABLE_NAME USER_CONS_COLUMNS.TABLE_NAME%type;
tt_COLUMN_NAME USER_CONS_COLUMNS.COLUMN_NAME%type;
tt_POSITION USER_CONS_COLUMNS.POSITION%type;
tt_Dummy number;
tt_dummyChar varchar2(2000);
l_Cons_Found_Flag VarChar2(1);
Err_TABLE_NAME USER_CONSTRAINTS.TABLE_NAME%type;
Err_COLUMN_NAME USER_CONS_COLUMNS.COLUMN_NAME%type;
Err_POSITION USER_CONS_COLUMNS.POSITION%type;

tLineNum number;

cursor UserTabs is
select table_name
from user_tables
order by table_name;

cursor TableCons is
select CONSTRAINT_TYPE,
CONSTRAINT_NAME,
R_CONSTRAINT_NAME
from user_constraints
where OWNER = USER
and table_name = t_Table_Name
and CONSTRAINT_TYPE = 'R'
order by TABLE_NAME, CONSTRAINT_NAME;

cursor ConColumns is
select CONSTRAINT_NAME,
TABLE_NAME,
COLUMN_NAME,
POSITION
from user_cons_columns
where OWNER = USER
and CONSTRAINT_NAME = t_CONSTRAINT_NAME
order by POSITION;

cursor IndexColumns is
select TABLE_NAME,
COLUMN_NAME,
POSITION
from user_cons_columns
where OWNER = USER
and CONSTRAINT_NAME = t_CONSTRAINT_NAME
order by POSITION;

DebugLevel number := 99; -- >>> 99 = dump all info`
DebugFlag varchar(1) := 'N'; -- Turn Debugging on
t_Error_Found varchar(1);

begin

tLineNum := 1000;
open UserTabs;
LOOP
Fetch UserTabs into t_TABLE_NAME;
t_Error_Found := 'N';
exit when UserTabs%NOTFOUND;

-- Log current table
tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, NULL );

tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Checking Table '||t_Table_Name);

l_Cons_Found_Flag := 'N';
open TableCons;
LOOP
FETCH TableCons INTO t_CONSTRAINT_TYPE,
t_CONSTRAINT_NAME,
t_R_CONSTRAINT_NAME;
exit when TableCons%NOTFOUND;

if ( DebugFlag = 'Y' and DebugLevel >= 99 )
then
begin
tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Found CONSTRAINT_NAME = '|| t_CONSTRAINT_NAME);

tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Found CONSTRAINT_TYPE = '|| t_CONSTRAINT_TYPE);

tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Found R_CONSTRAINT_NAME = '|| t_R_CONSTRAINT_NAME);
commit;
end;
end if;

open ConColumns;
LOOP
FETCH ConColumns INTO
tt_CONSTRAINT_NAME,
tt_TABLE_NAME,
tt_COLUMN_NAME,
tt_POSITION;
exit when ConColumns%NOTFOUND;
if ( DebugFlag = 'Y' and DebugLevel >= 99 )
then
begin
tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, NULL );

tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Found CONSTRAINT_NAME = '|| tt_CONSTRAINT_NAME);

tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Found TABLE_NAME = '|| tt_TABLE_NAME);

tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Found COLUMN_NAME = '|| tt_COLUMN_NAME);

tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Found POSITION = '|| tt_POSITION);
commit;
end;
end if;

begin
select 1 into tt_Dummy
from user_ind_columns
where TABLE_NAME = tt_TABLE_NAME
and COLUMN_NAME = tt_COLUMN_NAME
and COLUMN_POSITION = tt_POSITION;

if ( DebugFlag = 'Y' and DebugLevel >= 99 )
then
begin
tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Row Has matching Index' );
end;
end if;
exception
when Too_Many_Rows then
if ( DebugFlag = 'Y' and DebugLevel >= 99 )
then
begin
tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Row Has matching Index' );
end;
end if;

when no_data_found then
if ( DebugFlag = 'Y' and DebugLevel >= 99 )
then
begin
tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'NO MATCH FOUND' );
commit;
end;
end if;

t_Error_Found := 'Y';

select distinct TABLE_NAME
into tt_dummyChar
from user_cons_columns
where OWNER = USER
and CONSTRAINT_NAME = t_R_CONSTRAINT_NAME;

tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum, 'Changing data in table '||tt_dummyChar
||' will lock table ' ||tt_TABLE_NAME);

commit;
tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum,'Create an index on table '||tt_TABLE_NAME
||' with the following columns to remove lock problem');

open IndexColumns ;
loop
Fetch IndexColumns into Err_TABLE_NAME,
Err_COLUMN_NAME,
Err_POSITION;
exit when IndexColumns%NotFound;
tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum,'Column = '||Err_COLUMN_NAME||' ('||Err_POSITION||')');
end loop;
close IndexColumns;
end;
end loop;
commit;
close ConColumns;
end loop;
if ( t_Error_Found = 'N' )
then
begin
tLineNum := tLineNum + 1;
insert into ck_log ( LineNum, LineMsg ) values
( tLineNum,'No foreign key errors found');
end;
end if;
commit;
close TableCons;
end loop;
commit;
end;
/

Oracle Online Logların Boyutunu Nasıl Değiştiririz

Hemen hemen tüm DBA lerin başına en az bir kere online logların boyutunu değiştirme işi gelmiştir. Biliyorsunuz ki online logların boyutu ve sayıları veritabanımızın performansını doğrudan etkilemektedir. Çok küçük boyutlu loglar veritabanımızın arkaplanında çalışan processlerin çok fazla switch işlemi yapmasına ve bunun da veritabanında beklemeye sebep olmaktadırlar. Çok büyük boyutlu loglar da ise, veritabanının crash olması durumunda veri kayıplarına neden olacağını biliyoruz. Oracle ın önerdiği bir saat içinde en fazla 5 kere log switch olmasıdır. Bu yüzden online log boyutları veritabanı için çok önem taşımaktadır.

Şimdi örnek olarak veritabanımızda bulunan online logların boyutlarını değiştirelim.

Aşağıdaki komutla veritabanında bulunan log dosyalarını ve boyutlarını listeleyebiliyoruz.

SQL> select group#,members,status,bytes/1024/1024 as mb from v$log;

 GROUP#    MEMBERS STATUS                   MB
---------- ---------- ---------------- ----------
 1          1 INACTIVE                 50
 2          1 INACTIVE                 50
 3          1 CURRENT                  50

Yukarıdaki örnekten gördüğümüz üzerine veritabanında 3 farklı log grubu ve her grupta bir tane thread bulunmaktadır. Bu yazımda herkesin group ve thread in ne olduğunu bildiğini varsayıyorum. Aşağıdaki komut ise online log ların dosya sisteminde nerede olduğunu göstermektedir.

SQL> select group#,member from v$logfile;

 GROUP# MEMBER
---------- ------------------------------------------------------------
 3 /u01/app/oracle/oradata/orcl/redo03.log
 2 /u01/app/oracle/oradata/orcl/redo02.log
 1 /u01/app/oracle/oradata/orcl/redo01.log

Gördüğünüz üzerine her bir log dosyasının boyutu 50 MB. Şimdi bunları 100M yapacağız.
Veritabanında log dosyalarının direk boyutunu arttırıp azaltamıyoruz. Bunun için istediğimiz boyutta yeni online log dosyaları oluşturuyoruz ve daha sonra eski online log dosyalarını siliyoruz.

SQL> alter database add logfile '/u01/app/oracle/oradata/orcl/group401.log' size 100m;

Database altered.

SQL> alter database add logfile '/u01/app/oracle/oradata/orcl/group501.log' size 100m;

Database altered.
SQL> alter database add logfile '/u01/app/oracle/oradata/orcl/group601.log' size 100m;

Database altered.

Yukarıdaki komutların sonucunda veritabanında toplam 6 tane online log oldu.

SQL> select group#,members,status,bytes/1024/1024 mb from v$log;

 GROUP#    MEMBERS STATUS                   MB
---------- ---------- ---------------- ----------
 1          1 INACTIVE                 50
 2          1 INACTIVE                 50
 3          1 CURRENT                  50
 4          1 UNUSED                  100
 5          1 UNUSED                  100
 6          1 UNUSED                  100

6 rows selected.

Şimdi önceden oluşturulmuş olan 3 tane online log dosyasını sileceğiz. Burada dikkat etmemiz gereken nokta, sileceğimiz online log dosyasının status unun INACTIVE olmasıdır. Yukarıdaki örnekte gördüğümüz üzere şuan group 1 ve group 2 yi silebiliriz.

SQL> alter database drop logfile group 1;

Database altered.
SQL> alter database drop logfile group 2;

Database altered.

Group 3 ü silmeye çalıştığımızda sistem bu dosyanın şuan kullanıldığı için silenemeyeceğini bize söyleyecektir.

SQL>  alter database drop logfile group 3;

 alter database drop logfile group 3

*

ERROR at line 1:

ORA-01623: log 3 is current log for instance orcl (thread 1) - cannot drop

ORA-00312: online log 3 thread 1: '/u01/app/oracle/oradata/orcl/redo03.log'

Bu durumda bu dosyaların switch olmasını bekleyeceğiz ya da kendimiz switch komutunu çalıştıracağız.

SQL> alter system switch logfile;

System altered.

SQL> select group#,members,status,bytes/1024/1024 as mb from v$log;

 GROUP#    MEMBERS STATUS                   MB
---------- ---------- ---------------- ----------
 3          1 ACTIVE                   50
 4          1 CURRENT                 100
 5          1 UNUSED                  100
 6          1 UNUSED                  100

Yukarıdaki komutla birlikte group 3 teki log dosyasının status u CURRENT den ACTIVE e geçti. Durumu ACTIVE iken de bu dosyayı silemeyiz. Yani veritabanının bu dosya üzerinde check point işlemi tam olarak bitmemiştir. Aşağıdaki komutu çalıştırarak bu dosyayı INACTIVE durumuna getirebiliriz. INACTIVE olduktan sonra da bu dosyayı silebiliriz.

SQL> alter system checkpoint;

System altered.

SQL> select group#,members,status,bytes/1024/1024 as mb from v$log;

 GROUP#    MEMBERS STATUS                   MB
---------- ---------- ---------------- ----------
 3          1 INACTIVE                 50
 4          1 CURRENT                 100
 5          1 UNUSED                  100
 6          1 UNUSED                  100

SQL> alter database drop logfile group 3;

Database altered.

SQL> select group#,members,status,bytes/1024/1024 as mb from v$log;

 GROUP#    MEMBERS STATUS                   MB
---------- ---------- ---------------- ----------
 4          1 CURRENT                 100
 5          1 UNUSED                  100
 6          1 UNUSED                  100

Böylelikle veritabanımızda bulunan online log dosyalarının boyutunu 100M a arttırmış olduk, yani eski 50 MB ları silip yerine 100MB lık yeni online logları koymuş olduk.
Bir sonraki yazımızda görüşmek üzere…

TOAD – Grant Hatası

Merhabalar,
Geçenlerde bir müşterimizin veritabanına bağlanmaya çalışırken aşağıdaki hatayı aldım.

"Access to the following views required:
V$SESSION, V$PROCESS, V$SESS_IO, V$SESSION_WAIT, V$SESSION_EVENT, V$ACCESS, V$SESSSTAT, V$STATNAME, V$OPEN_CURSOR, V$SQL, V$LOCK, V$SESSION_LONGOPS, SYS.V_$TRANSACTION, SYS.V_$ROLLNAME, V$SQLTEXT_WITH_NEWLINES"

Bu hatanın çözümünü sizle paylaşmak istedim.

SQL> Grant select any dictionary, select any table, select_catalog_role to db_user;

Grant succeeded.

SQL> grant execute on sys.dbms_workload_repository to db_user;

Grant succeeded.

Windows Oracle Standby Veritabanı Arşiv Silme Scripti

Merhabalar,

Önceki yazımda Linux ve Unix işletim sistemleri için Standby veritabanında biriken arşiv dosyalarımızın temizlenmesi için script oluşturmuştuk. O scripte yeralan archiveDelete.sh scriptini windows için uyarladım. Geri kalan dosyalarda herhangi bir değişiklik olmayacak.
archiveDelete.bat

cd %archivePath% -- archivePath yerine arşiv scriptinin bulunduğu klasörü yazın.
del MAXSEQ.tmp
sqlplus -S /nolog < Maxseq.sql 
for /f "tokens=1,2" %%a in ('type MAXSEQ.tmp') do set seq%%a=%%b
set DD=%date:~-4%%date:~4,2%%date:~7,2%%time:~0,2%%time:~3,2%%time:~6,2%
set logfile=STANDBY_ARC_DEL_%DD%.log
(
 echo run{
 echo crosscheck archivelog all;
 echo delete noprompt archivelog until sequence %seq1% thread 1;
 echo delete noprompt archivelog until sequence %seq2% thread 2;
 echo delete noprompt archivelog until sequence %seq3% thread 3;
 echo delete noprompt archivelog until sequence %seq4% thread 4;
 echo }
) | rman target / nocatalog log %logfile%

forfiles /P %archivePath% /D -7 /M STANDBY*.* /C "cmd /c del @file" -- archivePath yerine arşiv scriptinin bulunduğu klasörü yazın.

Oracle Standby Veritabanı Arşiv Silme Scripti

Merhabalar,
Bu yazımda standby veritabanında biriken yüklenmiş arşivleri temizlemek için kullanabileceğimiz bir scriptten bahsedeceğim.
Scriptimiz Linux ve Unix işletim sistemlerinde çalışıyor ve 3 dosyadan oluşuyor. Şimdi bunları açıklayalım:

maxThreadNumber.sql

// Aşağıdaki sql komutunda veritabanında bulunan thread'lerin max sequence sayılarını öğrenip, maxThreadNumber.tmp adında bir dosyaya yazıyoruz.
// Select sorgusunda max değerden 10 çıkarıyoruz çünkü her türlü ihtimale karşı standby veritabanında en son 10 arşiv logunu tutuyoruz.
connect / as sysdba 
set heading off pages 0 echo off feedback off; 
spool maxThreadNumber.tmp; 
select thread#, max(sequence#)-10 from v$archived_log where applied ='YES' and REGISTRAR='RFS' group by thread# ; 
spool off; 
exit; 

archiveDelete.sh

#!/bin/bash

export ORACLE_HOME=Bu kısıma Oracle Home tam adresini yazacağız. Ör: /oracle/app/product/11.2.0/dbhome_1
export ORACLE_SID=Bu kısıma Oracle SID i yazacağız
export archivePath=Bu kısıma arsiv silme scriptini koyacağımız klasörün adresini yazacağız. Ör: /home/oracle/archiveDelete

## arsivDelete scriptini her çalıştırdığımızda maxThreadNumber.sql scripti maxThreadNumber.tmp adında bir dosya üretiyor. 
## Yeni dosya oluşturmadan önce eskisini siliyoruz.
 rm -f $archivePath/maxThreadNumber.tmp

 $ORACLE_HOME/bin/sqlplus / as sysdba < $archivePath/maxThreadNumber.sql 

## maxThreadNumber.tmp dosyasında veritabanımızda kaç tane thread olduğu yazmaktadır.
## Bu dosyaya göre aşağıda bulunan seq1,seq2.. gibi satırları çoğaltalım.
## Örneğin veritabanımızda 4 tane thread varsa seq2 ve seq3 teki '#' işaretlerini kaldırıp, seq4 için de bir satır oluşturmamız lazım.
 seq1=`cat $archivePath/maxThreadNumber.tmp | awk 'NR==1{print $2}'`
#seq2=`cat $archivePath/maxThreadNumber.tmp | awk 'NR==2{print $2}'`
#seq3=`cat $archivePath/maxThreadNumber.tmp | awk 'NR==3{print $2}'`

$ORACLE_HOME/bin/rman << EOF
 connect target /
 run{
 crosscheck archivelog all;
## Yukarıdaki thread sayısına göre aşağıdaki satırları düzenlemeyi unutmayın.
 delete noprompt archivelog until sequence $seq1 thread 1;
#delete noprompt archivelog until sequence $seq2 thread 2;
#delete noprompt archivelog until sequence $seq3 thread 3;
 }
 EOF
exit

Arşivleri silmek için sadece archiveDelete.sh scriptini çalıştırmamız gerekiyor.

$./archiveDelete.sh

Oracle Standby Veritabanı Komutları

Merhabalar,
Bu yazımda standby veritabanlarını yönetmek için kullanacağımız birkaç komuttan bahsedeceğim.

Öncelikle produciton veritabanından standby da hata olup olmadığını v$archive_dest view’ina bakarak görebiliriz.

$ sqlplus / as sysdba
SQL> show parameter log_archive_dest

Yukarıdaki komutla standby veritabanının hangi arşiv lokasyonuna yazıldığını öğrenebiliriz. Daha sonra öğrendiğimiz lokasyonun dest_id numarasını aşağıdaki komuta yazacağız.

SQL> select DEST_NAME, status,error from v$archive_dest where dest_id = 2;

DEST_NAME                             STATUS           ERROR
-----------------------------------   ---------        --------------------
LOG_ARCHIVE_DEST_2                    VALID

Yukarıdaki gibi VALID yazısını görüyorsak standby veritabanımız sorunsuz çalışıyor demektir. Eğer status bölümünde INVALID yazısı geliyorsa, Error bölümünde standby veritabanına bağlantı sorununun nedenini yazıyor.
Eğer standby veritabanımız çalışıyorsa, standby veritabanına bağlanıp production veritabanıyla arasındaki eksik arşiv sayısını aşağıdaki komut ile öğrenebiliriz.

SQL> select count(1) from v$archived_log where registrar='RFS' and APPLIED<>'YES';

Standby veritabanını kapatıp açtıktan sonra otomatik arşivleri üzerine apply etmesi için aşağıdaki komutu çalıştırmamız gerekiyor. Genellikle standby veritabanları kapatılıp açıldığında aşağıdaki komut çalıştırılmayı unutulur. Bu durumda production veritabanı standby veritabanına arşivleri yazmaya devam eder fakat standby veritabanı bu arşivleri üzerine apply etmez ve verilerimiz en sonra standby veritabanı kapatıldığı andaki production veritabanındaki verilerle aynı olur.

SQL> alter database recover managed standby database using current logfile disconnect from session;

Genel Oracle Hataları — ORA-12154, ORA-00600, ORA-01722, ORA-03113, ORA-01000

Merhabalar,

Bu yazımda genel olarak Oracle veritabanlarında ve uygulamalarda sıkça karşımıza çıkan oracle hatalarından bahsedeceğim. Genellikle bir oracle hatası aldığımızda ilk yaptığımız şey hata kodunu kopyalayıp Google’da aramaktır. Bence ilk olarak support.oracle.com’u tercih edin. Daha hızlı ve güvenli çözüme ulaşabilirsiniz. Bu yazımda ise Google’da en çok aranan 5 tane hatadan bahsedeceğim.

ORA-12154: TNS:could not resolve the connect identifier specified

Bu hatayı aldığınız zaman veritabanınız TNS bağlantısı kuramıyor demektir. Genellikle bağlantı bilgilerinde sıkıntı olabiliyor. Bağlantı bilgilerini kontrol ettikten sonra Listener’ın açık olup olmadığına bakın.

$ cat $ORACLE_HOME/network/admin/tnsnames.ora

TNSNAMES.ora dosyası içinde bağlanmaya çalıştığınız veritabanı bilgilerinin sunucu adına ve servis adına dikkat edin. Genellikle yanlış bilgiler yüzünden bağlantı sağlanamıyor. Bağlantı bilgileri doğruysa listener’ın açık olup olmadığına bakın.

$ lsnrctl status
$ lsnrctl start -- listener kapalıysa, listener'ı çalıştırın

ORA-00600: internal error code, arguments: [%s], [%s],[%s], [%s], [%s]

Eğer veritabanınızda ora-600 hatası alıyorsanız, veritabanınızda ciddi sıkıntılar var demektir. Belki bir bug’la karşılaşmışsınızdır belki sistem parametrelerini doğru ayarlamamışsınızdır, belki de farklı bir sıkıntıdan kaynaklanıyordur. ORA-600 hatası aldığınız zaman yanında birkaç tane parametre de gelir. İlk yapmanız gereken support.oracle.com a girip ora-600 hatalarına bakmaktır. Support sitesinde Note 153788.1 diye arama yaparsanız karşınıza oracle generic hatalarının olduğu bir araç geliyor. Bu sayfayı kullanarak ora-600 hatasını, onun yanında gelen parametretleri ve veritabanı versiyonunuzu girerek, sorunuzun kaynağını ve onunla ilgili dökümanları görebilirsiniz.

ORA-01722: Invalid Number

Bu hatayı genellikle sql de sayısal olmayan string bir değeri sayıya çevirmeye çalıştığınız zaman alıyorsunuz. Genellikle tablolarımızda verileri varchar2 alanında tutuyoruz. Bazen sayısal verileri de string olarak tutabiliyoruz. Bu sayısal verileri de karşılaştırma yapmak için to_number() gibi fonksiyonlarla dönüştürmek istiyoruz. Fakat bizim string olarak sakladığımız sayısal verilere bazen yanlış veri girişinde bulunuyor ve bu hatayı alıyoruz.
Örneğin,
no adında bir alanımız olsun ve buraya sürekli sayısal değer girelim.

create table deneme (no varchar2(10));
insert into deneme values ('1');
insert into deneme values ('2');
commit;

Peki ya yanlışlıkla biri farklı bir değer girerse:

insert into deneme values ('uc');
commit;

to_number() fonksiyonunu kullandığınızda bu hatayı alacaksınız.

select to_number(no,'999');
ORA-01722: Invalid Number

ORA-03113: end-of-file on communication channel

Bu hatayı aldığımız zaman client makinesinden veritabanına olan bağlantımız bir nedenden dolayı kopmuş demektir. Bu sorunun kaynağı,
Server crashed olmuş olabilir, işletim sistemi seviyesinde çalışan process’ler kapanmış olabilir, ya da oracle veritabanından kaynaklanan içsel bir problem olabilir. Genelde çok basit hatalardan dolayı bile oracle bu hatayı vermektedir.
Bu hatayı aldığınız zaman bence en iyisi alert.log dosyasında hatayla ilgili detaylı olarak logları incelemektir. Çözüm tahmin ettiğinizden de kolay olabilir.

ORA-01000: maximum open cursors exceeded

Bu hata, veritabanında olan maksimum açık cursor sayısına ulaştığınız zaman oluşuyor. Yani genelde programcılar kod kısmında veritabanına bağlantı sağladıktan sonra bağlantıyı sonlardırmıyorlar ya da her işlem için ayrıca bağlantı açıyorlar. Böyle durumlarda sistem çok fazla kullanıldığı anda ORA-01000 hatası oluşuyor. Maksimum açık cursor parametresi veritabanı açılış parametrelerinden biridir. sqlplus ile bağlanıp

SQL> show parameter open_cursor 

komutunu çalıştırdıktan sonra mevcut değeri görebilirsiniz. Çözüm olarak ya bu değeri arttıracaksınız ya da programcılarınızda kodu tekrar inceleyip açık kalan cursor’leri kapatmasını isteyeceksiniz.
Bu değeri arttırmak için, sqlplus‘s bağlanın :

SQL> alter system set OPEN_CURSOR=1000 scope=both;

Burada 1000 yerine, sisteminize uygun bir değer vermelisiniz.