Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit60936c5

Browse files
committed
Add set_synchronous_standbys() method
1 parent869920c commit60936c5

File tree

4 files changed

+122
-2
lines changed

4 files changed

+122
-2
lines changed

‎docs/source/testgres.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,12 @@ testgres.node
5959
..automethod::__init__
6060

6161
..autoclass::testgres.node.ProcessProxy
62-
:members:
62+
:members:
63+
64+
testgres.standby
65+
----------------
66+
67+
..automodule::testgres.standby
68+
:members:
69+
:undoc-members:
70+
:show-inheritance:

‎testgres/node.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
importsubprocess
77
importtime
88

9+
fromcollectionsimportIterable
910
fromshutilimportrmtree
1011
fromsiximportraise_from,iteritems
1112
fromtempfileimportmkstemp,mkdtemp
@@ -58,6 +59,8 @@
5859

5960
from .loggerimportTestgresLogger
6061

62+
from .standbyimportFirst
63+
6164
from .utilsimport \
6265
eprint, \
6366
get_bin_path, \
@@ -650,7 +653,7 @@ def restart(self, params=[]):
650653

651654
defreload(self,params=[]):
652655
"""
653-
Reload config files using pg_ctl.
656+
Asynchronously reload config files using pg_ctl.
654657
655658
Args:
656659
params: additional arguments for pg_ctl.
@@ -979,6 +982,33 @@ def replicate(self, name=None, slot=None, **kwargs):
979982
withclean_on_error(self.backup(**kwargs))asbackup:
980983
returnbackup.spawn_replica(name=name,destroy=True,slot=slot)
981984

985+
defset_synchronous_standbys(self,standbys):
986+
"""
987+
Set standby synchronization options. This corresponds to
988+
`synchronous_standby_names <https://www.postgresql.org/docs/current/static/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES>`_
989+
option. Note that :meth:`~.PostgresNode.reload` or
990+
:meth:`~.PostgresNode.restart` is needed for changes to take place.
991+
992+
Args:
993+
standbys: either :class:`.First` or :class:`.Any` object specifying
994+
sychronization parameters. It is also possible to pass simply
995+
a list of replicas which would be equivalent to passing
996+
``First(1, <list>)``
997+
998+
Example::
999+
1000+
master = get_new_node().init().start()
1001+
with master.replicate.start() as standby:
1002+
master.append_conf("synchronous_commit = remote_apply")
1003+
master.set_synchronous_standbys(First(1, [standby]))
1004+
master.restart()
1005+
1006+
"""
1007+
ifisinstance(standbys,Iterable):
1008+
standbys=First(1,standbys)
1009+
1010+
self.append_conf("synchronous_standby_names = '{}'".format(standbys))
1011+
9821012
defcatchup(self,dbname=None,username=None):
9831013
"""
9841014
Wait until async replica catches up with its master.

‎testgres/standby.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# coding: utf-8
2+
3+
importsix
4+
5+
6+
@six.python_2_unicode_compatible
7+
classFirst:
8+
"""
9+
Specifies a priority-based synchronous replication and makes transaction
10+
commits wait until their WAL records are replicated to ``num_sync``
11+
synchronous standbys chosen based on their priorities.
12+
13+
Args:
14+
sync_num (int): the number of standbys that transaction need to wait
15+
for replies from
16+
standbys (:obj:`list` of :class:`.PostgresNode`): the list of standby
17+
nodes
18+
"""
19+
20+
def__init__(self,sync_num,standbys):
21+
self.sync_num=sync_num
22+
self.standbys=standbys
23+
24+
def__str__(self):
25+
returnu"{} ({})".format(self.sync_num,u", ".join(
26+
u"\"{}\"".format(r.name)forrinself.standbys))
27+
28+
29+
@six.python_2_unicode_compatible
30+
classAny:
31+
"""
32+
Specifies a quorum-based synchronous replication and makes transaction
33+
commits wait until their WAL records are replicated to at least ``num_sync``
34+
listed standbys. Only available for Postgres 10 and newer.
35+
36+
Args:
37+
sync_num (int): the number of standbys that transaction need to wait
38+
for replies from
39+
standbys (:obj:`list` of :class:`.PostgresNode`): the list of standby
40+
nodes
41+
"""
42+
43+
def__init__(self,sync_num,standbys):
44+
self.sync_num=sync_num
45+
self.standbys=standbys
46+
47+
def__str__(self):
48+
returnu"ANY {} ({})".format(self.sync_num,u", ".join(
49+
u"\"{}\"".format(r.name)forrinself.standbys))

‎tests/test_simple.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
fromtestgresimportbound_ports
4343
fromtestgres.utilsimportpg_version_ge
4444
fromtestgres.enumsimportProcessType
45+
fromtestgres.standbyimportFirst,Any
4546

4647

4748
defutil_exists(util):
@@ -388,6 +389,38 @@ def test_replicate(self):
388389
res=node.execute('select * from test')
389390
self.assertListEqual(res, [])
390391

392+
deftest_synchronous_replication(self):
393+
withget_new_node()asmaster:
394+
master.init(allow_streaming=True).start()
395+
master.append_conf('synchronous_commit = remote_apply')
396+
397+
# create standby
398+
withmaster.replicate()asstandby1,master.replicate()asstandby2:
399+
standby1.start()
400+
standby2.start()
401+
402+
# check formatting
403+
self.assertEqual('1 ("{}", "{}")'.format(
404+
standby1.name,standby2.name),
405+
str(First(1, (standby1,standby2))))
406+
self.assertEqual('ANY 1 ("{}", "{}")'.format(
407+
standby1.name,standby2.name),
408+
str(Any(1, (standby1,standby2))))
409+
410+
# set synchronous_standby_names
411+
master.set_synchronous_standbys([standby1,standby2])
412+
master.restart()
413+
master.safe_psql('create table abc(a int)')
414+
415+
# Create a large transaction that will take some time to apply
416+
# on standby to check that it applies synchronously
417+
# (If set synchronous_commit to 'on' or other lower level then
418+
# standby most likely won't catchup so fast and test will fail)
419+
master.safe_psql(
420+
'insert into abc select generate_series(1, 1000000)')
421+
res=standby1.safe_psql('select count(*) from abc')
422+
self.assertEqual(res,b'1000000\n')
423+
391424
deftest_replication_slots(self):
392425
withget_new_node()asnode:
393426
node.init(allow_streaming=True).start()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp