PHP 8 - "There is no active transaction" when transaction is autocommitted
twisted1919 opened this issue · 1 comments
This is related to yiisoft/yii2#18406
As of PHP 8, PDO::commit() and rollBack() will throw a There is no active transaction PDOException if the transaction had been autocommitted, as MySQL will do whenever a schema change is made. Previously they would fail silently.
What steps will reproduce the problem?
- Connect to a MySQL database
- Call Yii::app()->db->beginTransaction()
- Make a schema change, such as add a new column to a table (the transaction will be autocommitted in the process)
- Call Yii::app()->db->commit()
What is the expected result?
PHP would move along to the next line of code, regardless of whether the app is running on PHP 5, 7, or 8.
What do you get instead?
A PDOException is thrown with the message There is no active transaction when running PHP 8.
Additional info
Q | A |
---|---|
Yii version | 1.1.24-dev |
PHP version | 8.0.0 |
Operating system | Centos 7 |
I am not sure if this is a good fix or not, but what we did was to modify a bit the CDbTransaction
class and basically wrap PDO's commit
and rollback
method calls in an additional if
which makes sure we're still inside a transaction, like:
public function commit()
{
if($this->_active && $this->_connection->getActive())
{
Yii::trace('Committing transaction','system.db.CDbTransaction');
if ($this->_connection->getPdoInstance()->inTransaction()) {
$this->_connection->getPdoInstance()->commit();
}
$this->_active=false;
}
else
throw new CDbException(Yii::t('yii','CDbTransaction is inactive and cannot perform commit or roll back operations.'));
}
and
public function rollback()
{
if($this->_active && $this->_connection->getActive())
{
Yii::trace('Rolling back transaction','system.db.CDbTransaction');
if ($this->_connection->getPdoInstance()->inTransaction()) {
$this->_connection->getPdoInstance()->rollBack();
}
$this->_active=false;
}
else
throw new CDbException(Yii::t('yii','CDbTransaction is inactive and cannot perform commit or roll back operations.'));
}
Does this seem correct to you?