Adapter
1 month ago
Schema
2 weeks ago
Adapter.php
1 month ago
AdapterInterface.php
1 month ago
BatchInsert.php
6 months ago
Schema.php
1 month ago
SchemaInterface.php
1 month ago
Settings.php
1 year ago
TransactionLevel.php
1 year ago
TransactionalDatabaseDynamicTrait.php
1 year ago
TransactionalDatabaseInterface.php
1 year ago
TransactionalDatabaseStaticTrait.php
1 year ago
TransactionLevel.php
81 lines
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * Matomo - free/libre analytics platform |
| 5 | * |
| 6 | * @link https://matomo.org |
| 7 | * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later |
| 8 | */ |
| 9 | namespace Piwik\Db; |
| 10 | |
| 11 | use Piwik\Db; |
| 12 | use Piwik\Option; |
| 13 | class TransactionLevel |
| 14 | { |
| 15 | public const TEST_OPTION_NAME = 'TransactionLevel.testOption'; |
| 16 | private $statusBackup; |
| 17 | /** |
| 18 | * @var TransactionalDatabaseInterface $transactionalDatabase |
| 19 | */ |
| 20 | private $transactionalDatabase; |
| 21 | public function __construct(\Piwik\Db\TransactionalDatabaseInterface $transactionalDatabase) |
| 22 | { |
| 23 | $this->transactionalDatabase = $transactionalDatabase; |
| 24 | } |
| 25 | public function canLikelySetTransactionLevel() |
| 26 | { |
| 27 | $dbSettings = new Db\Settings(); |
| 28 | return strtolower($dbSettings->getEngine()) === 'innodb'; |
| 29 | } |
| 30 | /** |
| 31 | * @deprecated Use `setTransactionLevelForNonLockingReads` |
| 32 | */ |
| 33 | public function setUncommitted() |
| 34 | { |
| 35 | return $this->setTransactionLevelForNonLockingReads(); |
| 36 | } |
| 37 | public function setTransactionLevelForNonLockingReads() : bool |
| 38 | { |
| 39 | if ($this->transactionalDatabase->getSupportsTransactionLevelForNonLockingReads() === \false) { |
| 40 | // we know "Uncommitted" transaction level is not supported, we don't need to do anything as it won't work to set the status |
| 41 | return \false; |
| 42 | } |
| 43 | try { |
| 44 | $backup = $this->transactionalDatabase->getCurrentTransactionIsolationLevelForSession(); |
| 45 | } catch (\Exception $e) { |
| 46 | $this->transactionalDatabase->setSupportsTransactionLevelForNonLockingReads(\false); |
| 47 | return \false; |
| 48 | } |
| 49 | try { |
| 50 | $this->transactionalDatabase->setTransactionIsolationLevel(\Piwik\Db\Schema::getInstance()->getSupportedReadIsolationTransactionLevel()); |
| 51 | $this->statusBackup = $backup; |
| 52 | if ($this->transactionalDatabase->getSupportsTransactionLevelForNonLockingReads() === null) { |
| 53 | // the first time we need to check if the transaction level actually works by |
| 54 | // trying to set something w/ the new transaction isolation level |
| 55 | Option::set(self::TEST_OPTION_NAME, '1'); |
| 56 | } |
| 57 | $this->transactionalDatabase->setSupportsTransactionLevelForNonLockingReads(\true); |
| 58 | } catch (\Exception $e) { |
| 59 | // setting the transaction level status did not work |
| 60 | // catch eg 1665 Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED |
| 61 | $this->transactionalDatabase->setSupportsTransactionLevelForNonLockingReads(\false); |
| 62 | $this->restorePreviousStatus(); |
| 63 | return \false; |
| 64 | } |
| 65 | return \true; |
| 66 | } |
| 67 | public function restorePreviousStatus() |
| 68 | { |
| 69 | if ($this->statusBackup) { |
| 70 | $value = strtoupper($this->statusBackup); |
| 71 | $this->statusBackup = null; |
| 72 | $value = str_replace('-', ' ', $value); |
| 73 | if (in_array($value, array('REPEATABLE READ', 'READ COMMITTED', 'SERIALIZABLE'))) { |
| 74 | $this->transactionalDatabase->setTransactionIsolationLevel($value); |
| 75 | } elseif ($value !== 'READ UNCOMMITTED') { |
| 76 | $this->transactionalDatabase->setTransactionIsolationLevel('REPEATABLE READ'); |
| 77 | } |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 |