Bu yazımızda Oracle Veritabanı temel olarak hangi komponentlerden oluşur, memory deki bazı işlemler nelerdir, storage kısmında işler nasıl yürür, oracle bazı işlemleri nasıl yapar, bir user bir oracle veritabanına nasıl bağlantı kurar, bağlandığında neler olur gibi temel oracle veritabanı işleyişini anlamamızı sağlayacak mimari özelliklerden bahsedeceğiz. Aşağıdaki şekilde kabaca mimariyi ve mimarideki en temel yapıların isimlerini görmekteyiz, bu yapıları ve işlevlerine bu yazımızda yüzeyselde olsa değinmeye çalışacağım.
Bir Oracle veritabanı sunucusu, bir veritabanı ve bir instance’tan (veritabanı örneği) oluşur. Instance, belirli hafıza yapıları ve arkaplan işlemlerinden oluşur. Instance başlatıldığında, SGA (System Global Area) adı verilen bir hafıza bölümü RAM üzerinde oluşturulur ve arkaplan işlemleri başlatılır.
Veritabanı hem fiziksel hem de mantıksal yapılardan oluşur. Bu iki yapının farklı olmasından dolayı, verinin fiziksel olarak saklanması mantıksal saklama yapılarına erişimi etkilemeden gerçekleştirilebilir.
Veritabanına Bağlanma
Bağlantı (Connection) : Bir instance (veritabanı örneği) ile bir user process (kullanıcı işlemi) arasındaki iletişimdir. Connection ı bir yol olarak düşünebiliriz.
Oturum (Session) : Bir user (kullanıcı) ın, bir user process üzerinden kurduğu özel bir bağlantıdır.
Connection ve Session, kullanıcı işlemi ile yakın ilişkili ama farklı anlamlarda iki kavramdır.
Kullanıcı SQL*Plus gibi bir araç veya veritabanını kullanan bir uygulama çalıştırdığında, istemci makinede bir user process başlatılır. Kullanıcı, adını, şifresini ve ulaşmak istediği veritabanının ismini girerek Oracle Sunucusuna bağlandığı anda sunucu makinede bir server process yaratılır. Eğer Dedicated Server değil de Shared Server yapısı kullanılıyorsa her user process için ayrı bir server process oluşturulmaz. Her oturum dispatcher tarafından paylaşımlı server process havuzuna yönlendirilerek, user process’in faaliyette olan bir server process ile ilişkilendirilmesi sağlanır. •User process isteklerini server process’e iletir. Server process istekleri yerine getirir, ve sonucunu user process’e verir. Kullanıcı bağlantıyı kestiğinde server ve user process’ler bitirilir.
Her çalışan Oracle veritabanı bir instance ile ilişkilendirilir. ORACLE_SID ile işletim sistemine tanıtılan instance, belirli bir zamanda sadece bir veritabanını açıp kullanabilir.
Instance başladıktan sonra, Oracle yazılımı bu instance’ı belirli bir veritabanı ile ilişkilendirir. Bu işleme veritabanını “mount” etme denir. Mount konumunda iken veritabanı sadece yetkili kullanıcılara açıktır. Open konumuna getirildiğinde ise tüm kullanıcılar veritabanına bağlanabilir.
Bir bilgisayar üzerinde her biri kendi fiziksel veritabanına erişebilen birçok instance aynı anda çalışabilir.
Oracle Database mimarisini çeşitli birbiriyle ilişkili yapısal bileşenler olarak görebilirsiniz.
Bir Oracle örneği, veritabanı yönetmek ve veritabanına erişmek için bellek yapıları ve işlemleri kullanır. Tüm bellek yapıları, veritabanı sunucusunu oluşturan bilgisayarların ana belleğinde bulunur. İşlemler, bu bilgisayarların belleğinde çalışan işlerdir. Bir işlem, bir “kontrol dizgesi” veya bir işletim sisteminde bir dizi adım çalıştıracak bir mekanizma olarak tanımlanır.
Oracle Database, çeşitli amaçlar için bellek yapıları oluşturur ve kullanır. Örneğin, bellek, çalıştırılan program kodunu, kullanıcıların paylaştığı verileri ve bağlı her kullanıcı için özel veri alanlarını saklar. İki temel bellek yapısı bir örnekle ilişkilendirilir:
•System Global Area (SGA), bir instance için veri ve kontrol bilgisi içeren SGA bileşenleri olarak bilinen paylaşımlı bellek yapıları grubudur. SGA, tüm sunucu ve arka plan işlemleri tarafından paylaşılır. SGA’da saklanan verilere örnek olarak önbellekte saklanan veri blokları ve paylaşılan SQL alanları bulunur.
•Program Global Alanları (PGA), bir sunucu veya arka plan işlemi için veri ve kontrol bilgisi içeren bellek bölgeleridir. Bir PGA, bir sunucu veya arka plan işlemi başlatıldığında Oracle Database tarafından oluşturulan paylaşılmayan bellektir. PGA’ya erişim sunucu süreci için özeldir. Her sunucu işlemi ve arka plan işlemi kendi PGA’sına sahiptir.
System Global Area (SGA)
Instance, SGA adında tüm sunucu ve arkaplan işlemleri tarafından paylaşılan bir hafıza yapısına sahiptir. SGA’nın içindeki bileşenler:
Database Buffer Cache: Veri dosyalarından elde edilen veri bloklarını saklar. Değişikliğe uğrayan bloklar belirli zaman aralıklarında veri dosyalarına aktarılır.
Redo Log Buffer: Instance’ın veritabanında yaptığı değişikliklerin kaydedildiği bölgedir. Gerektiğinde kurtarma (recovery) işleminde kullanılmak üzere bu bilgiler belirli zaman aralıklarında redo log dosyalarına aktarılır.
Shared Pool: En son çalıştırılan sorgu ve veri kütüphanesinden en son kullanılan veri gibi kullanıcılar arasında paylaşılabilen çeşitli bilgileri saklar.
Large Pool: Yedekleme/Kurtarma işlemleri ve G/Ç sunucu işlemleri gibi bazı büyük işlemler için büyük miktarda hafıza tahsisi gerektiğinde kullanılan bölgedir.
Java Pool: Java Sanal Makinesi (JVM) tarafından kullanılan tüm oturum-bazlı Java kodu ve verisini saklar. Streams Pool: Yakalama (capture) ve uygulama (apply) işlemleri için gerekli olan bilgileri saklamak için Oracle Stream’leri tarafından kullanılır
Process Global Area (PGA)
PGA, bir sunucu işlemi veya bir arkaplan işlemi için veri ve kontrol bilgilerini içeren hafıza bölgesidir. Birçok process tarafından paylaşılabilen SGA’nın tersine, PGA sadece kendisini başlatan process tarafından kullanılabilir. Hafıza yapılarının büyüklüğünü belirlemek için çeşitli parametreler kullanılabilir. Örneğin MEMORY_TARGET parametresi ile Oracle’ın sistem üzerinde kullanabileceği RAM alanı belirlenebilir. Bu sayede belirlenen büyüklüğü aşmayacak şekilde SGA ve PGA bileşenlerinin boyutları Oracle veritabanı tarafından otomatik olarak değiştirilir.
Process Mimarisi
Background Processes
Arkaplan işlemleri kullanıcı işlemi ile doğrudan ilişkili değildirler. Belirli zaman aralıklarında veya belirli koşulların sağlanması durumunda çalışırlar.
Database Writer (DBWn): Database buffer cache’te değişen veri bloklarını veri dosyalarına yazar.
Log Writer (LGWR): Veritabanında değişikliğe neden olan DML komutlarını redo log buffer’dan redo log dosyalarına yazar.
System Monitor (SMON): Veritabanı açıldığında recovery gerekip gerekmediğini araştırır. Veritabanının tutarlılığını kontrol eder.
Process Monitor (PMON): Process’lerden biri sonlanmazsa bu process’in kullandığı tüm kaynakları temizler.
Checkpoint process (CKPT): Buffer cache’teki değişiklikler veritabanına kaydedildiğinde, veritabanının durum bilgisini günceller.
Her Oracle instance’ı, farklı arkaplan işlemlerine sahip olabilir. RAC (Real Application Clusters) ve ASM (Automatic Storage Management) kullanılmadığı durumlarda instance içinde yer alan arkaplan işlemleri:
- Database Writer process (DBWn)
- Log Writer process (LGWR)
- Checkpoint process (CKPT)
- System Monitor process (SMON)
- Process Monitor process (PMON)
- Recoverer process (RECO)
- Job Queue processes
- Archiver processes (ARCn)
- Queue Monitor processes (QMNn)
Eğer RAC veya ASM kullanılıyorsa daha fazla sayıda arkaplan işlemi kullanılır. V$BGPROCESS görünümü içinde arkaplan işlemleri ile ilgili bilgiler yer alır.
Bazı arkaplan işlemleri instance başladığında otomatik olarak yaratılırken, bazıları ise gerekli olduğu durumlarda başlatılır.
Server Process, değişiklikleri database buffer cache’deki veri ve rollback bloklarına kaydeder. Database Writer (DBWn), dirty buffer’ları database buffer cache’ten veri dosyalarına yazar. Yeterli sayıda serbest buffer’ın (Server process’in veri dosyalarından blok okuması gerektiğinde, üstüne yazılabilecek buffer’lar) database buffer cache’de bulunmasını sağlar. Server process direkt olarak veri dosyalarına ulaşmadığı için performans artar. DBWn aşağıdaki olaylardan biri gerçekleşince çalışır:
- Dirty buffers sayısı eşik değerine ulaştığında
- Bir işlem belirli sayıda boş blok arayıp bulamadığında
- Bir zamanaşımı oluştuğunda
- Veritabanı kapanırken
Girdileri redo log buffer’dan redo log dosyalarına yazan arkaplan işlemidir. Aşağıdaki durumlarda LGWR redo log dosyasına sıralı yazma işlemi gerçekleştirir.
- Redo log buffer’ın 1/3’ü dolduğunda
- Bir zamanaşımı oluştuğunda (her 3 saniyede bir defa)
- DBWR değişen blokları database buffer cache’ten veri dosyalarına aktarmadan önce
- Bir transaction commit edildiğinde (işlendiğinde)
1 Parse Bu bölümde, kullanıcı process’i sorguyu server process’e, yazım kontrolü için bir istek ile gönderir veya sorguyu işler. Server process, komutun geçerliliğini kontrol eder, ve SGA’daki Shared Pool alanını ifadeyi derlemek için kullanır. Bu safhanın sonunda server process user process’e olumlu yada olumsuz bir yanıt gönderir.
Parse aşamasında kullanılan Shared Pool içinde bulunan Library Cache, en son kullanılan SQL ifadeleri ile ilgili bilgileri saklar. Bir ifade yeniden çalıştırılırken, eğer çalıştırma planının üzerine başka ifadelerin çalıştırma planları yazılmadıysa, server process ifadeyi yazım açısından incelemek (parse) zorunda kalmaz. Data Dictionary Cache ise, tablo ve kolon tanımlamaları, kullanıcı isimleri ve şifreler, ve ayrıcalıklar gibi en son kullanılan veri kütüphanesi bilgilerini içerir.
2 Execute Bu safhada server process veriyi almak için hazırlar.
3 Fetch Sorgu tarafından seçilen satırlar bu safhada server’dan user’a gider. Transfer için kullanılan hafızanın büyüklüğüne bağlı olarak, sorgunun sonucunu kullanıcıya aktarmak için bir yada daha çok fetch (alıp getirme) gereklidir.
Bir DML (Data Manipulation Language) ifadesi (UPDATE, DELETE, INSERT) sadece Parse ve Execute safhalarını içerir.
- Server process, veri ve rollback bloklarını buffer cache’de bulamazsa, bu blokları veri dosyalarından okur.
- Okunan blokları buffer cache’e kopyalar.
- Server process veriyi kilitler.
- Server process, yapılan değişikliği, redo log buffer içindeki rollback (önceki değer) ve veri (yeni değer) kısımlarına kaydeder.
- Server process, database buffer cache içindeki rollback bloğuna önceki değeri kaydeder ve veri bloğunu da günceller. Buffer cache’teki her iki blok, diskteki ilgili bloklarla aynı değerlere sahip olmadıklarını belirtmesi için, dirty buffers olarak işaretlenir.
Database Buffer Cache: En son kullanılan veri bloklarını saklamak için kullanılır. Her bir buffer’ın büyüklüğü, DB_BLOCK_SIZE parametresi ile belirlenen blok boyutu ile aynıdır. Buffer sayısı DB_BLOCK_BUFFERS ile belirlenir. Oracle server Buffer Cache’de yeni blok alanları temin etmek için Least Recently Used (LRU) algoritmasını kullanır.
- 1 Server process, redo log buffer’a bir commit kaydı yapar. Bu kaydı yaparken SCN (System Change Number) kullanır. Bir transaction commit edildiğinde, Oracle Server bu transaction’a, veritabanı için unique olan ve devamlı artan bir SCN verir.
- 2 LGWR redo log buffer girdilerini, commit kaydı ile beraber, redo log dosyalarına yazar. Bu noktadan sonra, dosya okuma hatası oluşmadıkça, Oracle server değişiklerin kaybolmayacağını garanti eder.
- 3 COMMIT’in tamamlandığı kullanıcıya bildirilir.
- 4 Server process, transaction’ın bittiğine ve kilitlerin kaldırılabileceğine dair bilgiyi kaydeder.
COMMIT’in avantajları:
Log dosyalarına sıralı yazmak, veri dosyalarındaki farklı bloklara yazmaktan daha hızlıdır. Log dosyalarına yazılan değişiklikleri kaydeden bilgi çok küçüktür. Bunun yanında veri dosyalarına yazmak, verinin tüm bloklarının yazılmasını gerektirir. Transaction’ın büyüklüğü COMMIT işleminin harcadığı zamanı etkilemez.
Contol File (Kontrol dosyaları): Kontrol dosyasında veritabanının fiziksel yapısı ile ilgili bilgiler (veritabanının adı, veri dosyaları ve redo log dosyalarının yerleri ve adları, …) tutulur. Bir veritabanı en az bir kontrol dosyası içerir.
Data Files (Veri dosyaları): Veri kütüphanesini, kullanıcı (şema) nesnelerini ve transaction’lar tarafından değiştirilen eski değerleri saklar. Bir veritabanı en az bir veri dosyasına sahiptir.
Online redo log dosyaları: Beklenmedik durumlar karşısında veri kaybını önlemek ve veritabanını yeniden oluşturmayı sağlamak için veritabanında olan değişikliklerin kaydını tutar. Bir veritabanına en az 2 redo log gereklidir.
Parametre dosyası (Spfile , Pfile): Bir Oracle instance’ının kendisini başlatırken gerek duyduğu tanımların saklandığı metin tabanlı dosyadır.
Password Files (Şifre dosyası): SYS gibi ayrıcalıklı veritabanı kullanıcılarının şifrelerini saklar.
Yedek dosyaları: Orijinal veri dosyasının hasar görmesi durumunda kullanılır.
Arşivlenmiş redo log dosyaları: Redo log dosyalarının offline kopyalarıdır. Disk bozukluğu gibi durumlarda kurtarma işlevi görür.
Trace dosyaları ve Alert log dosyası
Oracle çalışırken bir hata oluşursa, mesajlar ALERT dosyasına kronolojik olarak yazılır. Veritabanı açılırken, eğer ALERT dosyası yoksa Oracle bir tane yaratır.
Eğer hata bir arkaplan işlemi tarafından tespit edildiyse, hata ile ilgili bilgi o işlem ile ilişkilendirilen ayrı bir iz (trace) dosyasına yazılır. Gerekli olduğu durumlarda veritabanı yöneticisi veya Oracle destek birimi çalışanı tarafından incelenir.
İz dosyaları aynı zamanda kullanıcının isteği ile server işlemleri tarafından da yaratılabilir. Bu dosyalara kullanıcı iz dosyaları (user trace files) denir. Bu dosyaların konumu parametre dosyasındaki USER_DUMP_DEST ile, alabileceği en büyük değer ise MAX_DUMP_FILE_SIZE ile belirlenebilir.
Aşağıdaki komut belirli bir oturum için bir iz dosyasının kullanılmasını sağlar. –ALTER SESSION SET SQL_TRACE = TRUE;
Veri Blokları (Data Blocks)
En küçük düzeyde, bir Oracle veritabanının verileri veri bloklarında saklanır. Bir veri bloğu, disk üzerindeki belirli sayıda fiziksel veritabanı alanına karşılık gelir. Bir veritabanı, Oracle veri bloklarında boş veritabanı alanını kullanır ve ayırır.
Veritabanı, işletim sisteminden veri blokları isteyince, işletim sistemi bunu gerçek bir dosya sistemine veya depolama aygıtındaki disk bloğuna eşleştirir. Bu nedenle, veritabanınızdaki verilerin herhangi birinin fiziksel adresini bilmeniz gerekmez.
Veri bloğunun boyutu DB_BLOCK_SIZE parametresi ile tanımlanır. Varsayılan 8 KB boyut çoğu veritabanı için yeterlidir. Veritabanınız, büyük tablolar ve dizinler içeren bir veri ambarı uygulamasını destekliyorsa, daha büyük bir blok boyutu yararlı olabilir.
Veritabanınız, okuma ve yazma işlemleri rasgele olan bir işlemi (transaction) destekliyorsa, daha küçük bir blok boyutu belirlemek faydalı olabilir. Maksimum blok boyutu işletim sisteminize bağlıdır.
Uzantı (Extent)
Mantıksal veritabanının sonraki seviyesine uzantı (extent) denir. Uzantı, belirli bir bilgi türünü depolamak için kullanılan belirli sayıda (tek bir tahsisde elde edilen) bitişik veri bloklarıdır. Her extent yalnızca bir veri dosyasında mevcut olabilir.
Bölüm (Segment)
Bir segment, belirli bir mantıksal yapı için ayrılmış extent’ler kümesidir. Oracle veritabanı dinamik olarak alan ayırır. Bir segment’in mevcut extent’leri dolduğunda, yeni extent’ler eklenir. Bu nedenle, bir segment’in extent’leri disk üzerinde bitişik olabilir veya olmayabilir.
Segment türleri:
- Data segment: Dizin içermeyen her tablo bir; dış tablolar, bölümlenmiş tablolar ve geçici tablolar ise bir veya daha fazla segment’e sahiptir. Bir tablonun tüm verileri, kendisine ait veri segment’inin extent’lerinde saklanır. Bölümlenmiş (partitioned) bir tablo için, her bölüm bir veri segment’ine sahiptir. Her kümeye (cluster) ait ayrı bir veri segment’i vardır. Kümedeki her tablonun verileri kümenin veri segment’inde saklanır.
- Index segments: Her dizin (index) verisini saklayan bir index segment’ine sahiptir. Bölümlenmiş bir dizin için, her bölüm bir index segment’ine sahiptir.
- Rollback (undo) segments: Her instance için geri alma (undo) bilgilerini geçici olarak saklamak için çok sayıda geri alma segment’i içeren bir UNDO tablo alanı oluşturulur. Geri alma segment’indeki bilgiler, tutarlı (consistent) bir veritabanı oluşturmak için ve veritabanı kurtarma sırasında, kullanıcılar için kaydedilmemiş işlemleri geri almak için kullanılır.
- Temporary segments: Geçici bölümler, bir SQL ifadesinin yürütmeyi tamamlamak için geçici bir çalışma alanına ihtiyacı olduğunda Oracle veritabanı tarafından oluşturulur. Deyim yürütmeyi tamamladığında, geçici segment’in extent’leri gelecekteki kullanım için instance’a geri verilir. Her kullanıcı için veya veritabanı çapında kullanılan bir varsayılan geçici tablo alanı belirtmeniz önerilir.
Tablespace, Şema ve Veri Dosyası
Tablespace: Tablo alanı yönetimsel işleri kolaylaştırmak için bütün uygulama nesnelerini birlikte gruplar. Kullanıcılara yer tahsis etmek, verinin ulaşılabilirliğini kontrol etmek, veri saklanmasını farklı disklere bölerek I/O performansını arttırmak, kısmi backup ve kısmi recovery işlemlerini gerçekleştirmek gibi kullanım alanları vardır. Her tablo alanı sadece bir veritabanına ait olabilir, ve bir yada daha çok veri dosyasından oluşur. Veritabanı çalışırken tablo alanları offline konumuna getirilebilir. “Oracle Storage Manager” ile tablo alanları yaratılabilir.
Şema (Schema): Bir veritabanı kullanıcısının sahip olduğu veritabanı nesnelerinin (tablo, views, index, sequence, stored procedures, …) kümesidir.
Data File (Veri Dosyası): Her tablo alanı bir yada daha çok veri dosyası içerir. Bir veri dosyası sadece bir tablo alanına ait olabilir. Veritabanı yöneticisi, bir veri dosyasının büyüklüğünü, o dosyanın yaratılmasından sonra da değiştirebilir, veya tablo alanı nesnesinin büyümesiyle orantılı olarak büyümesini sağlayabilir.
SYSTEM ve SYSAUX Tablespace
- SYSTEM ve SYSAUX tablo alanları her veritabanında bulunmak zorundadır (veritabanı yaratılırken otomatik olarak yaratılırlar).
- SYSTEM tablo alanı veri sözlüğü tabloları gibi temel verileri saklar.
- Yardımcı (auxiliary) bir tablo alanı olan SYSAUX ise ek veritabanı bileşenleri (Enterprise Manager Repository gibi) içerir.
- Her iki tablo alanı da yalnızca okunur (read-only) konuma getirilemez. SYSTEM veritabanı açıkken her zaman çevrim içi yani kullanılabilir konumda olmalıdır, SYSAUX ise tablo alanı kurtarma işleminde çevrim dışı konuma getirilebilir.
Startup ve Shutdown
NOMOUNT Veritabanı yaratılırken, veya kontrol dosyaları tekrar yaratılırken kullanılır. Instance başlarken; parametre dosyası (init<SID>.ora) okunur, SGA oluşturulur, arkaplan işlemleri başlatılır, trace ve ALERT dosyaları açılır.
MOUNT Özel bakım işlemlerini gerçekleştirmek için kullanılır. Örneğin veritabanı şu işlemler için, açılmadan, sadece mount edilmelidir.
- Data File isimlerinin değiştirilmesi
- Redo log arşivleme seçeneklerinin değiştirilmesi
- Veritabanının yedeğinin alınması
Mount edilirken; önceden açılmış instance ile veritabanı ilişkilendirilir, parametre dosyasında belirtilen kontrol dosyaları açılır, veri ve redo log dosyalarının durumlarını ve isimlerini elde etmek için kontrol dosyası okunur.
OPEN Veritabanı açılınca tüm kullanıcılar veritabanına bağlanabilir. Veritabanı açılırken; online veri dosyaları ve online redo log dosyaları açılır.
Normal Varsayılan kapanma modudur. Yeni bağlantılara izin verilmez. Oracle Server tüm kullanıcıların bağlantılarını kesmelerini bekler. Oracle instance’ı kapatmadan önce veritabanını dismount eder ve kapatır. Bir sonraki startup instance recovery gerektirmez.
Transactional Hiçbir istemci yeni bir transaction’a başlayamaz. Devam eden transaction’ı biten istemcinin bağlantısı kesilir. Tüm transaction’lar bittiğinde shutdown immediate oluşur. Bir sonraki startup instance recovery gerektirmez.
Immediate Devam etmekte olan SQL ifadeleri bitirilmez. Oracle Server, veritabanına bağlı olan kullanıcıların, bağlantılarını kesmelerini beklemez. Aktif transaction’lar rollback edilir ve bağlı tüm kullanıcıların bağlantısı kesilir. Oracle instance’ı kapatmadan önce veritabanını dismount eder ve kapatır. Bir sonraki startup instance recovery gerektirmez.
Abort Diğer 3 yöntemle kapanma gerçekleştirilemezse, veritabanı instance’ı gözardı edilerek kapatılabilir. Devam etmekte olan SQL ifadeleri derhal sonlandırılır. Oracle, veritabanına bağlı olan kullanıcıların, bağlantılarını kesmelerini beklemez. Commit edilmeyen transaction’lar rollback edilmez. Dosyalar kapatılmadan instance sonlandırılır. Bir sonraki startup instance recovery gerektirir.
Buraya kadar anlatılan bilgiler, elbetteki tüm Oracle Veritabanı çalışma mantığını içermiyor, temel seviyede bir oracle veritabanı nelerden oluşmuştur ve nasıl çalışır? Sorusunun cevabı niteliğinde olabilir. Sonraki yazılarımızda, Oracle RAA, Backup (RMAN), Data Guard gibi sektörde Oracle ı öne çıkaran bazı teknolojiler üzerinde yazılar yazmaya çalışacağım, umarım okuyan ve araştıran arkadaşlara faydası olur.
Herhangi bir yerde yanlış olduğunu düşündünüz veya kafanıza takılan bir yer olur ise iletişim kısmından bana ulaşabilirsiniz. Mutlaka uygun bir zamanda size dönüş yaparım.
Comments (1)
Matarasesays:
Mart 28, 2022 at 10:54 amSeverek takip ediyorum. İçeriklerin artması dileğiyle