Кажется, вам нужно провести аудит данных, вместо того, чтобы видеть состояние данных на заданную дату, потому что было бы очень сложно восстановить состояние данных на основе вашего решения (правильно, если я неправильно в этом предположении). Я не думаю, что идея жизнеспособна, потому что даже для очень маленьких баз данных ваша таблица журналов будет огромной, и поэтому очень сложно правильно управлять.
Безболезненным решением для изменения данных аудита является создание таблицы истории для каждой таблицы, которую вы хотите отслеживать. эта таблица будет содержать запись для каждого запроса на вставку, обновление и удаление, выполняемую в каждой строке. структура таблицы истории будет такой же, как в таблице, которую она отслеживает, за исключением трех дополнительных столбцов, столбца для хранения выполняемой операции, столбца для хранения порядкового номера и столбца для хранения метки времени появления.
Следующие результаты запроса в SQL, необходимый для создания этих таблиц аудита, но он будет работать только если:
- ваши таблицы не начать с
_
(поскольку таблицы аудита будут делать);
- ваши таблицы имеют не комбинированный первичный ключ;
- в ваших таблицах нет столбцов с именем «Зарегистрировано», «Действие» и « ».
Запрос:
SET sql_mode = 'PIPES_AS_CONCAT';
SELECT
'CREATE TABLE __' || table_name || ' LIKE ' || table_name || ';\r\n' ||
'RENAME TABLE __' || table_name || ' TO _' || table_name || ';\r\n' ||
'ALTER TABLE _' || table_name || ' ADD Registrated TIMESTAMP NOT NULL FIRST;\r\n' ||
'ALTER TABLE _' || table_name || ' ADD Action TINYINT UNSIGNED NOT NULL FIRST;\r\n' ||
'ALTER TABLE _' || table_name || ' ADD Revision INT UNSIGNED NOT NULL FIRST;\r\n' ||
'ALTER TABLE _' || table_name || ' MODIFY ' || column_name || ' ' || UPPER(data_type) || IF(is_nullable = 'NO', ' NOT NULL', '') || ';\r\n' ||
'ALTER TABLE _' || table_name || ' DROP PRIMARY KEY;\r\n' ||
'ALTER TABLE _' || table_name || ' MODIFY COLUMN Revision INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY;\r\n' ||
'CREATE TRIGGER i' || table_name || ' AFTER INSERT ON ' || table_name || ' FOR EACH ROW INSERT INTO _' || table_name || ' SELECT NULL, 1, CURRENT_TIMESTAMP, ' || table_name || '.* FROM ' || table_name || ' WHERE ' || table_name || '.' || column_name || ' = NEW.' || column_name || ';\r\n' ||
'CREATE TRIGGER u' || table_name || ' AFTER UPDATE ON ' || table_name || ' FOR EACH ROW INSERT INTO _' || table_name || ' SELECT NULL, 2, CURRENT_TIMESTAMP, ' || table_name || '.* FROM ' || table_name || ' WHERE ' || table_name || '.' || column_name || ' = NEW.' || column_name || ';\r\n' ||
'CREATE TRIGGER d' || table_name || ' BEFORE DELETE ON ' || table_name || ' FOR EACH ROW INSERT INTO _' || table_name || ' SELECT NULL, 3, CURRENT_TIMESTAMP, ' || table_name || '.* FROM ' || table_name || ' WHERE ' || table_name || '.' || column_name || ' = OLD.' || column_name || ';'
FROM information_schema.tables
JOIN information_schema.table_constraints USING (table_schema, table_name)
JOIN information_schema.key_column_usage USING (table_schema, table_name, constraint_name)
JOIN information_schema.columns USING (table_schema, table_name, column_name)
WHERE
information_schema.tables.table_schema = (SELECT DATABASE()) AND
information_schema.table_constraints.constraint_type = 'PRIMARY KEY';
Примечание 1: внешние ключи ссылочное инструмент целостности, а не производительность инструмента. Хорошая модель базы данных будет работать лучше, но внешние ключи сами по себе приводят к большей обработке, не менее. CREATE TABLE LIKE
создаст пустую таблицу на основе определения исходной таблицы, включая любые атрибуты и индексы столбцов, но все остальное (например, данные, внешние ключи и т. Д.) Игнорируется. Целостность данных проверяется с помощью ограничений исходных таблиц, поэтому в таблице аудита нет усиления с помощью внешних ключей.