| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Db; |
|
|
| use Piwik\Db; |
| use Piwik\Option; |
|
|
| class TransactionLevel |
| { |
| public const TEST_OPTION_NAME = 'TransactionLevel.testOption'; |
|
|
| private $statusBackup; |
|
|
| |
| |
| |
| private $transactionalDatabase; |
|
|
| public function __construct(TransactionalDatabaseInterface $transactionalDatabase) |
| { |
| $this->transactionalDatabase = $transactionalDatabase; |
| } |
|
|
| public function canLikelySetTransactionLevel() |
| { |
| $dbSettings = new Db\Settings(); |
|
|
| return strtolower($dbSettings->getEngine()) === 'innodb'; |
| } |
|
|
| |
| |
| |
| public function setUncommitted() |
| { |
| return $this->setTransactionLevelForNonLockingReads(); |
| } |
|
|
| public function setTransactionLevelForNonLockingReads(): bool |
| { |
| if ($this->transactionalDatabase->getSupportsTransactionLevelForNonLockingReads() === false) { |
| |
| return false; |
| } |
|
|
| try { |
| $backup = $this->transactionalDatabase->getCurrentTransactionIsolationLevelForSession(); |
| } catch (\Exception $e) { |
| $this->transactionalDatabase->setSupportsTransactionLevelForNonLockingReads(false); |
| return false; |
| } |
|
|
| try { |
| $this->transactionalDatabase->setTransactionIsolationLevel(Schema::getInstance()->getSupportedReadIsolationTransactionLevel()); |
|
|
| $this->statusBackup = $backup; |
|
|
| if ($this->transactionalDatabase->getSupportsTransactionLevelForNonLockingReads() === null) { |
| |
| |
| Option::set(self::TEST_OPTION_NAME, '1'); |
| } |
|
|
| $this->transactionalDatabase->setSupportsTransactionLevelForNonLockingReads(true); |
| } catch (\Exception $e) { |
| |
| |
| $this->transactionalDatabase->setSupportsTransactionLevelForNonLockingReads(false); |
| $this->restorePreviousStatus(); |
| return false; |
| } |
|
|
| return true; |
| } |
|
|
| public function restorePreviousStatus() |
| { |
| if ($this->statusBackup) { |
| $value = strtoupper($this->statusBackup); |
| $this->statusBackup = null; |
|
|
| $value = str_replace('-', ' ', $value); |
| if (in_array($value, array('REPEATABLE READ', 'READ COMMITTED', 'SERIALIZABLE'))) { |
| $this->transactionalDatabase->setTransactionIsolationLevel($value); |
| } elseif ($value !== 'READ UNCOMMITTED') { |
| $this->transactionalDatabase->setTransactionIsolationLevel('REPEATABLE READ'); |
| } |
| } |
| } |
| } |
|
|