MariaDB'de bir hesaba yetki GRANT yetki ON seviye TO hesap; deyimiyle verilir, REVOKE yetki ON seviye FROM hesap; deyimiyle geri alınır. Örneğin bir web uygulamasının hesabına yalnızca kendi veritabanında okuma ve yazma izni vermek için GRANT SELECT, INSERT, UPDATE, DELETE ON uygulama.* TO 'app'@'localhost'; yazmanız yeterlidir. Hesabın o anda hangi yetkilere sahip olduğunu SHOW GRANTS FOR 'app'@'localhost'; ile görürsünüz.
Bu yazı yetki seviyelerini (genel, veritabanı, tablo, sütun, rutin), en sık kullanılan yetkileri, WITH GRANT OPTION, TO PUBLIC, yetki eşleşmesinin az bilinen kurallarını ve REVOKE ile ilgili tuzakları MariaDB Server belgelerine göre anlatıyor. Hesap açmayı CREATE USER yazısında, yetkileri gruplamayı rol yazısında bulabilirsiniz. Serinin geri kalanı için MariaDB öğrenme rehberi sayfasına göz atın.
GRANT deyiminin üç biçimi
Belgelere göre GRANT üç ana biçimde kullanılır: yetki vermek, bir hesaba başka bir hesap adına işlem yapma (PROXY) izni vermek ve bir rolü hesaba atamak. Bu yazının konusu birinci biçimdir; rol atama rol yazısında işleniyor. Yetki verme biçiminin iskeleti şöyledir:
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO account_or_role [, account_or_role] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH grant_option_list]GRANT kullanabilmek için GRANT OPTION yetkisine ve vermek istediğiniz yetkilerin kendisine sahip olmanız gerekir. Kendinizde olmayan bir yetkiyi başkasına veremezsiniz. Aynı deyimde virgülle birden fazla yetki ve birden fazla hesap yazılabilir. REQUIRE kısmı hesabın TLS ile bağlanmasını zorunlu kılmak içindir ve TLS yazısında anlatılıyor; WITH kısmına ise GRANT OPTION ya da kaynak sınırları yazılır.
Yetki seviyeleri

Yetkiler farklı kapsamlarda verilebilir ve her kapsam ayrı bir sistem tablosunda saklanır. Bazı yetkiler yalnızca belirli seviyelerde anlamlıdır; örneğin SHUTDOWN ya da PROCESS yalnızca genel seviyede verilir.
| Seviye | ON yazımı | Saklandığı tablo |
|---|---|---|
| Genel (global) | *.* | mysql.global_priv |
| Veritabanı | db_adi.* (ya da geçerli veritabanı için *) | mysql.db |
| Tablo | db_adi.tablo_adi (ya da tablo_adi) | mysql.tables_priv |
| Sütun | Tablo seviyesi + yetkiden sonra sütun listesi | mysql.columns_priv |
| Fonksiyon | FUNCTION db_adi.rutin_adi | mysql.procs_priv |
| Prosedür | PROCEDURE db_adi.rutin_adi | mysql.procs_priv |
Veritabanı seviyesinde verilen tablo ve fonksiyon yetkileri, o veritabanında daha sonra oluşturulacak nesneleri de kapsar. Genel seviyede verilen yetkiler de aynı şekilde sonradan açılacak tüm veritabanlarına uygulanır. Belgelerin vurguladığı bir ayrıntı: genel yetkiler hemen etkili olmaz, yalnızca GRANT çalıştıktan sonra açılan bağlantılara uygulanır. Bir kullanıcıya genel yetki verdiyseniz yeniden bağlanmasını isteyin.
En sık kullanılan yetkiler
Yetki listesi uzundur; günlük işlerde çoğunlukla aşağıdakiler kullanılır. Tam liste ve her yetkinin açıklaması resmî GRANT sayfasında yer alıyor.
| Yetki | Seviye | Ne sağlar |
|---|---|---|
| SELECT | Tablo / sütun | Satırları okumak |
| INSERT | Tablo / sütun | Satır eklemek |
| UPDATE | Tablo / sütun | Satır güncellemek; WHERE için SELECT de gerekir |
| DELETE | Tablo | Satır silmek |
| CREATE | Veritabanı / tablo | Veritabanı ya da tablo oluşturmak |
| DROP | Veritabanı / tablo | Silmek; TRUNCATE TABLE için de gerekir |
| ALTER | Tablo | Tablo yapısını değiştirmek |
| INDEX | Tablo | CREATE INDEX ile index eklemek |
| CREATE VIEW / SHOW VIEW | Tablo | View oluşturmak / tanımını görmek |
| TRIGGER | Tablo | Trigger oluşturmak, silmek, tanımını görmek |
| EXECUTE | Fonksiyon / prosedür | Saklı rutini çalıştırmak |
| CREATE ROUTINE / ALTER ROUTINE | Veritabanı / rutin | Saklı rutin oluşturmak / değiştirmek |
| EVENT | Veritabanı | Zamanlanmış olay oluşturmak ve değiştirmek |
| LOCK TABLES | Veritabanı | LOCK TABLES; ayrıca SELECT gerekir |
| FILE | Genel | LOAD DATA INFILE, LOAD_FILE() ile sunucu dosyalarını okumak / yazmak |
| PROCESS | Genel | Tüm iş parçacıklarını SHOW PROCESSLIST ile görmek |
| RELOAD | Genel | FLUSH deyimlerini çalıştırmak |
| SHUTDOWN | Genel | Sunucuyu kapatmak |
Belgelerdeki birkaç ayrıntı sık karıştırılır. INDEX yetkisi olmadan da CREATE TABLE içinde index tanımlanabilir (CREATE yetkiniz varsa) ya da ALTER TABLE ile index eklenebilir (ALTER yetkiniz varsa). REFERENCES yetkisi listede bulunur ama belgelerde kullanılmadığı belirtilir. FILE yetkisi sunucunun dosya sistemine erişim açtığı için uygulama hesaplarına verilmemelidir; dosya içe aktarma LOAD DATA yazısında ele alınıyor.
SUPER yetkisinin bölünmesi
Eskiden birçok yönetim işi tek bir SUPER yetkisine bağlıydı. Belgelere göre bu yetki daha ince parçalara ayrılmıştır: SET USER, FEDERATED ADMIN, CONNECTION ADMIN, REPLICATION SLAVE ADMIN, BINLOG ADMIN, BINLOG REPLAY, REPLICA MONITOR, BINLOG MONITOR, REPLICATION MASTER ADMIN ve READ_ONLY ADMIN. MariaDB 11.0'dan itibaren bunlar artık SUPER'ın parçası değildir ve ayrı ayrı verilmeleri gerekir. Örneğin read_only açıkken yazabilmek için READ_ONLY ADMIN gerekir; bu yetkiyi kimseye vermeyerek bir replikada hiç kimsenin geçici olmayan tabloları değiştirememesini sağlayabilirsiniz. Replikasyon hesapları için gereken REPLICATION SLAVE yetkisi replikasyon yazısında kullanılıyor.
USAGE, ALL PRIVILEGES ve GRANT OPTION

USAGE gerçekte hiçbir yetki vermez. Yeni açılmış bir hesabın SHOW GRANTS çıktısında genel USAGE görünmesinin nedeni budur. GRANT USAGE ile hesabın yetkilerini değiştirmeden yalnızca MAX_USER_CONNECTIONS gibi seçenekleri ayarlayabilirsiniz.
ALL PRIVILEGES (kısaca ALL) yalnızca yazdığınız seviyedeki tüm yetkileri verir. Bir tabloya ALL vermek veritabanı ya da genel seviyede bir şey vermez. Ayrıca ALL PRIVILEGES özel GRANT OPTION yetkisini kapsamaz.
WITH GRANT OPTION, hesabın o seviyede sahip olduğu yetkileri başkalarına verebilmesini sağlar. Sütun seviyesinde verilemez; sütun yetkisiyle birlikte yazılırsa tüm tablo için verilir. Belgelerde root benzeri bir yönetici hesabı şöyle oluşturulur:
CREATE USER 'alexander'@'localhost';
GRANT ALL PRIVILEGES ON *.* TO 'alexander'@'localhost' WITH GRANT OPTION;Uygulamaya göre yetki vermek: küçük bir örnek
Tipik bir senaryo düşünelim: magaza veritabanını kullanan bir web uygulaması, rapor almak için ayrı bir okuma hesabı ve şema değişikliklerini yapan bir bakım hesabı. Aşağıdaki deyimler belgelerdeki sözdizimine göre yazıldı; hesap adları örnek amaçlıdır.
CREATE USER 'magaza_app'@'localhost' IDENTIFIED BY 'guclu-bir-parola';
GRANT SELECT, INSERT, UPDATE, DELETE ON magaza.* TO 'magaza_app'@'localhost';
CREATE USER 'rapor'@'10.0.0.%' IDENTIFIED BY 'baska-bir-parola';
GRANT SELECT ON magaza.* TO 'rapor'@'10.0.0.%';
CREATE USER 'bakim'@'localhost' IDENTIFIED BY 'ucuncu-parola';
GRANT ALL PRIVILEGES ON magaza.* TO 'bakim'@'localhost';Uygulama hesabı tablo oluşturamaz ya da silemez; bir SQL injection açığı olsa bile saldırganın yapabilecekleri bu hesabın yetkileriyle sınırlı kalır. Bakım hesabının ALL yetkisi ise yalnızca magaza veritabanını kapsar, diğer veritabanlarına ya da genel yönetim işlerine uzanmaz.
Sütun ve rutin yetkileri
Hassas sütunları gizlemek için sütun seviyesinde yetki verebilirsiniz. Belgelerdeki örnek, kullanıcının çalışanların adını ve pozisyonunu görmesine izin verir ama maaş gibi diğer sütunlara erişimini kapatır. Sütun seviyesinde SELECT yetkisi olmayan sütunlar WHERE, ON, GROUP BY ve ORDER BY içinde de kullanılamaz.
GRANT SELECT (name, position) ON Employee TO 'jeffrey'@'localhost';Saklı prosedür çalıştırma izni EXECUTE ile verilir. Belgeler, bir prosedürü çağırma yetkisinin normalde yapamayacağınız işlemlere (örneğin bir tabloya satır eklemeye) kapı açabileceğini hatırlatır. Saklı rutinlerin güvenlik bağlamı stored procedure yazısında anlatılıyor.
GRANT EXECUTE ON PROCEDURE mysql.create_db TO maintainer;GRANT ile örtük hesap oluşturma
GRANT, hesap yoksa onu örtük olarak da oluşturabilir; bunun için CREATE USER için gereken yetkilere sahip olmanız gerekir. Ancak sql_mode içinde NO_AUTO_CREATE_USER açıksa (belgelere göre varsayılan budur) kimlik doğrulama bilgisi verilmeden yeni hesap oluşturulamaz. Belgelerdeki örnekte boş parolayla denenen GRANT hata verir:
GRANT USAGE ON *.* TO 'user123'@'%' IDENTIFIED BY '';ERROR 1133 (28000): Can't find any matching row in the user tableBu davranış yazım hatalarına karşı da bir korumadır: hesap adını yanlış yazdığınızda yanlışlıkla yeni ve parolasız bir hesap açılmaz. Önerilen yol hesabı önce CREATE USER ile açmak, sonra yetki vermektir.
Yetki eşleşmesinin az bilinen kuralı
Bağlantı sırasında MariaDB tek bir hesap seçer: kullanıcı adı birebir eşleşen ve host deseni en özgül olan hesap. Bu hesap kimliğinizi ve CURRENT_USER() değerini belirler; genel yetkileriniz de yalnızca bu hesabın mysql.global_priv satırından gelir. Veritabanı, tablo, sütun ve rutin yetkileri ise ayrı ayrı aranır: her seviyede, bağlanan hesabın kullanıcı adı ve istemcinin gerçekten bağlandığı host ile en özgül kayıt bulunur ve tek başına uygulanır. Daha genel host desenine ait kayıtlar buna eklenmez.
Belgelerdeki örnekte foo@localhost ve foo@'%' diye iki hesap var ve db veritabanında SELECT yalnızca foo@'%' hesabına verilmiş:
CREATE USER foo@localhost;
CREATE USER foo@'%';
CREATE DATABASE db;
CREATE TABLE db.t1 (a INT);
INSERT INTO db.t1 VALUES (1),(2),(3);
GRANT SELECT ON db.* TO foo@'%';Yerelden bağlanan foo, foo@localhost olarak doğrulanır; ama foo@localhost hesabının veritabanı seviyesinde hiç kaydı olmadığı için foo@'%' kaydı eşleşir ve SELECT başarılı olur. Şimdi foo@localhost hesabına aynı veritabanında herhangi bir yetki verelim:
GRANT INSERT ON db.* TO foo@localhost;
SELECT * FROM db.t1;ERROR 1142 (42000): SELECT command denied to user 'foo'@'localhost' for table `db`.`t1`Artık daha özgül bir kayıt olduğu için o kayıt tek başına geçerlidir ve SELECT reddedilir. Belgeler ayrıca SHOW GRANTS çıktısının yalnızca doğrulanan hesaba kayıtlı yetkileri gösterdiğini, başka bir hesabın kaydından gelen yetkileri listelemediğini belirtir. Yani SHOW GRANTS bazen bağlantının gerçekte sahip olduğundan daha az yetki gösterebilir.
Veritabanı adında joker karakter
GRANT içinde veritabanı adında % ve _ kullanılabilir. Birden çok desen eşleşirse daha az veritabanıyla eşleşebilen, yani daha özgül desen uygulanır ve yalnızca ilk eşleşen kayıt geçerli olur. Belgelerdeki örnekte `%test`.* deseni `j-%`.* deseninden daha özgül sayılır; bu yüzden j-test veritabanında yalnızca SELECT geçerli olur, INSERT verilmez.
CREATE USER 'jtest'@localhost IDENTIFIED BY 'jtest';
GRANT SELECT ON `%test`.* TO 'jtest'@localhost;
GRANT SELECT, INSERT, DELETE ON `j-%`.* TO 'jtest'@localhost;TO PUBLIC: herkese birden yetki
MariaDB 10.11'den itibaren GRANT ... TO PUBLIC ile sunucuya erişimi olan tüm kullanıcılara, sonradan oluşturulacaklar da dahil, yetki verilebilir. Kullanıcı SHOW GRANTS çalıştırdığında PUBLIC'ten gelen yetkileri de görür; yalnızca PUBLIC yetkilerini görmek için SHOW GRANTS FOR PUBLIC kullanılır. Belgelerdeki çıktı şöyledir:
GRANT ALL ON dev_db.* TO PUBLIC;
SHOW GRANTS FOR PUBLIC;
+------------------------------------------------+
| Grants for PUBLIC |
+------------------------------------------------+
| GRANT ALL PRIVILEGES ON `dev_db`.* TO `PUBLIC` |
+------------------------------------------------+SHOW GRANTS ile yetkileri görmek
SHOW GRANTS FOR hesap, o hesabın yetkilerini yeniden oluşturmak için gereken GRANT deyimlerini listeler. Yalnızca kullanıcı adını yazarsanız host '%' kabul edilir. Kendi yetkilerinizi görmek için SHOW GRANTS, SHOW GRANTS FOR CURRENT_USER ya da SHOW GRANTS FOR CURRENT_USER() yazabilirsiniz. Belgelerdeki root çıktısı şöyledir:
SHOW GRANTS FOR 'root'@'localhost';
+---------------------------------------------------------------------+
| Grants for root@localhost |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+Bu deyim SQL SECURITY DEFINER ile tanımlanmış bir saklı prosedür içinde çalışırsa çağıranın değil, tanımlayanın yetkilerini gösterir. Hesabın parolası, kilidi ve kaynak sınırları gibi yetki dışı bilgileri ise SHOW CREATE USER gösterir.
REVOKE ile yetkiyi geri almak
REVOKE, GRANT ile aynı seviye ve yetki adlarını kullanır. İlk biçim belirli bir seviyedeki yetkiyi alır ve ON yan cümlesi zorunludur:
REVOKE SUPER ON *.* FROM 'myuser'@'localhost';
REVOKE ALL ON *.* FROM 'myuser'@'localhost';Burada sık yapılan bir yanılgı var: REVOKE ALL ON *.* yalnızca genel seviyedeki yetkileri alır; veritabanı ya da tablo seviyesinde verilmiş yetkiler kalabilir. Tüm seviyelerdeki yetkileri ve GRANT OPTION'ı bir seferde almak için ikinci biçim tercih edilir. Bu biçimde ON *.* yazılmaz; yazılırsa hata verir:
REVOKE ALL, GRANT OPTION FROM 'myuser'@'localhost';Her iki durumda da hesap USAGE yetkisini korur, yani sunucuya bağlanmaya devam edebilir. Hesabın bağlanmasını da engellemek istiyorsanız DROP USER ile silmeniz ya da ACCOUNT LOCK ile kilitlemeniz gerekir.
Sık yapılan hatalar

- Genel yetkinin hemen etkili olmasını beklemek: Genel yetkiler yalnızca yeni bağlantılara uygulanır.
- Uygulama hesabına *.* üzerinde ALL vermek: Uygulamanın ihtiyacı genellikle tek bir veritabanındaki
SELECT,INSERT,UPDATE,DELETEyetkileridir. - ALL PRIVILEGES'ın GRANT OPTION'ı kapsadığını sanmak: Kapsamaz; gerekiyorsa
WITH GRANT OPTIONayrıca yazılır. - REVOKE ALL ON *.* ile her şeyin alındığını sanmak: Alt seviyedeki yetkiler kalabilir;
REVOKE ALL, GRANT OPTION FROM ...kullanın. - Yetkiyi yanlış host kısmına vermek:
'app'@'%'hesabına verilen yetki,'app'@'localhost'olarak doğrulanan bağlantıda o seviyede daha özgül bir kayıt varsa uygulanmaz. - Rol ve kullanıcıya aynı adı vermek: Belgelere göre çakışmada rol adı önceliklidir ve
GRANTyetkiyi kullanıcıya değil role verir. - FLUSH PRIVILEGES'ı gereksiz yere çalıştırmak:
GRANTveREVOKEsonrasında gerekmez; yalnızcamysqltablolarını elle değiştirdiğinizde gerekir.
Sık Sorulan Sorular
Bir kullanıcıya yalnızca tek bir veritabanında tam yetki nasıl verilir?
GRANT ALL PRIVILEGES ON veritabani.* TO 'kullanici'@'host'; yeterlidir. Bu yetki diğer veritabanlarını ve sunucu yönetimi yetkilerini kapsamaz; o veritabanında sonradan açılacak tabloları ise kapsar.
Yetkiyi verdim ama kullanıcı hâlâ erişemiyor, neden?
Önce yetkinin doğru hesaba (doğru host kısmıyla) verildiğini kontrol edin; bağlantıda SELECT CURRENT_USER(); hangi hesap olarak doğrulandığınızı gösterir. Genel yetkiyse kullanıcının yeniden bağlanması gerekir. Erişim hataları için sık hatalar yazısına bakabilirsiniz.
Aynı yetkileri birçok kullanıcıya vermenin kolay yolu var mı?
Evet, roller. Yetkileri bir role verip rolü kullanıcılara atarsınız; değişiklik tek yerden yapılır. Ayrıntılar MariaDB rolleri yazısında.
REVOKE sonrası kullanıcı neden hâlâ bağlanabiliyor?
Çünkü REVOKE hesabı silmez; hesap USAGE ile bağlanmaya devam eder. Bağlantıyı engellemek için hesabı silin ya da kilitleyin.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: MariaDB öğrenme rehberi · MariaDB CREATE USER · MariaDB rolleri · MariaDB TLS bağlantı · MariaDB replikasyon · SQL injection önleme · PHP PDO veritabanı bağlantısı