Есть какой-нибудь рабочий способ установить строку MySQL только для чтения? - PullRequest
2 голосов
/ 06 апреля 2019

Я прочитал все темы здесь и не нашел ни одного простого и рабочего решения моего вопроса. Так что я запускаю сайт на PHP-скрипте, который использует БД на 10.1.37-MariaDB.

У меня есть 1 таблица, в которой мне нужно установить только несколько строк (от 90 КБ) только для чтения. Больше не обновляется и не удаляется 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;

Получил только ошибки. Спасибо.

Ответы [ 3 ]

4 голосов
/ 06 апреля 2019

Вот потенциальное решение:

Создайте таблицу для хранения значений первичного ключа, которые вы хотите использовать только для чтения:

CREATE TABLE cb_aggregator_content_readonly (
  entry_id INT PRIMARY KEY
);
INSERT INTO cb_aggregator_content_readonly SET entry_id = 12345;

Создайте триггеры, чтобы выдать ошибку, если вы попытаетесьобновить или удалить строки с идентификаторами записей, которые должны быть доступны только для чтения:

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.

0 голосов
/ 06 апреля 2019

Вы можете изменить доступ пользователя, обращающегося к базе данных, чтобы иметь только права на чтение

, или вы можете создать другой столбец, называющий его "заблокированным", и добавить параметр в свои запросы, чтобы не обновлять строки сзначение в заблокированном.

Установите для заблокированного поля дату и время по умолчанию ноль.таким образом, вы можете выбрать значения, которые заблокированы и создать заказ по дате блокировки.Вы также можете добавить другое поле как locked_by и добавить идентификатор пользователя.

В качестве альтернативы, вы можете создать заблокированную таблицу и использовать объединения - если блокируемые данные не являются стандартными, я бы выбрал это

пример:

  UPDATE 
   date = NOW()
  FROM table
  WHERE id = 123 AND locked IS NULL
0 голосов
/ 06 апреля 2019

MySQL не имеет контроля доступа для каждой строки.Способ сделать это - сделать всю таблицу доступной только для чтения, но создать специального пользователя с правами на запись в нее.Затем напишите хранимую процедуру, которая обновляет таблицу, и сделайте ее владельцем этого пользователя.Хранимая процедура может проверить, entry_id = 12345 и не выполняет ли обновление.

SELECT ... FOR UPDATE не мешает записи строки, она просто блокирует ее на время транзакции.Другие транзакции будут просто заблокированы, пока транзакция не завершится, но тогда они смогут обновить строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...