create user 'test_user'@'localhost'; create role test_role1; create role test_role2; create role test_role3; grant test_role1 to test_user@localhost; grant test_role3 to test_user@localhost; grant test_role2 to test_role1; select user, host from mysql.user where user not like 'root'; User Host mariadb.sys localhost test_role1 test_role2 test_role3 test_user localhost select * from mysql.roles_mapping; Host User Role Admin_option test_role1 test_role2 N localhost root test_role1 Y localhost root test_role2 Y localhost root test_role3 Y localhost test_user test_role1 N localhost test_user test_role3 N create function mysql.test_func (s CHAR(20)) returns CHAR(50) DETERMINISTIC return concat('Test string: ',s); create procedure mysql.test_proc (OUT param1 INT) begin select COUNT(*) into param1 from mysql.roles_mapping; end| grant execute on function mysql.test_func to test_role2; grant execute on procedure mysql.test_proc to test_role2; grant execute on mysql.* to test_role3; show grants; Grants for test_user@localhost GRANT USAGE ON *.* TO `test_user`@`localhost` GRANT `test_role1` TO `test_user`@`localhost` GRANT `test_role3` TO `test_user`@`localhost` use mysql; ERROR 42000: Access denied for user 'test_user'@'localhost' to database 'mysql' select current_user(), current_role(); current_user() current_role() test_user@localhost NULL set role test_role1; select current_user(), current_role(); current_user() current_role() test_user@localhost test_role1 use mysql; call test_proc(@a); SELECT @a; @a 6 SELECT test_func('AABBCCDD'); test_func('AABBCCDD') Test string: AABBCCDD show grants; Grants for test_user@localhost GRANT EXECUTE ON FUNCTION `mysql`.`test_func` TO `test_role2` GRANT EXECUTE ON PROCEDURE `mysql`.`test_proc` TO `test_role2` GRANT USAGE ON *.* TO `test_role1` GRANT USAGE ON *.* TO `test_role2` GRANT USAGE ON *.* TO `test_user`@`localhost` GRANT `test_role1` TO `test_user`@`localhost` GRANT `test_role2` TO `test_role1` GRANT `test_role3` TO `test_user`@`localhost` set role none; select current_user(), current_role(); current_user() current_role() test_user@localhost NULL show grants; Grants for test_user@localhost GRANT USAGE ON *.* TO `test_user`@`localhost` GRANT `test_role1` TO `test_user`@`localhost` GRANT `test_role3` TO `test_user`@`localhost` call test_proc(@a); ERROR 42000: execute command denied to user 'test_user'@'localhost' for routine 'mysql.test_proc' SELECT test_func('AABBCCDD'); ERROR 42000: execute command denied to user 'test_user'@'localhost' for routine 'mysql.test_func' set role test_role3; select current_user(), current_role(); current_user() current_role() test_user@localhost test_role3 show grants; Grants for test_user@localhost GRANT EXECUTE ON `mysql`.* TO `test_role3` GRANT USAGE ON *.* TO `test_role3` GRANT USAGE ON *.* TO `test_user`@`localhost` GRANT `test_role1` TO `test_user`@`localhost` GRANT `test_role3` TO `test_user`@`localhost` call test_proc(@a); SELECT @a; @a 6 SELECT test_func('AABBCCDD'); test_func('AABBCCDD') Test string: AABBCCDD drop user 'test_user'@'localhost'; revoke execute on function mysql.test_func from test_role2; revoke execute on procedure mysql.test_proc from test_role2; revoke execute on mysql.* from test_role3; delete from mysql.user where user like'test_%'; delete from mysql.roles_mapping where Role like 'test%'; drop function mysql.test_func; drop procedure mysql.test_proc; flush privileges;