我在这里阅读了所有主题,并没有找到任何简单而有效的解决方案。所以我在php脚本上运行网站,该脚本在10.1.37-MariaDB上使用DB。
我有1个表,我需要只设置几行(从90k)只读。不再由php脚本更新或删除。
所有这些行都有唯一的entry_id
数字值,让我们说entry_id = 12345
。
在需要的表中我也有这个:
SELECT * FROM `cb_aggregator_content` ORDER BY `model_last_checked` ASC
试图添加:
SELECT * FROM `cb_aggregator_content` WHERE `entry_id`=12345 FOR UPDATE;
只有错误。谢谢。
这是一个潜在的解决方案:
创建一个表来存储您想要只读的主键值:
CREATE TABLE cb_aggregator_content_readonly (
entry_id INT PRIMARY KEY
);
INSERT INTO cb_aggregator_content_readonly SET entry_id = 12345;
如果您尝试更新或删除具有应该是只读的条目ID的行,则使触发器抛出错误:
DELIMITER ;;
CREATE TRIGGER no_upd_content BEFORE UPDATE ON cb_aggregator_content
FOR EACH ROW BEGIN
IF EXISTS(SELECT * FROM cb_aggregator_content_readonly WHERE entry_id = OLD.entry_id) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Please do not update entry ';
END IF;
END;;
CREATE TRIGGER no_del_content BEFORE DELETE ON cb_aggregator_content
FOR EACH ROW BEGIN
IF EXISTS(SELECT * FROM cb_aggregator_content_readonly WHERE entry_id = OLD.entry_id) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Please do not delete entry';
END IF;
END;;
DELIMITER ;
现在它应该阻止您更新或删除要保留的行:
mysql> delete from cb_aggregator_content where entry_id = 123;
Query OK, 1 row affected (0.02 sec)
mysql> delete from cb_aggregator_content where entry_id = 12345;
ERROR 1644 (45000): Please do not delete entry
如果要将更多的entry_id添加到要保留的那些中,只需将更多值插入到cb_aggregator_content_readonly表中。
MySQL没有每行访问控制。这样做的方法是使整个表只读,但创建一个具有写权限的特殊用户。然后编写一个更新表的存储过程,并使其由该用户拥有。存储过程可以检查entry_id = 12345
是否执行更新。
SELECT ... FOR UPDATE
不会阻止写行,它只是在事务持续期间锁定它。在事务完成之前,其他事务将被阻止,但随后他们将能够更新该行。
您可以将访问数据库的用户的访问权限更改为仅具有读取权限
或者您可以创建另一个列,将其称为“已锁定”,并在查询中添加一个参数,以便不更新任何具有锁定值的行。
将锁定字段设置为日期时间,默认值为null。这样,您可以选择已锁定的值并按锁定日期创建订单。您还可以将另一个字段添加为locked_by并附加用户ID。
或者,您可以创建一个锁定的表并使用连接 - 如果被锁定的数据不是标准的,我会选择这个
例如:
UPDATE
date = NOW()
FROM table
WHERE id = 123 AND locked IS NULL