diff --git a/vendor/magento/module-paypal/Model/Ipn.php b/vendor/magento/module-paypal/Model/Ipn.php
index 9691da4b82763..f33bd6f7593de 100644
--- a/vendor/magento/module-paypal/Model/Ipn.php
+++ b/vendor/magento/module-paypal/Model/Ipn.php
@@ -7,10 +7,12 @@
 namespace Magento\Paypal\Model;
 
 use Exception;
+use Magento\Framework\App\ObjectManager;
 use Magento\Framework\Exception\LocalizedException;
 use Magento\Sales\Model\Order;
 use Magento\Sales\Model\Order\Email\Sender\CreditmemoSender;
 use Magento\Sales\Model\Order\Email\Sender\OrderSender;
+use Magento\Sales\Model\OrderMutexInterface;
 
 /**
  * PayPal Instant Payment Notification processor model
@@ -46,13 +48,19 @@ class Ipn extends \Magento\Paypal\Model\AbstractIpn implements IpnInterface
     protected $creditmemoSender;
 
     /**
-     * @param \Magento\Paypal\Model\ConfigFactory $configFactory
+     * @var OrderMutexInterface|null
+     */
+    private ?OrderMutexInterface $orderMutex;
+
+    /**
+     * @param ConfigFactory $configFactory
      * @param \Psr\Log\LoggerInterface $logger
      * @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory
      * @param \Magento\Sales\Model\OrderFactory $orderFactory
      * @param Info $paypalInfo
      * @param OrderSender $orderSender
      * @param CreditmemoSender $creditmemoSender
+     * @param OrderMutexInterface|null $orderMutex
      * @param array $data
      */
     public function __construct(
@@ -63,6 +71,7 @@ public function __construct(
         Info $paypalInfo,
         OrderSender $orderSender,
         CreditmemoSender $creditmemoSender,
+        ?OrderMutexInterface $orderMutex = null,
         array $data = []
     ) {
         parent::__construct($configFactory, $logger, $curlFactory, $data);
@@ -70,6 +79,7 @@ public function __construct(
         $this->_paypalInfo = $paypalInfo;
         $this->orderSender = $orderSender;
         $this->creditmemoSender = $creditmemoSender;
+        $this->orderMutex = $orderMutex ?: ObjectManager::getInstance()->get(OrderMutexInterface::class);
     }
 
     /**
@@ -466,6 +476,21 @@ protected function _registerPaymentReversal()
      * @return void
      */
     protected function _registerPaymentRefund()
+    {
+        return $this->orderMutex->execute(
+            (int) $this->_order->getEntityId(),
+            \Closure::fromCallable([$this, 'processRefund'])
+        );
+    }
+
+    /**
+     * Process a refund
+     *
+     * @return void
+     * @throws Exception
+     * @SuppressWarnings(PHPMD.UnusedPrivateMethod) This method is used in closure callback
+     */
+    private function processRefund()
     {
         $this->_importPaymentInformation();
         $reason = $this->getRequestData('reason_code');
diff --git a/vendor/magento/module-sales/Model/RefundInvoice.php b/vendor/magento/module-sales/Model/RefundInvoice.php
index c9d23d98e9f5e..feaa8d9814bf7 100644
--- a/vendor/magento/module-sales/Model/RefundInvoice.php
+++ b/vendor/magento/module-sales/Model/RefundInvoice.php
@@ -5,11 +5,16 @@
  */
 namespace Magento\Sales\Model;
 
+use Magento\Framework\App\ObjectManager;
 use Magento\Framework\App\ResourceConnection;
 use Magento\Sales\Api\CreditmemoRepositoryInterface;
+use Magento\Sales\Api\Data\CreditmemoCommentCreationInterface;
+use Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface;
 use Magento\Sales\Api\InvoiceRepositoryInterface;
 use Magento\Sales\Api\OrderRepositoryInterface;
 use Magento\Sales\Api\RefundInvoiceInterface;
+use Magento\Sales\Exception\CouldNotRefundException;
+use Magento\Sales\Exception\DocumentValidationException;
 use Magento\Sales\Model\Order\Config as OrderConfig;
 use Magento\Sales\Model\Order\Creditmemo\NotifierInterface;
 use Magento\Sales\Model\Order\CreditmemoDocumentFactory;
@@ -19,7 +24,6 @@
 use Psr\Log\LoggerInterface;
 
 /**
- * Class RefundInvoice
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class RefundInvoice implements RefundInvoiceInterface
@@ -79,6 +83,11 @@ class RefundInvoice implements RefundInvoiceInterface
      */
     private $validator;
 
+    /**
+     * @var OrderMutexInterface
+     */
+    private $orderMutex;
+
     /**
      * RefundInvoice constructor.
      *
@@ -93,6 +102,7 @@ class RefundInvoice implements RefundInvoiceInterface
      * @param NotifierInterface $notifier
      * @param OrderConfig $config
      * @param LoggerInterface $logger
+     * @param OrderMutexInterface|null $orderMutex
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
@@ -106,7 +116,8 @@ public function __construct(
         CreditmemoDocumentFactory $creditmemoDocumentFactory,
         NotifierInterface $notifier,
         OrderConfig $config,
-        LoggerInterface $logger
+        LoggerInterface $logger,
+        ?OrderMutexInterface $orderMutex = null
     ) {
         $this->resourceConnection = $resourceConnection;
         $this->orderStateResolver = $orderStateResolver;
@@ -119,6 +130,7 @@ public function __construct(
         $this->notifier = $notifier;
         $this->config = $config;
         $this->logger = $logger;
+        $this->orderMutex = $orderMutex ?: ObjectManager::getInstance()->get(OrderMutexInterface::class);
     }
 
     /**
@@ -133,7 +145,48 @@ public function execute(
         \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null,
         \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null
     ) {
-        $connection = $this->resourceConnection->getConnection('sales');
+        $invoice = $this->invoiceRepository->get($invoiceId);
+        $order = $this->orderRepository->get($invoice->getOrderId());
+
+        return $this->orderMutex->execute(
+            (int) $order->getEntityId(),
+            \Closure::fromCallable([$this, 'processRefund']),
+            [
+                $invoiceId,
+                $items,
+                $isOnline,
+                $notify,
+                $appendComment,
+                $comment,
+                $arguments
+            ]
+        );
+    }
+
+    /**
+     * Refund process logic
+     *
+     * @param int $invoiceId
+     * @param array $items
+     * @param bool $isOnline
+     * @param bool $notify
+     * @param bool $appendComment
+     * @param CreditmemoCommentCreationInterface|null $comment
+     * @param CreditmemoCreationArgumentsInterface|null $arguments
+     * @return int|null
+     * @throws CouldNotRefundException
+     * @throws DocumentValidationException
+     * @SuppressWarnings(PHPMD.UnusedPrivateMethod) This method is used in closure callback
+     */
+    private function processRefund(
+        $invoiceId,
+        array $items = [],
+        bool $isOnline = false,
+        bool $notify = false,
+        bool $appendComment = false,
+        \Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null,
+        \Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null
+    ) {
         $invoice = $this->invoiceRepository->get($invoiceId);
         $order = $this->orderRepository->get($invoice->getOrderId());
         $creditmemo = $this->creditmemoDocumentFactory->createFromInvoice(
@@ -160,7 +213,6 @@ public function execute(
                 __("Creditmemo Document Validation Error(s):\n" . implode("\n", $validationMessages->getMessages()))
             );
         }
-        $connection->beginTransaction();
         try {
             $creditmemo->setState(\Magento\Sales\Model\Order\Creditmemo::STATE_REFUNDED);
             $order->setCustomerNoteNotify($notify);
@@ -178,10 +230,8 @@ public function execute(
             $this->invoiceRepository->save($invoice);
             $order = $this->orderRepository->save($order);
             $creditmemo = $this->creditmemoRepository->save($creditmemo);
-            $connection->commit();
         } catch (\Exception $e) {
             $this->logger->critical($e);
-            $connection->rollBack();
             throw new \Magento\Sales\Exception\CouldNotRefundException(
                 __('Could not save a Creditmemo, see error log for details')
             );

