我有一个MySQL表,该表存储一些我不想被任何人修改的数据。这意味着即使是数据库管理员也不应对其进行修改。有什么办法可以禁止包括数据库管理员在内的所有人修改表行?
我研究了这可以通过读/写锁部分实现。但是,仍将允许数据库管理员使用持有锁的用户名登录并加以利用。
我的目标是禁止所有人(包括数据库管理员)对表记录进行修改。我有什么办法可以使用MySQL实现此目标吗?
答案 0 :(得分:0)
管理员帐户始终完全控制服务器上的数据库。即使您对表具有revoke
权限,管理员也可以自己grant
权限。从常识的角度来看,这是有道理的。如果您确实想更新该表中的一行,该怎么办?核对整个服务器并重新插入?
您能做的最好的就是设置一些审核。如果可以对表进行备份,并定期将表与备份进行比较,则这是一种可能的方法。确保将备份存储在管理员无法访问的位置。当然,还有其他各种各样的潜在问题,所以这不是很理想。
如果您愿意切换到MariaDB,则可以利用System-Versioned Tables。我通常不会建议“尝试其他RDBMS”,但是MariaDB是MySQL的一个分支,因此过渡可能不会像切换到Oracle那样痛苦。
答案 1 :(得分:0)
如前所述,很难将事情限制为管理员,因为它几乎可以完成所有事情。
您可以创建一个阻止更新的触发器。我有2种解决方案,其中包含2种不同的触发器
示例1
此版本不会发送错误,但是对模式修改很明智。它还会影响“ 0行”
-- Table
CREATE TABLE not_updatable(
id int unsigned not null auto_increment primary key,
data varchar(50)
);
-- Trigger
DELIMITER $$
CREATE TRIGGER not_updatable_after_update
BEFORE UPDATE
ON not_updatable
FOR EACH ROW
BEGIN
SET NEW.id=OLD.id, NEW.data=OLD.data;
END$$
DELIMITER ;
结果:
mariadb@localhost:test> CREATE TABLE not_updatable(
id int unsigned not null auto_increment primary key,
data varchar(50)
);
Query OK, 0 rows affected
Time: 0.236s
mariadb@localhost:test> CREATE TRIGGER not_updatable_after_update
-> BEFORE UPDATE
-> ON not_updatable
-> FOR EACH ROW
-> BEGIN
-> SET NEW.id=OLD.id, NEW.data=OLD.data;
-> END;
Query OK, 0 rows affected
Time: 0.070s
mariadb@localhost:test> insert into not_updatable(data) values ('test 1'), ('test 2');
Query OK, 2 rows affected
Time: 0.043s
mariadb@localhost:test> select * from not_updatable;
+------+--------+
| id | data |
|------+--------|
| 1 | test 1 |
| 2 | test 2 |
+------+--------+
2 rows in set
Time: 0.004s
mariadb@localhost:test> update not_updatable set data = 'test 3' where id = 1;
Query OK, 0 rows affected
Time: 0.001s
mariadb@localhost:test> select * from not_updatable;
+------+--------+
| id | data |
|------+--------|
| 1 | test 1 |
| 2 | test 2 |
+------+--------+
2 rows in set
Time: 0.003s
示例2
这会引发错误,因此对于攻击者而言更可见
-- Table
CREATE TABLE not_updatable(
id int unsigned not null auto_increment primary key,
data varchar(50)
);
-- Trigger
DELIMITER $$
CREATE TRIGGER not_updatable_after_update
BEFORE UPDATE
ON not_updatable
FOR EACH ROW
BEGIN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Don''t try to cheat !';
END$$
DELIMITER ;
结果:
mariadb srumeu@localhost:test> drop trigger not_updatable_after_update;
Query OK, 0 rows affected
Time: 0.000s
mariadb srumeu@localhost:test> CREATE TRIGGER not_updatable_after_update
-> BEFORE UPDATE
-> ON not_updatable
-> FOR EACH ROW
-> BEGIN
-> SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Don''t try to cheat !';
-> END;
Query OK, 0 rows affected
Time: 0.078s
mariadb srumeu@localhost:test> update not_updatable set data = 'test 3' where id = 1;
(1644, "Don't try to cheat !")
mariadb srumeu@localhost:test> select * from not_updatable;
+------+--------+
| id | data |
|------+--------|
| 1 | test 1 |
| 2 | test 2 |
+------+--------+
2 rows in set
Time: 0.014s