Сохраненная процедура не сохраняет записи в другой таблице, если есть исключение - PullRequest
0 голосов
/ 19 июня 2020

У меня 40 миллионов записей в пользовательской таблице и на несколько миллионов меньше записей в соответствующей пользовательской таблице. Теперь я хочу заархивировать более старые записи более чем на 3 месяца в архивной таблице.

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

Пожалуйста, помогите мне в том же.

Исходные таблицы и архивная таблица и хранимая процедура, как показано ниже:

CREATE TABLE `user` (
  `password` varchar(128) NOT NULL,
  `last_login` datetime DEFAULT NULL,
  `is_superuser` tinyint(1) NOT NULL,
  `subscriber_id` bigint(20) NOT NULL,
  `first_name` varchar(40) NOT NULL,
  `middle_name` varchar(40) NOT NULL,
  `last_name` varchar(40) NOT NULL,
  `email` varchar(254) DEFAULT NULL,
  `is_staff` tinyint(1) NOT NULL,
  `is_active` tinyint(1) NOT NULL,
  `date_joined` datetime NOT NULL,
  `favorites` varchar(1024) NOT NULL,
  `last_played` varchar(1024) NOT NULL,
  `alias` varchar(32) NOT NULL,
  PRIMARY KEY (`subscriber_id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `userprofile` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `profile_image` varchar(100) DEFAULT NULL,
  `alias` varchar(40) DEFAULT NULL,
  `dob` date DEFAULT NULL,
  `created_at` datetime DEFAULT current_timestamp(),
  `gender` varchar(1) DEFAULT NULL,
  `age_group` varchar(100) DEFAULT NULL,
  `location` varchar(300) DEFAULT NULL,
  `updated_at` datetime DEFAULT current_timestamp(),
  `subscriber_id` bigint(20) NOT NULL,
  `state` varchar(100) DEFAULT NULL,
  `city` varchar(100) DEFAULT NULL,
  `email` varchar(254) DEFAULT NULL,
  `dateOfBirth` datetime DEFAULT NULL,
  `gamer_name` varchar(40) DEFAULT NULL,
  `mobile_no` bigint(20) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=2009216 DEFAULT CHARSET=latin1;

CREATE TABLE `user_archived` (
  `password` varchar(128) NOT NULL,
  `last_login` datetime DEFAULT NULL,
  `is_superuser` tinyint(1) NOT NULL,
  `subscriber_id` bigint(20) NOT NULL,
  `first_name` varchar(40) NOT NULL,
  `middle_name` varchar(40) NOT NULL,
  `last_name` varchar(40) NOT NULL,
  `email` varchar(254) DEFAULT NULL,
  `is_staff` tinyint(1) NOT NULL,
  `is_active` tinyint(1) NOT NULL,
  `date_joined` datetime NOT NULL,
  `favorites` varchar(1024) NOT NULL,
  `last_played` varchar(1024) NOT NULL,
  `alias` varchar(32) NOT NULL,
  `archive_dt`  timestamp default CURRENT_TIMESTAMP,
  PRIMARY KEY (`subscriber_id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `userprofile_archived` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `profile_image` varchar(100) DEFAULT NULL,
  `alias` varchar(40) DEFAULT NULL,
  `dob` date DEFAULT NULL,
  `created_at` datetime DEFAULT current_timestamp(),
  `gender` varchar(1) DEFAULT NULL,
  `age_group` varchar(100) DEFAULT NULL,
  `location` varchar(300) DEFAULT NULL,
  `updated_at` datetime DEFAULT current_timestamp(),
  `subscriber_id` bigint(20) NOT NULL,
  `state` varchar(100) DEFAULT NULL,
  `city` varchar(100) DEFAULT NULL,
  `email` varchar(254) DEFAULT NULL,
  `dateOfBirth` datetime DEFAULT NULL,
  `gamer_name` varchar(40) DEFAULT NULL,
  `mobile_no` bigint(20) unsigned DEFAULT NULL,
  `archive_dt` timestamp DEFAULT now(),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

DELIMITER $$

DROP PROCEDURE IF EXISTS `debug_msg`$$
DROP PROCEDURE IF EXISTS `insert_test_data`$$
DROP PROCEDURE IF EXISTS `delete_test_data`$$
DROP PROCEDURE IF EXISTS `UserArchive`$$

CREATE PROCEDURE debug_msg(enabled INTEGER, msg VARCHAR(255))
    BEGIN
        IF enabled THEN
        select concat('** ', msg) AS '** DEBUG:';
        END IF;
    END$$

CREATE PROCEDURE insert_test_data(IN NUM int)
    BEGIN
        DECLARE i INT DEFAULT 0;
        DECLARE _NM varchar(25) default null;
        DECLARE _ID bigint default 0;
        DECLARE _PRO_ID bigint default 9215;
        DECLARE _CDT timestamp;
        DECLARE _DOB date default date('2000-03-23'); 

        WHILE i < NUM DO
            SELECT max(subscriber_id)+1 INTO _ID FROM user;

            SELECT SUBSTRING(MD5(RAND()) FROM 1 FOR 8) INTO _NM;

            SELECT from_unixtime(unix_timestamp('2017-10-01') + floor(rand() * (unix_timestamp('2018-06-30') - unix_timestamp('2017-06-01') + 1))) INTO _CDT;

            INSERT INTO user (password,last_login,is_superuser,subscriber_id,first_name,middle_name,last_name,email,is_staff,is_active,date_joined,favorites,last_played,alias) VALUES ('', (select from_unixtime(unix_timestamp('2018-10-01') + floor(rand() * (unix_timestamp('2019-06-30') - unix_timestamp('2018-01-01') + 1)))), 0, _ID, CONCAT('First', _NM), CONCAT('Middle', _NM), CONCAT('Last',_NM),CONCAT(_NM,i,'@gmail.com'), 0, 1, (select from_unixtime(unix_timestamp('2017-10-01') + floor(rand() * (unix_timestamp('2018-06-30') - unix_timestamp('2017-06-01') + 1)))), '', '', '');

        INSERT INTO userprofile (id, profile_image, alias, dob, created_at, gender, age_group, location, updated_at, subscriber_id, state, city, email, dateOfBirth, gamer_name, mobile_no) VALUES (_PRO_ID,'http://www.sample.com/abc.jpg',_NM, _DOB, _CDT, 'M','11-17',NULL, (select from_unixtime(unix_timestamp('2018-10-01') + floor(rand() * (unix_timestamp('2019-06-30') - unix_timestamp('2018-01-01') + 1)))), _ID, NULL, NULL, NULL, NULL, NULL, NULL);

        SET _PRO_ID = _PRO_ID +1;
        SET i = i + 1;

        END WHILE;
    END$$

CREATE PROCEDURE delete_test_data()
    BEGIN
        DELETE FROM userprofile WHERE subscriber_id > 8000009999999999;
        DELETE FROM user WHERE subscriber_id > 8000009999999999;
    END$$

CREATE PROCEDURE UserArchive(IN before_dt date)

    BEGIN
        DECLARE cnt int;
        DECLARE min_dt date;
        DECLARE counter int default 0 ;
        DECLARE `_rollback` BOOL DEFAULT 0;

        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION

        BEGIN
            SHOW ERRORS;
            ROLLBACK;   
        END;

        SELECT COUNT(subscriber_id) INTO cnt FROM `user` WHERE date(last_login) < before_dt;
        SELECT min(last_login) INTO min_dt FROM `user` ;

        call debug_msg(TRUE, (SELECT concat_ws(' ','Total Records to be migrated:', cnt, 'Loop from:', before_dt,' till (decreasing):', min_dt)));

        WHILE before_dt > min_dt do

            SET before_dt =  DATE_ADD(before_dt, INTERVAL -1 DAY);
            SELECT count(subscriber_id) INTO counter FROM user WHERE Date(last_login) = before_dt;
            call debug_msg(TRUE, (SELECT concat_ws(' ','Count Subscribers:', counter,' on Date:', before_dt)));

            IF counter > 0 THEN

                START TRANSACTION;

                    INSERT INTO userprofile_archived (id, profile_image, alias, dob, created_at, gender, age_group,
                         location, updated_at, subscriber_id, state, city, email, dateOfBirth, gamer_name, mobile_no)
                    SELECT 
                        id, profile_image, alias, dob, created_at, gender, age_group, location, updated_at, subscriber_id, 
                        state, city, email, dateOfBirth, gamer_name, mobile_no
                    FROM userprofile 
                    WHERE subscriber_id IN (SELECT subscriber_id FROM user WHERE Date(last_login) = before_dt);

                    call debug_msg(TRUE, (SELECT concat_ws(' ','Insertion completed on User Profile table.')));

                    DELETE FROM userprofile 
                    WHERE subscriber_id IN(
                        (SELECT subscriber_id FROM user 
                            WHERE Date(last_login) = before_dt));

                    call debug_msg(TRUE, (select concat_ws(' ','Deletion completed on User Profile table.')));
                    INSERT INTO user_archived (password, last_login, is_superuser, 
                                subscriber_id, first_name,middle_name,last_name, email, is_staff, 
                                is_active, date_joined, favorites, last_played, alias)
                        SELECT
                        password, last_login, is_superuser, subscriber_id, first_name,middle_name,last_name,email,
                        is_staff,is_active,date_joined,favorites,last_played,alias
                        FROM user
                        WHERE Date(last_login) = before_dt;

                    call debug_msg(TRUE, (select concat_ws(' ','Insertion completed on User table.')));

                    DELETE FROM user 
                        WHERE Date(last_login) = before_dt;
                    call debug_msg(TRUE, (select concat_ws(' ','Deletion completed on User table.')));

                    COMMIT;
            END IF;
         END WHILE;
    END$$
DELIMITER ;

1 Ответ

0 голосов
/ 19 июня 2020

Я решил проблему с фиксацией. Проблема возникла из-за кода, который находился вне поля l oop. Итак, если возникло исключение, пропустите код и продолжайте. Теперь работает нормально.

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN SHOW ERRORS; ROLLBACK;<br> END;

Теперь Код выше записывается как:

DELIMITER $$
...
...
CREATE PROCEDURE UserArchive(IN before_dt date)

    BEGIN
        DECLARE cnt int;
        ...
        ...
        WHILE before_dt > min_dt do
            BEGIN

            DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
            BEGIN
                SHOW ERRORS;
                ROLLBACK;   
            END;
            ...
            ...
            END;
         END WHILE;
    END$$
DELIMITER ; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...