在
postUp()
方法中完成结构数据库更改后,我想使用 up()
导入一些数据。导入应使用 DBAL API 在事务中完成。然而,插入似乎是一个接一个地提交的。如果在导入过程中发生错误(例如“重复密钥”错误),则可以观察到这一点。即使启动了回滚,在错误之前执行的插入也将被提交到数据库。似乎破坏事务行为的是 up()
方法中的任何 DDL 语句。
考虑以下因素:
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('CREATE TABLE user (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET UTF8 COLLATE UTF8_unicode_ci ENGINE = InnoDB');
}
public function postUp(Schema $schema)
{
/**
* @var EntityManager $em
*/
$em = $this->container->get('doctrine.orm.entity_manager');
$em->getConnection()->transactional(function ($conn) {
$conn->executeUpdate("INSERT INTO user (id,name) VALUES(1,'Josh')");
$conn->executeUpdate("INSERT INTO user (id,name) VALUES(1,'Will')");
});
}
现在,第二个插入语句将导致“1062:重复键”错误,并将触发对连接实例上的
rollback()
的调用。但是,实际回滚不会发生,并且第一个插入的行保留在数据库中。我实际上使用调试器跟踪了执行情况,并且 commit()
从未被调用,rollback()
被调用,因为它应该,但最终结果似乎相反。我还尝试执行插入而不将它们包装在 transactional()
中,行为是相同的。
但是,如果
up()
方法中没有 DDL 语句(例如,如果用户表已存在),则事务按预期工作,并且 user
表保持为空,无论是否在事务中包装插入语句。我在这里做错了什么或理解错误以及如何正确执行此操作?