Ejemplo n.º 1
0
 public function query($sql, $fname = __METHOD__, $tempIgnore = false)
 {
     $priorWritesPending = $this->writesOrCallbacksPending();
     $this->mLastQuery = $sql;
     $isWrite = $this->isWriteQuery($sql) && !$this->registerTempTableOperation($sql);
     if ($isWrite) {
         $reason = $this->getReadOnlyReason();
         if ($reason !== false) {
             throw new DBReadOnlyError($this, "Database is read-only: {$reason}");
         }
         # Set a flag indicating that writes have been done
         $this->mLastWriteTime = microtime(true);
     }
     // Add trace comment to the begin of the sql string, right after the operator.
     // Or, for one-word queries (like "BEGIN" or COMMIT") add it to the end (bug 42598)
     $commentedSql = preg_replace('/\\s|$/', " /* {$fname} {$this->agent} */ ", $sql, 1);
     # Start implicit transactions that wrap the request if DBO_TRX is enabled
     if (!$this->mTrxLevel && $this->getFlag(self::DBO_TRX) && $this->isTransactableQuery($sql)) {
         $this->begin(__METHOD__ . " ({$fname})", self::TRANSACTION_INTERNAL);
         $this->mTrxAutomatic = true;
     }
     # Keep track of whether the transaction has write queries pending
     if ($this->mTrxLevel && !$this->mTrxDoneWrites && $isWrite) {
         $this->mTrxDoneWrites = true;
         $this->trxProfiler->transactionWritingIn($this->mServer, $this->mDBname, $this->mTrxShortId);
     }
     if ($this->getFlag(self::DBO_DEBUG)) {
         $this->queryLogger->debug("{$this->mDBname} {$commentedSql}");
     }
     # Avoid fatals if close() was called
     $this->assertOpen();
     # Send the query to the server
     $ret = $this->doProfiledQuery($sql, $commentedSql, $isWrite, $fname);
     # Try reconnecting if the connection was lost
     if (false === $ret && $this->wasErrorReissuable()) {
         $recoverable = $this->canRecoverFromDisconnect($sql, $priorWritesPending);
         # Stash the last error values before anything might clear them
         $lastError = $this->lastError();
         $lastErrno = $this->lastErrno();
         # Update state tracking to reflect transaction loss due to disconnection
         $this->handleSessionLoss();
         if ($this->reconnect()) {
             $msg = __METHOD__ . ": lost connection to {$this->getServer()}; reconnected";
             $this->connLogger->warning($msg);
             $this->queryLogger->warning("{$msg}:\n" . (new RuntimeException())->getTraceAsString());
             if (!$recoverable) {
                 # Callers may catch the exception and continue to use the DB
                 $this->reportQueryError($lastError, $lastErrno, $sql, $fname);
             } else {
                 # Should be safe to silently retry the query
                 $ret = $this->doProfiledQuery($sql, $commentedSql, $isWrite, $fname);
             }
         } else {
             $msg = __METHOD__ . ": lost connection to {$this->getServer()} permanently";
             $this->connLogger->error($msg);
         }
     }
     if (false === $ret) {
         # Deadlocks cause the entire transaction to abort, not just the statement.
         # http://dev.mysql.com/doc/refman/5.7/en/innodb-error-handling.html
         # https://www.postgresql.org/docs/9.1/static/explicit-locking.html
         if ($this->wasDeadlock()) {
             if ($this->explicitTrxActive() || $priorWritesPending) {
                 $tempIgnore = false;
                 // not recoverable
             }
             # Update state tracking to reflect transaction loss
             $this->handleSessionLoss();
         }
         $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore);
     }
     $res = $this->resultObject($ret);
     return $res;
 }
Ejemplo n.º 2
0
 /**
  * Mark a DB as in a transaction with one or more writes pending
  *
  * Note that there can be multiple connections to a single DB.
  *
  * @param string $server DB server
  * @param string $db DB name
  * @param string $id Resource ID string of connection
  */
 public function transactionWritingIn($server, $db, $id = '')
 {
     $this->trxProfiler->transactionWritingIn($server, $db, $id);
 }