Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-8027

Truncate on InnoDB with foreign key does not delete one after another

    Details

      Description

      According to the documentation (https://mariadb.com/kb/en/mariadb/truncate-table/) a truncate on a table with InnoDB should empty the table by deleting the table and recreating it. If the table contains foreign keys the engine should delete row after row and trigger all foreign keys. But thats currently not the case. Currently mariadb fails with the error:

      ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint
      

      Thanks and greetings
      Leo

        Gliffy Diagrams

          Attachments

            Activity

            Hide
            jplindst Jan Lindström added a comment -

            Remember that if we would follow foreign keys on truncate this could lead delete on child table that has ON DELETE RESTRICT: Rejects the delete or update operation for the parent table, thus we should roll back but we can't. I do not see any bug here, this is current limitation.

            Show
            jplindst Jan Lindström added a comment - Remember that if we would follow foreign keys on truncate this could lead delete on child table that has ON DELETE RESTRICT: Rejects the delete or update operation for the parent table, thus we should roll back but we can't. I do not see any bug here, this is current limitation.
            Hide
            leo.unglaub Leo Unglaub added a comment -

            Just for the record. I disagree with your last statement. It's wrong and makes no sence. But since you closed that ticket there is nothing i can do about it

            Show
            leo.unglaub Leo Unglaub added a comment - Just for the record. I disagree with your last statement. It's wrong and makes no sence. But since you closed that ticket there is nothing i can do about it
            Hide
            jplindst Jan Lindström added a comment -

            Consider following:

            create table parent(a int not null primary key) engine=innodb;
            create table child1(a int not null primary key, b int,
            foreign key (b) references parent(a) on delete cascade on update cascade) engine=innodb;
            create table child2(a int not null primary key, b int,
            foreign key (b) references parent(a) on delete restrict on update restrict) engine=innodb;
            
            insert into parent values (1);
            insert into child1 values (1,1);
            insert into child2 values (1,1);
            commit;
            

            Now consider first case where we would do normal delete:

            MariaDB [test]> delete from parent;
            ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child2`, CONSTRAINT `child2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `parent` (`a`))
            

            In this case we can naturally roll back the delete. However, consider

            truncate table parent;
            

            If we execute this row by row, firstly row from child1 is deleted (this case is fine) but row from child2 may not be deleted because we have specified ON DELETE RESTRICT and also parent row can't be then deleted, instead we should roll back the truncate. This is not currently possible. Not deleting rows that are needed for foreign key constraints on truncate is also not logical.

            Show
            jplindst Jan Lindström added a comment - Consider following: create table parent(a int not null primary key) engine=innodb; create table child1(a int not null primary key, b int, foreign key (b) references parent(a) on delete cascade on update cascade) engine=innodb; create table child2(a int not null primary key, b int, foreign key (b) references parent(a) on delete restrict on update restrict) engine=innodb; insert into parent values (1); insert into child1 values (1,1); insert into child2 values (1,1); commit; Now consider first case where we would do normal delete: MariaDB [test]> delete from parent; ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child2`, CONSTRAINT `child2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `parent` (`a`)) In this case we can naturally roll back the delete. However, consider truncate table parent; If we execute this row by row, firstly row from child1 is deleted (this case is fine) but row from child2 may not be deleted because we have specified ON DELETE RESTRICT and also parent row can't be then deleted, instead we should roll back the truncate. This is not currently possible. Not deleting rows that are needed for foreign key constraints on truncate is also not logical.
            Hide
            leo.unglaub Leo Unglaub added a comment -

            I still dont see the difference between truncate triggering a row by row delete and a user triggering a row by row delete. It's the same effect for all referenced tables. They have to delete there entry. But it does not matter, i have added a function called "Force Truncate" into my HeidiSQL Clone for Linux. If the truncate fails the client will do the row by row delete automaticly.

            Show
            leo.unglaub Leo Unglaub added a comment - I still dont see the difference between truncate triggering a row by row delete and a user triggering a row by row delete. It's the same effect for all referenced tables. They have to delete there entry. But it does not matter, i have added a function called "Force Truncate" into my HeidiSQL Clone for Linux. If the truncate fails the client will do the row by row delete automaticly.
            Hide
            jplindst Jan Lindström added a comment -

            Difference is that delete is transactional (all or nothing is executed) but truncate is not (if table is found all rows are deleted). Thus, for truncate we need to first check can we do it and then execute. In middle of execution of the truncate there is no way to roll back all that we have done so far.

            Show
            jplindst Jan Lindström added a comment - Difference is that delete is transactional (all or nothing is executed) but truncate is not (if table is found all rows are deleted). Thus, for truncate we need to first check can we do it and then execute. In middle of execution of the truncate there is no way to roll back all that we have done so far.

              People

              • Assignee:
                greenman Ian Gilfillan
                Reporter:
                leo.unglaub Leo Unglaub
              • Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: