@@ -1562,7 +1562,19 @@ END
1562
1562
$$ LANGUAGE plpgsql;
1563
1563
1564
1564
1565
- -- Commit or rollback not completed distributed transactions
1565
+ -- Commit or rollback not completed distributed transactions.
1566
+ -- All nodes must be alive for this to do something.
1567
+ -- If coordinator is still in the cluster, we just try asking it.
1568
+ -- If not, and there is only one participant, we simply commit the xact.
1569
+ -- If n_participants > 1, and xact is prepared everywhere, commit it.
1570
+ -- Otherwise, check WAL of every node; if COMMIT is found, COMMIT, if ABORT
1571
+ -- is found, ABORT.
1572
+ --
1573
+ -- Currently this function is not too hasty because
1574
+ -- * We make totally independent decisions for each 'prepare'.
1575
+ -- * We never know the participants and poll all nodes in the cluster.
1576
+ -- * If coordinator is excluded, we sequentially examine WAL of *all* nodes to
1577
+ -- learn the outcome, even where xact is prepared.
1566
1578
CREATE FUNCTION recover_xacts () RETURNS void AS $$
1567
1579
DECLARE
1568
1580
node_id int ;
@@ -1590,7 +1602,9 @@ BEGIN
1590
1602
1591
1603
FOR node_id IN SELECT id FROM shardman .nodes
1592
1604
LOOP
1593
- cmds := format(' %s%s:SELECT string_agg(' ' %s=>' ' ||gid, ' ' ,' ' ) FROM pg_prepared_xacts;' , cmds, node_id, node_id);
1605
+ cmds := format($cmd$
1606
+ %s%s:SELECT coalesce(string_agg(' %s=>' || gid, ' ,' ), ' ' ) FROM pg_prepared_xacts;$cmd$,
1607
+ cmds, node_id, node_id);
1594
1608
END LOOP;
1595
1609
1596
1610
-- Collected prepared xacts from all nodes
@@ -1625,7 +1639,7 @@ BEGIN
1625
1639
n_prepared := n_prepared + counter::int ;
1626
1640
END LOOP;
1627
1641
1628
- IF n_prepared= n_participants
1642
+ IF n_prepared = n_participants
1629
1643
THEN
1630
1644
RAISE NOTICE ' Commit distributed transaction % which is prepared at all participant nodes' , gid;
1631
1645
finish := format(' %s%s:COMMIT PREPARED %L;' , finish, xact_node_id, gid);
@@ -1635,16 +1649,19 @@ BEGIN
1635
1649
1636
1650
IF EXISTS (SELECT * FROM pg_proc WHERE proname= ' pg_prepared_xact_status' )
1637
1651
THEN
1638
- -- Without coordinator there is no standard way to get status of this distributed transaction.
1639
- -- Use PGPRO-EE pg_prepared_xact_status() function if available
1652
+ -- Without coordinator there is no standard way to get
1653
+ -- status of this distributed transaction. Use PGPRO-EE
1654
+ -- pg_prepared_xact_status() function if available
1640
1655
cmds := ' ' ;
1641
1656
FOR node_id IN SELECT id FROM shardman .nodes
1642
1657
LOOP
1643
- cmds := format(' %s%s:SELECT pg_prepared_xact_status(%L);' , cmds, node_id, gid);
1658
+ cmds := format(' %s%s:SELECT pg_prepared_xact_status(%L);' ,
1659
+ cmds, node_id, gid);
1644
1660
END LOOP;
1645
1661
SELECT shardman .broadcast (cmds) INTO resp;
1646
1662
1647
- -- Collect information about distributed transaction status at all nodes
1663
+ -- Collect information about distributed transaction
1664
+ -- status at all nodes
1648
1665
do_commit := false;
1649
1666
do_rollback := false;
1650
1667
FOREACH status IN ARRAY string_to_array(resp, ' ,' )
@@ -1662,9 +1679,10 @@ BEGIN
1662
1679
THEN
1663
1680
IF do_rollack
1664
1681
THEN
1665
- RAISE NOTICE ' Inconsistent state of transaction %' , gid;
1682
+ RAISE WARNING ' Inconsistent state of transaction %' ,
1683
+ gid;
1666
1684
ELSE
1667
- RAISE NOTICE ' Commit transaction %s at node % because if was committed at one of participants' ,
1685
+ RAISE NOTICE ' Committing transaction %s at node % because it was committed at one of participants' ,
1668
1686
gid, xact_node_id;
1669
1687
finish := format(' %s%s:COMMIT PREPARED %L;' , finish, xact_node_id, gid);
1670
1688
END IF;
@@ -1674,24 +1692,29 @@ BEGIN
1674
1692
gid, xact_node_id;
1675
1693
finish := format(' %s%s:ROLLBACK PREPARED %L;' , finish, xact_node_id, gid);
1676
1694
ELSE
1677
- RAISE NOTICE ' Can not make any decision concerning distributes transaction %' , gid;
1695
+ RAISE NOTICE ' Can' ' t make any decision concerning distributed transaction %' , gid;
1678
1696
END IF;
1679
1697
END IF;
1680
1698
END IF;
1681
1699
ELSE
1682
- RAISE NOTICE ' Commit transaction % with single participant %' , gid, xact_node_id;
1700
+ RAISE NOTICE ' Committing transaction % with single participant %' , gid, xact_node_id;
1683
1701
finish := format(' %s%s:COMMIT PREPARED %L;' , finish, xact_node_id, gid);
1684
1702
END IF;
1685
1703
ELSE
1686
1704
-- Check status of transaction at coordinator
1687
- SELECT shardman .broadcast (format(' %s:SELECT txid_status(%s);' , coordinator, xid)) INTO status;
1688
- RAISE NOTICE ' Status of distributed transaction % is % at coordinator %' , gid, status, coordinator;
1705
+ SELECT shardman .broadcast (format(' %s:SELECT txid_status(%s);' , coordinator, xid))
1706
+ INTO status;
1707
+ RAISE NOTICE ' Status of distributed transaction % is % at coordinator %' ,
1708
+ gid, status, coordinator;
1689
1709
IF status= ' committed'
1690
1710
THEN
1691
1711
finish := format(' %s%s:COMMIT PREPARED %L;' , finish, xact_node_id, gid);
1692
1712
ELSIF status= ' aborted'
1693
1713
THEN
1694
1714
finish := format(' %s%s:ROLLBACK PREPARED %L;' , finish, xact_node_id, gid);
1715
+ ELSEIF status IS NULL
1716
+ THEN
1717
+ RAISE WARNING ' '
1695
1718
END IF;
1696
1719
END IF;
1697
1720
END LOOP;
0 commit comments