SlowCycle.de » DROP DATABASE setzt globalen LOCK
DROP DATABASE setzt globalen LOCK
MySQL (InnoDB) setzt einen globalen lock auf alle Datenbanken
wenn man ein “DROP DATABASE testdb” Statement ausführt. Bei 100- 200ms pro Tabelle
kann es bei größeren Datenbanken zu einem Stillstand der Abarbeitung aller Anfragen
von mehreren Sekunden kommen.
Dies kann man mit folgendem kleinem bash script nachstellen.
#!/bin/bash while true do mysql -uroot -p****** anotherdb -e "SELECT NOW(), id FROM table LIMIT 1" sleep 1 done
Während das script läuft, kann man dann in bspw. einer 2. Konsole
das “DROP DATABASE irgendeinedb” Statement ausführen.
Man kann dann in der ersten Konsole sehen das die Abarbeitung der Anfragen
anhalten.
Nachfolgende Prozedur kann Abhilfe schaffen.
(Man muss die Prozedur an eine Datenbank binden,
am besten nicht an die, die man löschen möchte.)
Die Prozedur löscht erst alle Tabellen der DB einzeln und erst am Ende
wird auf die quasi leere DB ein DROP DATABASE Statement angewendet.
Befehl:
CALL drop_database(‘irgendeinedb’);
DROP PROCEDURE IF EXISTS drop_database; DELIMITER $$ CREATE PROCEDURE drop_database(IN _database VARCHAR(60)) BEGIN DECLARE _done INT DEFAULT 0; DECLARE _table VARCHAR(60); DECLARE _cur CURSOR FOR SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = _database; DECLARE CONTINUE HANDLER FOR NOT FOUND SET _done = 1; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; OPEN _cur; REPEAT FETCH _cur INTO _table; IF NOT _done THEN SET @QUERY = CONCAT('DROP TABLE ', _database, '.', _table); PREPARE query FROM @QUERY; EXECUTE query; DEALLOCATE PREPARE query; END IF; UNTIL _done END REPEAT; CLOSE _cur; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; SET @QUERY = CONCAT('DROP DATABASE ', _database); PREPARE query FROM @QUERY; EXECUTE query; DEALLOCATE PREPARE query; END; $$ DELIMITER ;
Gib deinen Kommentar ab