Sürüm kontrol sistemleri ve özellikle Git, kod değişikliklerini izlemek, ekibinizle işbirliği yapmak ve kod tabanınızın kararlılığını sağlamak için temel araçlardır. Git öncelikle kaynak kodu için tasarlanmış olsa da sürüm kontrolü ve şema değişikliği yönetimi için MySQL veritabanlarıyla birlikte de kullanabilirsiniz.
Bu makalede, Git kancalarını kullanarak sürüm kontrolü için Git'i MySQL ile nasıl entegre edeceğimizi, bir kılavuz formatındaki belirli örneklerle keşfedeceğiz. Listelerde verilen tüm scriptler tamamen işlevsel ve eksiksizdir. Bunları test ortamınızda sırayla çoğaltabilirsiniz.
Öncelikle bir test veritabanı ve kullanıcı oluşturalım:
create database testdb_remote; create user 'user_remote'@'localhost' identified WITH mysql_native_password by 'remote123'; grant all on testdb_remote.* to 'user_remote'@'localhost';
Daha sonra uzak bir depo oluşturacağız. Bu herhangi bir uzak sunucudaki bir depo olabilir, ancak basitlik açısından onu yerel olarak oluşturacağız. Komutları yürütme kolaylığı için git bash kullanıyorum. Yerel makinemde zaten bir git klasörü var, bu yüzden onu kullanıyorum:
cd /c/git mkdir testdb.remote cd testdb.remote git init --bare
Ve uzak deponun kopyası olarak yerel bir depo oluşturun:
cd /c/git git clone /c/git/testdb.remote testdb.local cd testdb.local git ls-files
Depoda dosya yok; hadi bir tane oluşturalım ve değişikliklerimizi uzak depoya aktaralım:
echo "Test DB repo" > readme.md git status git add . git commit -m "1st commit" git push
Uzak havuzun içeriğini kontrol edelim:
cd /c/git/testdb.remote git ls-tree --full-tree -r HEAD
Uzak depoda örnekler içeren birkaç dosya içeren bir hooks klasörü vardır:
ls -1 /c/git/testdb.remote/hooks
Kancalar, belirli olaylar meydana geldiğinde çalıştırılan komut dosyalarıdır. Git'in istemci tarafı ve sunucu tarafı kancaları vardır. İstemci tarafı kancaları, taahhüt etme ve birleştirme gibi işlemlerle tetiklenir. Sunucu tarafı kancaları, itilmiş taahhütlerin alınması gibi ağ işlemlerinde çalışır. Kancalar burada ayrıntılı olarak açıklanmaktadır. Mantığı uygulamak için farklı seçenekler vardır; Alma sonrası sunucu tarafı kancasının kullanımına bir örnek vereceğim.
Hooks klasöründe "post-receive" adında bir dosya oluşturmamız gerekiyor, bu normal bir bash betiğidir:
#!/bin/sh while read oval nval ref do echo List of files changed in the commit: git diff --name-only $oval $nval done
Yukarıdaki komut dosyası, bir gönderim başarıyla tamamlandığında sunucuda yürütülecek ve değiştirilen dosyaların bir listesinin çıktısını verecektir. Readme.md dosyasına bir satır ekleyip değişiklikleri uzak depoya aktararak nasıl çalıştığını kontrol edelim:
cd /c/git/testdb.local echo "New line" >> readme.md git add . git commit -m "Line added" git push
Git Push komutunu çalıştırırken çıktının artık remote:
- bu, sunucuda yürütülen alma sonrası betiğinin çıktısıdır.
Temel değişikliklerden bahsetmişken, dosyalar eklenebilir, değiştirilebilir ve silinebilir. Bu değişikliklerin veritabanına nasıl uygulanacağı konusunda farklı yaklaşımlar kullanabilirsiniz:
İkinci seçeneği seçtiğinizi varsayalım, dolayısıyla eklenen veya değiştirilen dosyaları yürütmeniz gerekiyor. --diff-filter=AM
parametresini ekleyerek bu tür dosyaları burada açıklandığı gibi filtreleyebiliriz:
#!/bin/sh while read oval nval ref do echo List of files added or changed in the commit: git diff --name-only --diff-filter=AM $oval $nval done
Birkaç dosya ekleyin ve ayrıca readme.md dosyasını tekrar değiştirin:
echo "SELECT 1;" > test1.sql echo "SELECT 2;" > test2.sql echo "SELECT 3;" > test3.sql echo "New line 2" >> readme.md git add . git commit -m "New files" git push
Hook betiğinin çıktısı 4 dosya içerir:
test1.sql ve readme.md dosyalarını düzenliyoruz, test2.sql'i siliyoruz ve başka bir dosya ekliyoruz:
echo "SELECT 11;" > test1.sql echo "New line 2" >> readme.md rm test2.sql echo "SELECT 4;" > test4.sql git add . git commit -m "Modify, remove and add" git push
Yalnızca değiştirilen ve eklenen dosyalar görüntülenir:
Amacımız her başarılı gönderimden sonra SQL komut dosyalarını çalıştırmaktır, bu nedenle yalnızca bu türdeki dosyaları filtrelememiz gerekir; bizim durumumuzda hepsinin “.sql” uzantısına sahip olması şartını koyacağız. Filtrelemek için git diff
komutuna -- "*.sql"
parametresini ekleyin:
#!/bin/sh while read oval nval ref do echo List of files added or changed in the commit: git diff --name-only --diff-filter=AM $oval $nval -- "*.sql" done
Komut dosyalarını yürütmek için veritabanına da bağlanabilmemiz gerekir. Bunun için kimlik bilgileri oluşturup bağlantıyı test edeceğiz:
mysql_config_editor set --login-path=testdb_remote --host=localhost --port=3306 --user=user_remote --password mysql --login-path=testdb_remote --database=testdb_remote
“.sql” dosyalarında yineleme yapmak, her dosyayı yürütmek ve sonucu kontrol etmek için betiğimizi değiştirin. Ayrıca dosyaları gereken sırayla yürütmek için liste çıktısını da sıralamamız gerekir. Git show komutuyla SQL betiğinin içeriğini görüntülüyor ve bunu MySQL tarafından yürütülmek üzere kanaldan geçiriyoruz.
Değişken "$?" SQL betiği başarıyla yürütüldüyse 0 değerini, bir hata varsa başka bir değeri içerecektir:
#!/bin/sh while read oval nval ref do echo List of files added or changed in the commit: for file in $(git diff --name-only --diff-filter=AM $oval $nval -- "*.sql" | sort); do git show master:${file} | mysql --login-path=testdb_remote --database=testdb_remote echo "FILE: ${file} - result $?" done done
Bir test daha yapın - önceden oluşturulmuş tüm ".sql" dosyalarını silin ve aşağıdakiler için komut dosyaları oluşturun:
Ayrıca dosyaların istenen yürütme sırasını sağlamak için her dosya adına bir önek (1_, 2_ vb.) eklememiz gerekir:
rm *.sql echo "DB Initialization" >> readme.md echo " DROP TABLE IF EXISTS customers; CREATE TABLE customers ( id int UNSIGNED NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT NULL, PRIMARY KEY (id) ); " > 1_customers.sql echo " INSERT INTO customers (id, name) VALUES (1, 'John Doe'), (2, 'Jane Smith') AS new ON DUPLICATE KEY UPDATE customers.name = new.name; " > 2_customers_init.sql echo " DROP PROCEDURE IF EXISTS get_customer; DELIMITER $$ CREATE PROCEDURE get_customer(IN customer_id int UNSIGNED) BEGIN SELECT c.id, c.name FROM customers c WHERE c.id = customer_id; END $$ " > 3_get_customer.sql echo "SELECT FROM customers;" > 4_error_select.sql ls -1
Yani yürütülmesi gereken dört “.sql” dosyamız var:
Depoda değişiklikler yapıyoruz:
Ve git push
gerçekleştirildiğinde dosyaların sırayla yürütüldüğünü ve her dosyanın yürütme sonucunun (MySQL komut çıkış kodu) görüntülendiğini görüyoruz. “4_error_select.sql” dosyası bir sözdizimi hatası içeriyor, dolayısıyla yürütülmesinin sonucu 1'dir.
Son olarak veritabanımızda nelerin bulunduğunu kontrol edelim:
mysql --login-path=testdb_remote --database=testdb_remote show tables; call get_customer(1); call get_customer(2);
Gördüğünüz gibi tablo ve prosedür uzak veritabanında oluşturuldu. Prosedür başarıyla yürütülür ve verileri döndürür.
Kanca betiği çıktısının okunabilirliğini geliştirmek için MySQL CLI çıktısını bastırabilir veya onu bir günlük dosyasına yönlendirebilirsiniz. Ayrıca MySQL komutunun yürütülmesinin sonucunu analiz edebilir ve hook betiğine daha fazla mantık ekleyebilirsiniz.
Örneğin, bir test veritabanında SQL komut dosyalarını çalıştırabilir ve ardından üzerinde bazı testler çalıştırabilirsiniz ( burada anlattığım gibi). Testler test veritabanında başarıyla tamamlanırsa, üretim veritabanında SQL komut dosyalarını çalıştırın ve muhtemelen üzerinde bazı testler de çalıştırın.
Her adımın sonuçlarını analiz ederek herhangi bir konfigürasyonda işlem hatları oluşturabilirsiniz.
Elbette her yaklaşımın bir takım avantajları ve sınırlamaları vardır. İkinci yaklaşımda, komut dosyalarının yürütülme sırasını sağlamak gerekir çünkü örneğin bir tablo oluşturuluncaya kadar veri ekleyemeyiz. Ayrıca komut dosyalarını yeniden çalıştırabildiğinizden, yani oluşturulan nesnenin zaten veritabanında olduğu veya veritabanının zaten eklenecek verileri içerdiği durumlarda doğru şekilde çalışabildiğinizden emin olmanız gerekir.
Bir sürüm oluşturma sistemi kullanıldığında, geliştirme süreci biraz daha karmaşık hale gelir çünkü önceden belirlenmiş bir formattaki komut dosyalarındaki değişiklikleri ek olarak resmileştirmek gerekir. Ancak bir yükleme dosyası kullanarak bir miktar esneklik elde edebilirsiniz.
Açıklanan tekniğin temel avantajı, veritabanında sürüm oluşturmanın çok az çabayla uygulanmasının yanı sıra CI/CD işlem hatlarını uygulama yeteneğidir.
Bunun sizin için yararlı olup olmayacağını değerlendirmek için kendinize şu soruyu sorarak başlayabilirsiniz: Doğrudan üretimde ne sıklıkla kod yazıyorsunuz?