Penso che le procedure memorizzate potrebbero funzionare:
DELIMITER $$
DROP PROCEDURE IF EXISTS get_root;
CREATE PROCEDURE get_root(
IN parentID INT,
OUT rootID INT
)
BEGIN
SELECT parent_id FROM tree WHERE id = parentID INTO rootID;
IF rootID = 0
THEN SET rootID = parentID;
ELSE
CALL get_root(rootID, rootID);
END IF;
END$$
DELIMITER ;
SET @@GLOBAL.max_sp_recursion_depth = 255;
SET @@session.max_sp_recursion_depth = 255;
CALL get_root(4, @rootID);
SELECT @rootID;