Если в скрипте произошла ошибка, то как мне откатить транзакцию
старайся чтобы все, что касается работы с каким то объектом, у которого состояние требует реакции (закрытие файла, транзакции бд и т.п.) то настоятельно рекомендуется описывать всю логику примерно на одном уровне/в одном месте
Не рекомендуется пытаться делать где то один мега крутой метод который все закроет, финализирует и освободит, как только произойдет фатальная ошибка (а именно так будет работать php с базами данных и файлами). Например это можно сделать через описание деструкторов классов-пустышек с одним объектом в мемберах, определяемых для каждого отдельного случая, в этом случае перед завершением работы скрипта будут вызваны все десктрукторы (порядок вызова - с осторожностью, сложен для прогнозирования).
Язык программирования php рекомендует и предлагает для этого конструкцию try catch finaly, там где может произойти ошибка, в catch прописывай логику завершения именно данной секции (откатить транзакцию) и вызывай следующий throw по цепочке, в finaly же прописывай то что нужно исполнить в любом случае.
Да это потребует вдумчиво везде где только можно следить за ошибками, но такова селяви, либо ты надеешься на авось и автоматизацию либо следишь за всем сам.