WordPress

    Site Taşıma Sonrası Veritabanındaki Eski URL'leri Değiştirme

    Taşımadan sonra veritabanında kalan eski alan adlarını serileştirilmiş veriyi bozmadan değiştirmenin yollarını anlatır.

    12 dk okuma Güncellendi: 11 Ağustos 2026

    Site taşındı, dosyalar yerinde, veritabanı içe aktarıldı — ama sitenin yarısı hâlâ eski alan adını gösteriyor. Menü linkleri eski adrese gidiyor, görseller eski sunucudan çekilmeye çalışılıyor, ürün sayfaları yanlış yönleniyor. Veritabanında URL değiştirme işi, taşımanın en çok bozulan ve en çok "yaptım ama site tamamen çöktü" şikâyetiyle geri dönen adımıdır. Bunun tek bir sebebi var: WordPress ve benzeri sistemler bazı verileri serileştirilmiş (serialized) biçimde saklar ve düz bir SQL REPLACE komutu bu yapıyı sessizce kırar.

    Bu yazıda önce serileştirilmiş verinin neden düz replace'e dayanamadığını somut bir örnekle göstereceğim, sonra eski adresin veritabanının hangi tablolarında saklandığını çıkaracağız ve üç yöntemi — WP-CLI search-replace, eklenti ve gerçekten güvenli olan dar kapsamlı SQL — hangi durumda hangisinin doğru olduğuyla birlikte anlatacağım. Sonunda değişiklik sonrası kontrol listesi ve sık yapılan hatalar var. Türkçe kaynakların çoğu doğrudan UPDATE wp_posts SET post_content = REPLACE(...) komutu verip geçiyor; o komut basit bir blog yazısında çalışır, sayfa kurucu kullanan hiçbir sitede çalışmaz.

    Neden Basit SQL REPLACE Siteyi Bozar#

    Serileştirilmiş veri, PHP dizilerinin metin olarak saklanmış hâlidir ve her metin parçasının uzunluğunu kendi içinde yazar. Bir örnek üzerinden görmek her şeyi netleştirir. Elementor'un bir bölüm ayarında şu değer bulunsun:

    a:1:{s:3:"url";s:27:"https://eskisite.com/gorsel";}
    

    Buradaki s:27 şu anlama gelir: "bundan sonra gelen metin 27 karakterdir". Şimdi düz bir SQL replace ile eskisite.com ifadesini yenisitem.com.tr ile değiştirdiğinizi düşünün. Metin 31 karaktere çıkar ama başındaki sayı hâlâ 27 yazar:

    a:1:{s:3:"url";s:27:"https://yenisitem.com.tr/gorsel";}
    

    PHP bu değeri açmaya çalıştığında uzunluk tutmadığı için diziyi çözemez ve false döner. Sonuç, kullanıcı tarafında şöyle görünür: Elementor ile yapılmış sayfalar tamamen boş açılır, ACF alanları görünmez olur, Divi modülleri kaybolur, WooCommerce ürün varyasyonları listelenmez, tema seçenekleri sıfırlanmış gibi davranır. En sinsi tarafı da şudur: hata mesajı çıkmaz. Site açılır, sadece içeriğin bir kısmı sessizce yok olur — ve genelde bu, replace komutunu çalıştırdıktan saatler sonra fark edilir.

    Bu yüzden kural nettir: serileştirilmiş veri içeren hiçbir sütuna düz SQL replace uygulanmaz. Doğru araçlar veriyi önce çözer, içindeki metni değiştirir, uzunlukları yeniden hesaplayıp tekrar serileştirir. Aşağıdaki üç yöntemden ikisi bunu yapar.

    Değiştirmeden Önce: Yedek ve Envanter#

    Hiçbir koşulda yedek almadan başlamayın. Bu iş geri alınabilir görünür ama değildir; yanlış bir replace, aynı komutu ters yönde çalıştırarak düzelmez, çünkü bozulan uzunluk bilgisi geri gelmez. Komut satırınız varsa:

    mysqldump -u kullanici -p veritabani_adi > yedek-$(date +%F-%H%M).sql
    

    Paylaşımlı hostingte aynı işi phpMyAdmin'in Dışa Aktar sekmesinden yapabilirsiniz; ayrıntılar için phpMyAdmin içe/dışa aktarma yazısına bakın. Yedeği aldıktan sonra dosya boyutunu kontrol edin: birkaç kilobayt boyutunda bir dump, dışa aktarmanın yarım kaldığını gösterir.

    Sonraki adım envanter: eski adres tam olarak nerede duruyor? Bunu tahmin etmeyin, sayın. Aşağıdaki sorgu size ana tablolardaki kaç satırın eski adresi barındırdığını verir:

    SELECT 'options' AS tablo, COUNT(*) FROM wp_options WHERE option_value LIKE '%eskisite.com%'
    UNION ALL SELECT 'posts', COUNT(*) FROM wp_posts WHERE post_content LIKE '%eskisite.com%'
    UNION ALL SELECT 'postmeta', COUNT(*) FROM wp_postmeta WHERE meta_value LIKE '%eskisite.com%'
    UNION ALL SELECT 'termmeta', COUNT(*) FROM wp_termmeta WHERE meta_value LIKE '%eskisite.com%'
    UNION ALL SELECT 'usermeta', COUNT(*) FROM wp_usermeta WHERE meta_value LIKE '%eskisite.com%';
    

    Bu sayılar hem işin büyüklüğünü hem de sonrasında doğrulama yapacağınız referansı verir. İşlem bittiğinde aynı sorguyu tekrar çalıştırıp sıfır beklersiniz — guid sütunu hariç, ki ona birazdan geleceğiz.

    Eski adresin tipik olarak saklandığı yerler ve her birinin riski şöyledir:

    Tablo / sütunNe saklarSerileştirilmiş miDüz SQL güvenli mi
    wp_options.option_valuesiteurl, home, tema ayarları, eklenti yapılandırmalarıÇoğu zaman evetHayır (yalnızca siteurl/home için evet)
    wp_posts.post_contentYazı ve sayfa gövdesi, Gutenberg bloklarıGenelde hayırGenelde evet
    wp_posts.guidYazının kalıcı kimliğiHayırHayır — dokunulmamalı
    wp_postmeta.meta_valueElementor, ACF, Divi, WooCommerce verisiSıklıkla evetKesinlikle hayır
    wp_termmeta.meta_valueKategori görselleri, taksonomi ayarlarıSıklıkla evetHayır
    wp_usermeta.meta_valueKullanıcı arayüz tercihleriSıklıkla evetHayır
    wp_comments.comment_contentYorum metinleriHayırEvet
    Eklenti tabloları (wp_wc_*, wp_yoast_*)Ürün arama tablosu, SEO verisiDeğişkenAraçla yapın

    Yöntem 1: WP-CLI search-replace (En Güvenli Yol)#

    SSH erişiminiz varsa tartışmasız doğru yöntem budur, çünkü serileştirilmiş veriyi doğru şekilde çözüp yeniden kurar ve önce hiçbir şeyi değiştirmeden ne yapacağını rapor eder. Önce kuru çalıştırma:

    wp search-replace 'https://eskisite.com' 'https://yenisite.com' --all-tables --dry-run --report-changed-only
    

    Bu komut hiçbir satırı değiştirmez; hangi tabloda kaç değişiklik yapacağını listeler. Çıktı şuna benzer:

    Table         Column        Replacements  Type
    wp_options    option_value  38            SQL
    wp_postmeta   meta_value    1204          PHP
    wp_posts      post_content  417           SQL
    Success: 1659 replacements to be made.
    

    Type sütunundaki PHP değeri, o satırın serileştirilmiş veri içerdiğini ve WP-CLI'ın onu PHP tarafında çözerek işleyeceğini gösterir — düz SQL replace'in tam olarak bozacağı satırlar bunlardır. Rapordaki sayılar makul görünüyorsa --dry-run bayrağını kaldırıp gerçek çalıştırmayı yapın:

    wp search-replace 'https://eskisite.com' 'https://yenisite.com' --all-tables --precise --skip-columns=guid --report-changed-only
    

    Bu satırdaki dört bayrağın her biri bir sebep taşır:

    • --all-tables: Varsayılan olarak WP-CLI yalnızca WordPress'in kendi tablolarını tarar. WooCommerce arama tablosu, form eklentisi kayıtları ve özel eklenti tabloları bu bayrak olmadan atlanır.
    • --precise: Değiştirme işlemini SQL yerine PHP tarafında yapar. Daha yavaştır ama serileştirilmiş veriyle çalışırken en güvenli seçenektir; çok dilli sitelerde ve karmaşık meta yapılarında bunu her zaman açık tutun.
    • --skip-columns=guid: guid sütununa dokunulmaz. Bu sütun bir adres değil, yazının kalıcı benzersiz kimliğidir; değiştirilirse RSS okuyucular ve bazı toplayıcılar mevcut tüm yazıları yeni içerik sanar. Adres olarak görünmesi bir isimlendirme kazasıdır.
    • --report-changed-only: Çıktıyı sadece değişen tablolara indirir, yüzlerce satırlık sıfır raporu okumaktan kurtarır.

    WP-CLI'ın diğer kullanımları ve kurulum tarafı için WP-CLI kullanımı yazısına bakabilirsiniz. Bir uyarı: search-replace komutu tabloları tarar, bu yüzden büyük sitelerde birkaç dakika sürebilir; SSH oturumunuz düşerse işlem yarım kalır. Bunu önlemek için komutu screen veya tmux içinde çalıştırın.

    Protokol ve www varyantlarını unutmayın#

    Tek bir replace çoğu zaman yetmez. Sitede geçmişte hem http hem https, hem www'lu hem www'suz adresler oluşmuşsa hepsini ayrı ayrı ele almanız gerekir. Doğru sıra en uzun eşleşmeden en kısaya doğrudur:

    wp search-replace 'https://www.eskisite.com' 'https://yenisite.com' --all-tables --precise --skip-columns=guid
    wp search-replace 'http://www.eskisite.com'  'https://yenisite.com' --all-tables --precise --skip-columns=guid
    wp search-replace 'https://eskisite.com'     'https://yenisite.com' --all-tables --precise --skip-columns=guid
    wp search-replace 'http://eskisite.com'      'https://yenisite.com' --all-tables --precise --skip-columns=guid
    

    Kısa varyantı önce çalıştırırsanız www.eskisite.com değeri www.yenisite.com hâline gelir ve ikinci komut artık onu bulamaz. Ayrıca sitede yalnızca yol içeren kayıtlar da olabilir: eski sunucudaki mutlak dosya yolu (/home/eskikullanici/public_html/...) bazı eklenti ayarlarında saklanır. Onun için ayrı bir replace gerekir:

    wp search-replace '/home/eskikullanici/public_html' '/home/yenikullanici/public_html' --all-tables --precise
    

    Yöntem 2: SSH Yoksa Eklenti ile Yapmak#

    Paylaşımlı hostingte SSH erişiminiz yoksa doğru yol, serileştirilmiş veriyi doğru işleyen bir arama-değiştirme eklentisi kullanmaktır. Bu eklentiler WP-CLI ile aynı mantıkla çalışır: veriyi çözer, değiştirir, uzunlukları yeniden hesaplar. Uygulama sırası şudur:

    1. Eklentiyi kurup etkinleştirin.
    2. Ara kutusuna eski adresi tam biçimde yazın (https://eskisite.com), Değiştir kutusuna yenisini.
    3. Tablo listesinden tüm tabloları seçin. Bazı eklentiler varsayılan olarak yalnızca birkaç tablo seçili gelir.
    4. "GUID sütununu değiştir" seçeneği varsa kapalı bırakın.
    5. "Kuru çalıştırma (dry run)" seçeneğini işaretleyip önce raporu alın.
    6. Rapordaki değişiklik sayısı mantıklıysa kuru çalıştırmayı kapatıp gerçek işlemi yapın.
    7. İşlem bittikten sonra eklentiyi kaldırın. Bu tür bir aracı sitede sürekli kurulu tutmak, yönetici hesabı ele geçirildiğinde tüm veritabanını tek tıkla değiştirilebilir hâle getirir.

    Eklenti yöntemi büyük veritabanlarında zaman aşımına takılabilir. Maximum execution time hatası alırsanız işlemi tablo tablo bölerek yapın — önce wp_options, sonra wp_postmeta, sonra wp_posts — ya da hosting panelinden PHP çalışma süresi sınırını geçici olarak yükseltin.

    Yöntem 3: Sadece Güvenli Yerlerde Dar Kapsamlı SQL#

    SQL'i tamamen yasaklamak da doğru değil; belirli iki alan için gerçekten güvenli ve bazen tek çıkış yoludur. Site hiç açılmıyorsa, panele giremiyorsanız ve eklenti kuramıyorsanız siteurl ile home değerlerini phpMyAdmin'den elle düzeltmek siteyi ayağa kaldırır:

    UPDATE wp_options SET option_value = 'https://yenisite.com' WHERE option_name = 'siteurl';
    UPDATE wp_options SET option_value = 'https://yenisite.com' WHERE option_name = 'home';
    

    Bu iki satır serileştirilmiş değil, düz metindir; risk taşımaz. Aynı şekilde yazı gövdeleri ve yorumlar da genelde düz metindir:

    UPDATE wp_posts SET post_content = REPLACE(post_content, 'https://eskisite.com', 'https://yenisite.com');
    UPDATE wp_comments SET comment_content = REPLACE(comment_content, 'https://eskisite.com', 'https://yenisite.com');
    

    Ancak burada bile bir uyarı var: Gutenberg blok yorumları içinde JSON saklar ve bazı bloklar (özellikle galeri ve sorgu blokları) uzunluk bilgisi taşıyan yapılar içerebilir. Sitede sayfa kurucu kullanılıyorsa bu iki komutu da çalıştırmayın, doğrudan Yöntem 1 veya 2'ye gidin.

    Asla düz SQL uygulanmayacak sütunlar şunlardır ve bu listeyi ezberlemekte fayda var: wp_postmeta.meta_value, wp_termmeta.meta_value, wp_usermeta.meta_value, wp_options.option_value (siteurl/home dışındaki satırlar) ve tema/eklenti ayarlarını tutan tüm özel tablolar.

    Panelde adresi yanlış değiştirip siteye tamamen erişimi kaybettiyseniz, o senaryonun kurtarma adımları WordPress site adresi yanlış değiştirildi yazısında ayrıca ele alınıyor.

    WordPress Dışındaki Sistemlerde Durum#

    Serileştirme sorunu WordPress'e özgü olsa da, eski adresin veritabanında kalması her sistemde geçerlidir. Kısaca:

    • OpenCart: Adres veritabanında değil, config.php ve admin/config.php dosyalarında HTTP_SERVER, HTTPS_SERVER, DIR_* sabitleri olarak durur. Ayrıca oc_setting tablosunda config_url benzeri kayıtlar bulunur. Ürün açıklamalarına gömülü mutlak görsel adresleri için oc_product_description tablosunda düz replace güvenlidir.
    • PrestaShop: ps_shop_url tablosundaki domain ve domain_ssl sütunları güncellenir; ardından var/cache klasörü temizlenir.
    • Laravel ve modern PHP çatıları: Adres genelde .env dosyasındaki APP_URL değerindedir; veritabanına yalnızca kullanıcı içeriğine gömülmüşse girer. Yapılandırma önbelleği varsa temizlenmelidir.
    • Statik HTML siteler: Veritabanı yoktur; mutlak adresler doğrudan HTML içindedir ve metin editörüyle toplu değiştirilebilir.

    Değişiklikten Sonra Kontrol Listesi#

    Replace bitti diye iş bitmez. Sırayla şunları doğrulayın:

    1. Envanter sorgusunu tekrar çalıştırın; guid dışında sıfır beklenir.
    2. Nesne önbelleğini ve sayfa önbelleğini temizleyin (wp cache flush), CDN kullanıyorsanız oradan da purge yapın.
    3. Kalıcı bağlantıları yeniden kaydedin (Ayarlar → Kalıcı Bağlantılar → Kaydet).
    4. Sayfa kurucu ile yapılmış en karmaşık sayfayı açın; boş geliyorsa serileştirme bozulmuş demektir, yedeğe dönün.
    5. Bir ürün sayfasını, bir formu ve bir galeriyi tek tek test edin.
    6. Tarayıcı konsolunda Mixed Content uyarısı kalıp kalmadığına bakın; kaldıysa http:// varyantı için replace yapılmamıştır. Konu tamamen mixed content hatası yazısında anlatılıyor.
    7. Site hâlâ görsel olarak bozuksa sorun URL'de olmayabilir; taşıma sonrası site bozuk görünüyor yazısındaki izin ve büyük-küçük harf başlıklarına bakın.

    Sık Yapılan Beş Hata#

    Yedek almadan başlamak. En pahalı hata budur ve geri dönüşü yoktur; bozulan serileştirilmiş veri ters replace ile düzelmez.

    guid sütununu da değiştirmek. Adres gibi görünür, adres değildir. Değiştirildiğinde besleme okuyucular tüm arşivi yeni içerik olarak yeniden yayımlar.

    Kısa varyantı önce çalıştırmak. eskisite.com yerine www.eskisite.com ile başlanmalıdır; aksi hâlde www varyantı bulunamaz hâle gelir.

    Yalnızca WordPress tablolarını taramak. --all-tables verilmediğinde WooCommerce, form ve SEO eklentilerinin kendi tabloları atlanır; site günler sonra beklenmedik yerlerde eski adrese yönlenir.

    Adresi protokolsüz aramak. Yalnızca eskisite.com aratmak, [email protected] gibi e-posta adreslerini ve metin içindeki marka bahislerini de değiştirir. Her zaman protokolle birlikte tam adres kullanın.

    Taşımanın tamamını uçtan uca yapıyorsanız, bu adımın diğer aşamalarla ilişkisini görmek için WordPress manuel site taşıma yazısını izlemek en verimlisidir.

    Sıkça Sorulan Sorular#

    Veritabanında URL değiştirmek için hangi yöntem en güvenlidir#

    En güvenli yöntem WP-CLI'ın search-replace komutudur, çünkü serileştirilmiş veriyi PHP tarafında çözüp uzunluk bilgilerini yeniden hesaplayarak yazar. SSH erişiminiz yoksa aynı mantıkla çalışan bir arama-değiştirme eklentisi ikinci en iyi seçenektir. Düz SQL yalnızca siteurl, home gibi düz metin alanlarında güvenlidir. Hangi yöntemi seçerseniz seçin, işlemden önce mutlaka veritabanı yedeği alın.

    UPDATE REPLACE komutu neden siteyi çökertiyor#

    Çünkü serileştirilmiş veri, içindeki her metnin karakter sayısını kendi içinde saklar. Adres uzunluğu değiştiğinde bu sayı güncellenmez ve PHP veriyi çözemez, false döner. Sonuç, sayfa kurucu ile yapılmış sayfaların boş açılması, özel alanların kaybolması ve ürün varyasyonlarının görünmemesi olur. En tehlikeli yanı, hiçbir hata mesajı üretmeden içeriğin sessizce yok olmasıdır.

    guid sütununu neden değiştirmemeliyim#

    Çünkü guid bir adres değil, yazının kalıcı benzersiz kimliğidir; adres biçiminde yazılması yalnızca tarihsel bir tercihtir. Bu değeri değiştirdiğinizde RSS okuyucuları ve içerik toplayıcıları sitedeki tüm eski yazıları yeni yayımlanmış sanır ve aboneler toplu bildirim alır. WP-CLI'da --skip-columns=guid, eklentilerde ise ilgili kutuyu kapalı bırakarak bu sütunu koruyun.

    Değişiklikten sonra bazı sayfalar hâlâ eski adrese gidiyor#

    Bu genellikle üç sebepten olur: eski adresin http ya da www varyantı için ayrı bir replace yapılmamıştır, --all-tables verilmediği için eklenti tabloları atlanmıştır ya da bir önbellek katmanı eski çıktıyı sunmaya devam etmektedir. Envanter sorgusunu tekrar çalıştırıp hangi tabloda kaldığını bulun. Sayı sıfırsa sorun veritabanında değil, sayfa veya CDN önbelleğindedir.

    İşlem sırasında zaman aşımı hatası alıyorum#

    Bu, büyük veritabanlarında eklenti yöntemi kullanıldığında sık görülür ve PHP'nin çalışma süresi sınırına takılmaktan kaynaklanır. Çözüm, işlemi tablo tablo bölmek veya PHP çalışma süresi sınırını geçici olarak yükseltmektir. SSH erişiminiz varsa WP-CLI komut satırında çalıştığı için bu sınıra genellikle takılmaz; ayrıca oturum düşmesine karşı komutu screen içinde başlatmak iyi bir alışkanlıktır.

    Taşımadan sonra hiç URL değiştirmesem ne olur#

    Alan adı değişmediyse ve yalnızca sunucu değiştiyse hiçbir şey olmaz, çünkü veritabanındaki adresler zaten doğrudur. Ancak alan adı değiştiyse, geçici bir test adresi kullandıysanız ya da HTTP'den HTTPS'e geçtiyseniz site eski adresten kaynak çekmeye çalışır; görseller gelmez, linkler yanlış yönlenir ve HTTPS sayfada karışık içerik uyarısı çıkar. Bu durumda değişiklik isteğe bağlı değil, zorunludur.

    Kuru çalıştırma raporundaki sayılar çok yüksek görünüyor, normal mi#

    Genelde normaldir. Orta ölçekli bir WordPress sitesinde binlerce eşleşme çıkması beklenir, çünkü her görsel boyutu, her galeri kaydı ve her sayfa kurucu bileşeni ayrı bir satırda tam adres saklar. Endişelenmeniz gereken durum, rapordaki tablolar arasında hiç tanımadığınız bir sistem tablosunun bulunmasıdır. Sayılar yerine hangi tabloların etkilendiğine bakın; wp_postmeta ve wp_options başı çekiyorsa tablo beklenen şekildedir.

    Çoklu site (multisite) kurulumunda nasıl yapılır#

    Multisite'ta her alt sitenin kendi tablo öneki vardır (wp_2_options, wp_3_posts gibi) ve ayrıca ağ genelinde wp_blogs ile wp_site tabloları bulunur. WP-CLI'da --network ve --url parametrelerini kullanarak her siteyi ayrı ayrı işlemek, tek seferde ağın tamamını değiştirmeye çalışmaktan çok daha güvenlidir. wp_blogs tablosundaki domain sütunu ise elle güncellenmelidir, aksi hâlde alt siteler eski alan adına yönlenmeye devam eder.

    Kapanış#

    Veritabanındaki eski adresleri değiştirmek, taşımanın en kısa ama en riskli adımıdır. Riski yaratan şey işin zorluğu değil, yanlış aracın hiç hata vermemesidir: düz bir SQL replace çalışır, "Sorgu başarılı" der ve sitenin en değerli içeriğini sessizce kırar. Doğru sıra her zaman aynıdır — yedek al, envanter çıkar, kuru çalıştır, uzun varyanttan kısaya doğru değiştir, guid'e dokunma, sonra tek tek doğrula.

    Bu işi kendiniz yapmak istemiyorsanız site taşıma hizmeti dosya, veritabanı ve adres güncellemesini birlikte yürütür; işlem öncesi geri dönülebilir bir kopya için yedekleme çözümlerini devreye almak da aynı derecede önemlidir. Taşıdığınız site WordPress ise, WP-CLI ve SSH erişiminin hazır geldiği WordPress hosting paketleri bu yazıdaki en güvenli yöntemi doğrudan kullanılabilir kılar; büyük veritabanlarında zaman aşımı sorunuyla hiç uğraşmak istemiyorsanız kaynak sınırlarını kendiniz belirleyebildiğiniz VDS sunucu tarafı daha rahat bir çalışma alanı verir.

    veritabanısite taşımawordpress

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.