ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

PL/pgSQL Transactional Retry Logic

PL/pgSQL

Goal -- WPM

Ready
Exercise Algorithm Area
1CREATE OR REPLACE FUNCTION perform_critical_operation_with_retry(
2p_max_retries INTEGER,
3p_operation_details JSONB
4) RETURNS BOOLEAN AS $$
5DECLARE
6v_retry_count INTEGER := 0;
7v_success BOOLEAN := FALSE;
8v_deadlock_detected EXCEPTION;
9-- Define a custom exception for deadlock, though in real scenarios
10-- you'd catch specific SQLSTATE codes like '40P01'
11
12-- Placeholder for the actual operation that might fail
13PROCEDURE execute_operation(details JSONB) IS
14BEGIN
15-- Simulate an operation that might fail with a deadlock
16-- In a real scenario, this would involve DML statements
17RAISE NOTICE 'Executing operation with details: %', details;
18-- Simulate a potential deadlock error for testing purposes
19IF random() < 0.3 AND v_retry_count < p_max_retries THEN
20RAISE EXCEPTION SQLSTATE '40P01' USING MESSAGE = 'Deadlock detected';
21END IF;
22RAISE NOTICE 'Operation executed successfully.';
23END;
24
25BEGIN
26LOOP
27BEGIN
28-- Call the actual operation
29execute_operation(p_operation_details);
30v_success := TRUE;
31EXIT; -- Exit loop on success
32EXCEPTION
33WHEN SQLSTATE '40P01' THEN -- Catch deadlock error
34v_retry_count := v_retry_count + 1;
35RAISE NOTICE 'Deadlock detected. Retrying (Attempt %/%)...', v_retry_count, p_max_retries;
36IF v_retry_count >= p_max_retries THEN
37RAISE NOTICE 'Max retries reached. Operation failed.';
38RETURN FALSE; -- Indicate failure after max retries
39END IF;
40-- Optional: Add a small delay before retrying
41PERFORM pg_sleep(0.1);
42WHEN OTHERS THEN
43RAISE NOTICE 'An unexpected error occurred.';
44RETURN FALSE; -- Indicate failure on other errors
45END;
46END LOOP;
47
48RETURN v_success;
49END;
50$$ LANGUAGE plpgsql;
Algorithm description viewbox

PL/pgSQL Transactional Retry Logic

Algorithm description:

This PL/pgSQL function implements a robust transactional retry mechanism. It attempts to execute a critical database operation and, if a deadlock error (SQLSTATE '40P01') occurs, it automatically retries the operation up to a predefined maximum number of attempts. This is crucial for high-concurrency systems where transient deadlocks can occur, preventing the entire transaction from failing due to temporary resource contention.

Algorithm explanation:

The function `perform_critical_operation_with_retry` uses a `LOOP` construct to repeatedly attempt an operation. Inside the loop, a `BEGIN...EXCEPTION` block handles potential errors. Specifically, it catches the `SQLSTATE '40P01'` error, which signifies a deadlock. If caught, the retry count is incremented, and if the maximum retries haven't been exceeded, the loop continues after a short `pg_sleep`. If the operation succeeds, `v_success` is set to `TRUE`, and the loop `EXIT`s. Any other exception will cause the function to return `FALSE`. The time complexity is difficult to define precisely due to the unpredictable nature of deadlocks and retries, but in the best case (no retries), it's O(1) for the operation itself. In the worst case, it's O(N * C), where N is the number of retries and C is the cost of the operation. Space complexity is O(1) as it only uses a few variables.

Pseudocode:

FUNCTION perform_critical_operation_with_retry(max_retries, operation_details):
  retry_count = 0
  LOOP:
    BEGIN TRANSACTION:
      TRY:
        execute_operation(operation_details)
        RETURN TRUE  // Success
      CATCH SQLSTATE '40P01' (Deadlock):
        increment retry_count
        IF retry_count >= max_retries:
          RETURN FALSE // Failure after max retries
        ELSE:
          WAIT briefly
          CONTINUE LOOP
      CATCH other_error:
        RETURN FALSE // Failure on other errors
  END LOOP
END FUNCTION