From 1e510fd08a29dd76114d60c050a54043903a346c Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 03:01:56 +0300 Subject: [PATCH 01/46] Deploy pg from our repo --- tests/deploy/roles/postgres/tasks/main.yml | 116 +++++++++------------ tests/deploy/roles/postgres/vars/main.yml | 6 +- tests/deploy/tsdm.yml | 17 +-- 3 files changed, 65 insertions(+), 74 deletions(-) diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 8e6660d..517dbd9 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -31,79 +31,65 @@ sudo: yes - name: clone postgres sources - git: repo=git://git.postgresql.org/git/postgresql.git + git: repo={{pg_repo}} dest={{pg_src}} version={{pg_version_tag}} - force=yes - update=yes depth=1 accept_hostkey=True register: pg_sources -- name: upload patches - get_url: "url={{pg_patch}} dest={{pg_src}}/p1.patch" - # when: pg_sources.before != pg_sources.after - -- name: patch postgres - patch: > - src={{pg_src}}/p1.patch - basedir={{pg_src}} - remote_src=True - strip=1 - - ############################################################################# -# - stat: path={{pg_datadir}}/postmaster.pid -# register: pg_pidfile - -# - name: stop postgres if it was running -# command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" -# when: pg_pidfile.stat.exists - -# - name: force rebuild on changed sources -# command: "rm {{pg_dst}}/bin/postgres" -# when: pg_sources.changed - -# - name: build and install -# shell: ./configure --prefix={{pg_dst}} --without-zlib && make clean && make -j {{makejobs}} && make install -# args: -# chdir: "{{pg_src}}" -# creates: "{{pg_dst}}/bin/postgres" - -# - name: remove datadirs on datanodes -# command: "rm -rf {{pg_datadir}}" -# when: pg_destroy_and_init - -# - name: create datadirs on datanodes -# command: "{{pg_dst}}/bin/initdb {{pg_datadir}}" -# args: -# creates: "{{pg_datadir}}" - -# - name: configure postgres on datanodes -# lineinfile: -# dest: "{{pg_datadir}}/postgresql.conf" -# line: "{{item.line}}" -# state: present -# with_items: "{{pg_config}}" - -# - name: configure postgres on datanodes -- 2 -# lineinfile: -# dest: "{{pg_datadir}}/postgresql.conf" -# line: "{{item.line}}" -# state: present -# with_items: "{{pg_config_role}}" - -# - name: enable blind trust on datanodes -# lineinfile: -# dest: "{{pg_datadir}}/pg_hba.conf" -# line: "host all all 0.0.0.0/0 trust" - -# # - include: pg_shard.yml -# # when: deploy_pg_shard - -# - name: start postgrespro -# command: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" +- stat: path={{pg_datadir}}/postmaster.pid + register: pg_pidfile + +- name: stop postgres if it was running + command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" + when: pg_pidfile.stat.exists + +- name: force rebuild on changed sources + command: "rm {{pg_dst}}/bin/postgres" + when: pg_sources.changed + +- name: build and install + shell: ./configure --prefix={{pg_dst}} --without-zlib && make clean && make -j {{makejobs}} && make install + args: + chdir: "{{pg_src}}" + creates: "{{pg_dst}}/bin/postgres" + +- name: remove datadirs on datanodes + command: "rm -rf {{pg_datadir}}" + when: pg_destroy_and_init + +- name: create datadirs on datanodes + command: "{{pg_dst}}/bin/initdb {{pg_datadir}}" + args: + creates: "{{pg_datadir}}" + +- name: configure postgres on datanodes + lineinfile: + dest: "{{pg_datadir}}/postgresql.conf" + line: "{{item.line}}" + state: present + with_items: "{{pg_config}}" + +- name: configure postgres on datanodes -- 2 + lineinfile: + dest: "{{pg_datadir}}/postgresql.conf" + line: "{{item.line}}" + state: present + with_items: "{{pg_config_role}}" + +- name: enable blind trust on datanodes + lineinfile: + dest: "{{pg_datadir}}/pg_hba.conf" + line: "host all all 0.0.0.0/0 trust" + +# - include: pg_shard.yml +# when: deploy_pg_shard + +- name: start postgrespro + command: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 1fe0ff6..e3059ee 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -6,9 +6,13 @@ deploy_postgres: false deploy_dtm: false deploy_pg_shard: false +pg_repo: git://git.postgresql.org/git/postgresql.git +pg_version_tag: master + + pg_destroy_and_init: false -pg_version_tag: master + pg_port: 5432 pg_dtm_enable: false pg_dtm_host: "127.0.0.1" diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 4e10236..e997e04 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -6,17 +6,17 @@ - role: postgres pg_port: 15432 - pg_version_tag: REL9_5_BETA1 + pg_repo: https://github.com/kelvich/postgresql.git + pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data - pg_patch: https://raw.githubusercontent.com/postgrespro/pg_dtm/master/xtm.patch - role: postgres pg_port: 15433 - pg_version_tag: REL9_5_BETA1 + pg_repo: https://github.com/kelvich/postgresql.git + pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data2 - pg_patch: https://raw.githubusercontent.com/postgrespro/pg_dtm/master/xtm.patch tasks: @@ -28,7 +28,7 @@ register: dtm_sources - name: build dtm - shell: "PG_CONFIG={{pg_dst}}/bin/pg_config && make clean && make -j {{makejobs}} install" + shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" args: chdir: ./pg_tsdtm when: dtm_sources.changed @@ -40,7 +40,8 @@ line: "shared_preload_libraries = 'pg_dtm'" state: present - - name: start postgrespro - command: "{{pg_dst}}/bin/pg_ctl restart -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" - + - name: restart postgrespro1 + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" + - name: restart postgrespro2 + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" From e9491d80156d1a16b74992bc4e07d2dfcff48604 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 12:46:24 +0300 Subject: [PATCH 02/46] delete .so and .o --- pg_dtm.o | Bin 53712 -> 0 bytes pg_dtm.so | Bin 25956 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pg_dtm.o delete mode 100755 pg_dtm.so diff --git a/pg_dtm.o b/pg_dtm.o deleted file mode 100644 index 519cd7cdb2f0e1e33ed59e723b20a74fcf7f591c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53712 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 E1n-SLHvj+t From 3190eba2e4f5cd3afe3f07fa67cd6ef527c20fdd Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 14:14:01 +0300 Subject: [PATCH 03/46] automate tests --- .gitignore | 6 ++++++ tests/deploy/cluster.yml | 38 ++++++++++++++++++++++++++++++++++++++ tests/deploy/hosts | 11 ++++++++--- tests/deploy/hosts.sample | 8 ++++++++ tests/perf.yml | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 tests/deploy/cluster.yml create mode 100644 tests/deploy/hosts.sample create mode 100644 tests/perf.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c321a93 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +**/*.o +**/*.so +tests/perf/pref +tests/perf/pref.linux + + diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml new file mode 100644 index 0000000..ec1fc6d --- /dev/null +++ b/tests/deploy/cluster.yml @@ -0,0 +1,38 @@ +--- + +- hosts: nodes + + roles: + + - role: postgres + pg_port: 15432 + pg_repo: https://github.com/kelvich/postgresql.git + pg_version_tag: xtm_patched + pg_destroy_and_init: true + pg_datadir: ./postgrespro-data + + tasks: + + - name: clone dtm sources + git: repo=https://github.com/kelvich/pg_tsdtm.git + dest=./pg_tsdtm + accept_hostkey=yes + update=yes + force=yes + register: dtm_sources + + - name: build dtm + shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make clean && PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" + args: + chdir: ./pg_tsdtm + when: dtm_sources.changed + + - name: enable dtm extension on datanodes + lineinfile: + dest: "{{pg_datadir}}/postgresql.conf" + regexp: "^shared_preload_libraries " + line: "shared_preload_libraries = 'pg_dtm'" + state: present + + - name: restart postgrespro + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" diff --git a/tests/deploy/hosts b/tests/deploy/hosts index 8ae34b7..899ec64 100644 --- a/tests/deploy/hosts +++ b/tests/deploy/hosts @@ -1,8 +1,13 @@ [clients] -localhost +158.250.29.4 ansible_ssh_user=cluster offset=6001 +158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=3001 [nodes] -localhost +158.250.29.5 ansible_ssh_user=cluster offset=5001 +158.250.29.6 ansible_ssh_user=cluster offset=4001 +158.250.29.8 ansible_ssh_user=cluster offset=2001 +158.250.29.9 ansible_ssh_user=cluster offset=1001 +158.250.29.10 ansible_ssh_user=cluster offset=1 [master] -localhost +158.250.29.10 ansible_ssh_user=cluster offset=1 diff --git a/tests/deploy/hosts.sample b/tests/deploy/hosts.sample new file mode 100644 index 0000000..61a49c3 --- /dev/null +++ b/tests/deploy/hosts.sample @@ -0,0 +1,8 @@ +[clients] +client1 ansible_ssh_user=cluster offset=6001 + +[nodes] +nodes1 ansible_ssh_user=cluster offset=2001 + +[master] +master1 ansible_ssh_user=cluster offset=1 diff --git a/tests/perf.yml b/tests/perf.yml new file mode 100644 index 0000000..fd70263 --- /dev/null +++ b/tests/perf.yml @@ -0,0 +1,36 @@ +--- + +- hosts: clients + gather_facts: no + tasks: + + - name: generate connstrings + set_fact: + connstr: "-C 'host={{item}} user=cluster port=15432 dbname=postgres' " + with_items: + groups['nodes'] | reverse | batch(nnodes | d(2) | int) | first + register: connstrs + + - name: make a list + set_fact: + connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" + + - name: copy transfers binary + copy: src=perf/perf.linux dest=~/perf mode=a+x + +- hosts: clients[0] + gather_facts: no + tasks: + - name: fill the databases + shell: "./perf {{connections}} -g -i" + register: transfers_result + - debug: "var=transfers_result" + +- hosts: clients[0] + gather_facts: no + tasks: + - name: run transfers + shell: "./perf {{connections}} {{runkeys | d('-g -w 64 -r 1 -n 1000 -a 10000')}}" + register: transfers_result + - debug: var=transfers_result + From 7bb81cff952ece29b2390a2da7489c83587879c7 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 14:29:13 +0300 Subject: [PATCH 04/46] transfers.go bugs --- tests/perf/transfers.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/perf/transfers.go b/tests/perf/transfers.go index 91c6886..b5e6544 100644 --- a/tests/perf/transfers.go +++ b/tests/perf/transfers.go @@ -39,7 +39,6 @@ func (t TransfersTS) prepare_one(connstr string, wg *sync.WaitGroup) { exec(conn, "insert into t (select generate_series(0,$1-1), $2)", cfg.AccountsNum, 0) - exec(conn, "commit") wg.Done() } @@ -134,9 +133,6 @@ func (t TransfersTS) reader(wg *sync.WaitGroup, cFetches chan int, inconsistency snapshot = _execQuery(conn, "select dtm_access($1)", snapshot) } } - - exec(conn, "begin transaction isolation level " + cfg.Isolation) - sum += _execQuery(conn, "select sum(v) from t") } for _, conn := range conns { From f25f685abadd22a3a4ca046b6d2d59e5b91d3500 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 14:53:45 +0300 Subject: [PATCH 05/46] fix local deploy --- tests/deploy/tsdm.yml | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index e997e04..71f8ccb 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -5,19 +5,26 @@ roles: - role: postgres - pg_port: 15432 + pg_port: 5432 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data - role: postgres - pg_port: 15433 + pg_port: 5433 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data2 + - role: postgres + pg_port: 5433 + pg_repo: https://github.com/kelvich/postgresql.git + pg_version_tag: xtm_patched + pg_destroy_and_init: true + pg_datadir: ./postgrespro-data3 + tasks: - name: clone dtm sources @@ -35,7 +42,21 @@ - name: enable dtm extension on datanodes lineinfile: - dest: "{{pg_datadir}}/postgresql.conf" + dest: "postgrespro-data/postgresql.conf" + regexp: "^shared_preload_libraries " + line: "shared_preload_libraries = 'pg_dtm'" + state: present + + - name: enable dtm extension on datanodes + lineinfile: + dest: "postgrespro-data2/postgresql.conf" + regexp: "^shared_preload_libraries " + line: "shared_preload_libraries = 'pg_dtm'" + state: present + + - name: enable dtm extension on datanodes + lineinfile: + dest: "postgrespro-data3/postgresql.conf" regexp: "^shared_preload_libraries " line: "shared_preload_libraries = 'pg_dtm'" state: present @@ -44,4 +65,8 @@ command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" - name: restart postgrespro2 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data2 -l ./postgrespro-data/pg.log" + + - name: restart postgrespro3 + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data3 -l ./postgrespro-data/pg.log" + From 1cfcad8f178fea50f0da4e420e97aeb24bf46e8f Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 14:57:43 +0300 Subject: [PATCH 06/46] fix roles --- tests/deploy/roles/postgres/vars/main.yml | 4 ++-- tests/deploy/tsdm.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index e3059ee..22631bc 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -27,9 +27,9 @@ pg_config: - line: "port = {{pg_port}}" pg_config_role: - line: "#pg_config_role" -pg_src: ./postgrespro +pg_src: ~/postgrespro pg_dst: /tmp/postgrespro-build -pg_datadir: ./postgrespro-data +pg_datadir: ~/postgrespro-data libuv: version: v1.7.5 diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 71f8ccb..5885191 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -9,21 +9,21 @@ pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true - pg_datadir: ./postgrespro-data + pg_datadir: ~/postgrespro-data - role: postgres pg_port: 5433 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true - pg_datadir: ./postgrespro-data2 + pg_datadir: ~/postgrespro-data2 - role: postgres - pg_port: 5433 + pg_port: 5434 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true - pg_datadir: ./postgrespro-data3 + pg_datadir: ~/postgrespro-data3 tasks: From a222a72d7ef1df30a964d2a291d256da0f8bbb9f Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 15:14:30 +0300 Subject: [PATCH 07/46] local deploy fixes --- tests/deploy/roles/postgres/vars/main.yml | 2 +- tests/deploy/tsdm.yml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 22631bc..7f2cb83 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -22,7 +22,7 @@ pg_config: - line: "fsync = off" - line: "autovacuum = off" - line: "listen_addresses = '*'" - - line: "max_connections = 2048" + - line: "max_connections = 512" - line: "max_prepared_transactions = 400" - line: "port = {{pg_port}}" pg_config_role: diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 5885191..f42dd51 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -29,7 +29,7 @@ - name: clone dtm sources git: repo=https://github.com/kelvich/pg_tsdtm.git - dest=./pg_tsdtm + dest=./pg_tsdtm_test accept_hostkey=yes update=yes register: dtm_sources @@ -37,36 +37,36 @@ - name: build dtm shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" args: - chdir: ./pg_tsdtm + chdir: ./pg_tsdtm_test when: dtm_sources.changed - name: enable dtm extension on datanodes lineinfile: - dest: "postgrespro-data/postgresql.conf" + dest: "~/postgrespro-data/postgresql.conf" regexp: "^shared_preload_libraries " line: "shared_preload_libraries = 'pg_dtm'" state: present - name: enable dtm extension on datanodes lineinfile: - dest: "postgrespro-data2/postgresql.conf" + dest: "~/postgrespro-data2/postgresql.conf" regexp: "^shared_preload_libraries " line: "shared_preload_libraries = 'pg_dtm'" state: present - name: enable dtm extension on datanodes lineinfile: - dest: "postgrespro-data3/postgresql.conf" + dest: "~/postgrespro-data3/postgresql.conf" regexp: "^shared_preload_libraries " line: "shared_preload_libraries = 'pg_dtm'" state: present - name: restart postgrespro1 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data -l ~/postgrespro-data/pg.log" - name: restart postgrespro2 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data2 -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data2 -l ~/postgrespro-data/pg.log" - name: restart postgrespro3 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data3 -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data3 -l ~/postgrespro-data/pg.log" From 412ccb4813b1b929615582d570d8ae14577344b9 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 15:15:19 +0300 Subject: [PATCH 08/46] gi --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index c321a93..e185144 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -**/*.o -**/*.so tests/perf/pref tests/perf/pref.linux From b976bef03e5d5b89a0f0c479ca0003f06c9d9c9a Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 15:19:43 +0300 Subject: [PATCH 09/46] perf --- tests/run_perf.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/run_perf.sh b/tests/run_perf.sh index dd16f43..46dd259 100644 --- a/tests/run_perf.sh +++ b/tests/run_perf.sh @@ -1,4 +1,11 @@ -go run *.go \ +go run perf/*.go \ -C "dbname=postgres port=5432 sslmode=disable" \ -C "dbname=postgres port=5433 sslmode=disable" \ --g -w 8 -r 1 -n 1000 -a 1000 -i +-C "dbname=postgres port=5434 sslmode=disable" \ +-g -w 8 -r 1 -n 1000 -a 10000 -i + +go run perf/*.go \ +-C "dbname=postgres port=5432 sslmode=disable" \ +-C "dbname=postgres port=5433 sslmode=disable" \ +-C "dbname=postgres port=5434 sslmode=disable" \ +-g -w 8 -r 1 -n 1000 -a 10000 From c1e62b0f7932d63852060f079878f5f73c0ce3b3 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 15:25:14 +0300 Subject: [PATCH 10/46] clean before make --- tests/deploy/tsdm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 5885191..120c57a 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -35,7 +35,7 @@ register: dtm_sources - name: build dtm - shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" + shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make clean && PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" args: chdir: ./pg_tsdtm when: dtm_sources.changed From b293a3efe11b078a23fe8c0a65b4e85b45ab14a0 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 15:28:38 +0300 Subject: [PATCH 11/46] one relative path --- tests/deploy/tsdm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 00893a6..31e47b4 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -29,7 +29,7 @@ - name: clone dtm sources git: repo=https://github.com/kelvich/pg_tsdtm.git - dest=./pg_tsdtm_test + dest=~/pg_tsdtm_test accept_hostkey=yes update=yes register: dtm_sources @@ -37,7 +37,7 @@ - name: build dtm shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make clean && PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" args: - chdir: ./pg_tsdtm_test + chdir: ~/pg_tsdtm_test when: dtm_sources.changed - name: enable dtm extension on datanodes From 7a47f56ecc6649d8910b2e25dbadbd33427efaa7 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 15:40:17 +0300 Subject: [PATCH 12/46] abs path in perf.yml --- tests/perf.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index fd70263..83a0068 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -16,13 +16,13 @@ connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" - name: copy transfers binary - copy: src=perf/perf.linux dest=~/perf mode=a+x + copy: src=perf/perf.linux dest=~/perf mode=0755 - hosts: clients[0] gather_facts: no tasks: - name: fill the databases - shell: "./perf {{connections}} -g -i" + shell: "~/perf {{connections}} -g -i" register: transfers_result - debug: "var=transfers_result" @@ -30,7 +30,7 @@ gather_facts: no tasks: - name: run transfers - shell: "./perf {{connections}} {{runkeys | d('-g -w 64 -r 1 -n 1000 -a 10000')}}" + shell: "~/perf {{connections}} {{runkeys | d('-g -w 64 -r 1 -n 1000 -a 10000')}}" register: transfers_result - debug: var=transfers_result From f9a1b2a658ea211d10584dc85894133f17612686 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 17:55:24 +0300 Subject: [PATCH 13/46] Correctly handle case of equal connections --- tests/deploy/cluster.yml | 2 ++ tests/deploy/roles/postgres/vars/main.yml | 4 ++-- tests/deploy/tsdm.yml | 19 +------------------ tests/perf/transfers.go | 11 ++++++----- tests/run_perf.sh | 6 ++---- 5 files changed, 13 insertions(+), 29 deletions(-) mode change 100644 => 100755 tests/run_perf.sh diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index ec1fc6d..79e7e2b 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -10,6 +10,8 @@ pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data + pg_config_role: + - line: "dtm.vacuum_delay=10" tasks: diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 7f2cb83..2a73cea 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -22,8 +22,8 @@ pg_config: - line: "fsync = off" - line: "autovacuum = off" - line: "listen_addresses = '*'" - - line: "max_connections = 512" - - line: "max_prepared_transactions = 400" + - line: "max_connections = 2048" + - line: "max_prepared_transactions = 4000" - line: "port = {{pg_port}}" pg_config_role: - line: "#pg_config_role" diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 31e47b4..8bfadc8 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -18,13 +18,6 @@ pg_destroy_and_init: true pg_datadir: ~/postgrespro-data2 - - role: postgres - pg_port: 5434 - pg_repo: https://github.com/kelvich/postgresql.git - pg_version_tag: xtm_patched - pg_destroy_and_init: true - pg_datadir: ~/postgrespro-data3 - tasks: - name: clone dtm sources @@ -54,19 +47,9 @@ line: "shared_preload_libraries = 'pg_dtm'" state: present - - name: enable dtm extension on datanodes - lineinfile: - dest: "~/postgrespro-data3/postgresql.conf" - regexp: "^shared_preload_libraries " - line: "shared_preload_libraries = 'pg_dtm'" - state: present - - name: restart postgrespro1 command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data -l ~/postgrespro-data/pg.log" - name: restart postgrespro2 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data2 -l ~/postgrespro-data/pg.log" - - - name: restart postgrespro3 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data3 -l ~/postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data2 -l ~/postgrespro-data2/pg.log" diff --git a/tests/perf/transfers.go b/tests/perf/transfers.go index b5e6544..90d762c 100644 --- a/tests/perf/transfers.go +++ b/tests/perf/transfers.go @@ -67,13 +67,14 @@ func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *syn gtid := strconv.Itoa(id) + "." + strconv.Itoa(i) amount := 2*rand.Intn(2) - 1 - from_acc := cfg.Writers.StartId + 2*id + 1 - to_acc := cfg.Writers.StartId + 2*id + 2 - + from_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 1 + to_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 2 + conn1 := conns[rand.Intn(len(conns))] conn2 := conns[rand.Intn(len(conns))] - if conn1 == conn2 { - continue + for conn1 == conn2 { + conn1 = conns[rand.Intn(len(conns))] + conn2 = conns[rand.Intn(len(conns))] } exec(conn1, "begin transaction") diff --git a/tests/run_perf.sh b/tests/run_perf.sh old mode 100644 new mode 100755 index 46dd259..cec51c4 --- a/tests/run_perf.sh +++ b/tests/run_perf.sh @@ -1,11 +1,9 @@ go run perf/*.go \ -C "dbname=postgres port=5432 sslmode=disable" \ -C "dbname=postgres port=5433 sslmode=disable" \ --C "dbname=postgres port=5434 sslmode=disable" \ --g -w 8 -r 1 -n 1000 -a 10000 -i +-g -w 64 -r 1 -n 10000 -a 10000 -i go run perf/*.go \ -C "dbname=postgres port=5432 sslmode=disable" \ -C "dbname=postgres port=5433 sslmode=disable" \ --C "dbname=postgres port=5434 sslmode=disable" \ --g -w 8 -r 1 -n 1000 -a 10000 +-g -w 64 -r 1 -n 10000 -a 10000 From d21ad6636c639fbae131f49737d811e8b8cf4e87 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 18:41:26 +0300 Subject: [PATCH 14/46] Change DtmAdjustOldestXid --- pg_dtm.c | 4 ++++ tests/deploy/cluster.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pg_dtm.c b/pg_dtm.c index b60012c..90528ce 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -393,6 +393,10 @@ static TransactionId DtmAdjustOldestXid(TransactionId xid) DtmTransStatus *ts, *prev = NULL; timestamp_t cutoff_time = dtm_get_current_time() - DtmVacuumDelay*USEC; SpinLockAcquire(&local->lock); + ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + if (ts != NULL) { + cutoff_time = ts->cid - DtmVacuumDelay*USEC; + } for (ts = local->trans_list_head; ts != NULL && ts->cid < cutoff_time; prev = ts, ts = ts->next) { if (prev != NULL) { hash_search(xid2status, &prev->xid, HASH_REMOVE, NULL); diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 79e7e2b..84520da 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -11,7 +11,7 @@ pg_destroy_and_init: true pg_datadir: ./postgrespro-data pg_config_role: - - line: "dtm.vacuum_delay=10" + - line: "dtm.vacuum_delay=60" tasks: From c752b7994b9ccb53de07e5ac144f7de09e8af3f7 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 18:57:54 +0300 Subject: [PATCH 15/46] fixes --- tests/deploy/hosts | 3 +++ tests/deploy/roles/postgres/tasks/main.yml | 2 +- tests/perf.yml | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/deploy/hosts b/tests/deploy/hosts index 899ec64..c9d4501 100644 --- a/tests/deploy/hosts +++ b/tests/deploy/hosts @@ -11,3 +11,6 @@ [master] 158.250.29.10 ansible_ssh_user=cluster offset=1 + +[local] +localhost diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 517dbd9..6df0e0d 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -48,7 +48,7 @@ when: pg_pidfile.stat.exists - name: force rebuild on changed sources - command: "rm {{pg_dst}}/bin/postgres" + command: "rm -f {{pg_dst}}/bin/postgres" when: pg_sources.changed - name: build and install diff --git a/tests/perf.yml b/tests/perf.yml index 83a0068..69d02a5 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -1,6 +1,6 @@ --- -- hosts: clients +- hosts: clients[0] gather_facts: no tasks: @@ -30,7 +30,7 @@ gather_facts: no tasks: - name: run transfers - shell: "~/perf {{connections}} {{runkeys | d('-g -w 64 -r 1 -n 1000 -a 10000')}}" + shell: "~/perf {{connections}} {{runkeys | d('-g -w 8 -r 1 -n 1000 -a 10000')}}" register: transfers_result - debug: var=transfers_result From cabe53cef392eaccaf33012d432c568dab8738a8 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 19:06:36 +0300 Subject: [PATCH 16/46] point ansible deploy to new repo --- tests/deploy/tsdm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 8bfadc8..9515868 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -21,7 +21,7 @@ tasks: - name: clone dtm sources - git: repo=https://github.com/kelvich/pg_tsdtm.git + git: repo=https://github.com/postgrespro/pg_tsdtm.git dest=~/pg_tsdtm_test accept_hostkey=yes update=yes From efeef65fcf2faa2aa42a43b1da5b8748e672da54 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 19:11:03 +0300 Subject: [PATCH 17/46] Separately report sleep time --- pg_dtm.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index 90528ce..fc276ad 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -115,9 +115,6 @@ static void dtm_sleep(timestamp_t interval) { struct timespec ts; struct timespec rem; -#if TRACE_SLEEP_TIME - timestamp_t now = dtm_get_current_time(); -#endif ts.tv_sec = 0; ts.tv_nsec = interval*1000; @@ -126,17 +123,6 @@ static void dtm_sleep(timestamp_t interval) Assert(errno == EINTR); ts = rem; } -#if TRACE_SLEEP_TIME - totalSleepTime += dtm_get_current_time() - now; - if (now > prevReportTime + USEC*10) { - prevReportTime = now; - if (firstReportTime == 0) { - firstReportTime = now; - } else { - fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); - } - } -#endif } static cid_t dtm_get_cid() @@ -155,7 +141,23 @@ static cid_t dtm_sync(cid_t global_cid) cid_t local_cid; while ((local_cid = dtm_get_cid()) < global_cid) { SpinLockRelease(&local->lock); +#if TRACE_SLEEP_TIME + { + timestamp_t now = dtm_get_current_time(); +#endif dtm_sleep(global_cid - local_cid); +#if TRACE_SLEEP_TIME + totalSleepTime += dtm_get_current_time() - now; + if (now > prevReportTime + USEC*10) { + prevReportTime = now; + if (firstReportTime == 0) { + firstReportTime = now; + } else { + fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + } + } + } +#endif SpinLockAcquire(&local->lock); } return global_cid; @@ -449,7 +451,23 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) { DTM_TRACE((stderr, "%d: wait for in-doubt transaction %u in snapshot %lu\n", getpid(), xid, dtm_tx.snapshot)); SpinLockRelease(&local->lock); +#if TRACE_SLEEP_TIME + { + timestamp_t now = dtm_get_current_time(); +#endif dtm_sleep(delay); +#if TRACE_SLEEP_TIME + totalSleepTime += dtm_get_current_time() - now; + if (now > prevReportTime + USEC*10) { + prevReportTime = now; + if (firstReportTime == 0) { + firstReportTime = now; + } else { + fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + } + } + } +#endif if (delay*2 <= MAX_WAIT_TIMEOUT) { delay *= 2; } From a7f967403d04f09003f07ae60d5133692035a946 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 19:22:36 +0300 Subject: [PATCH 18/46] Separately report sleep time --- pg_dtm.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index fc276ad..9c559e3 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -74,9 +74,6 @@ static HTAB* xid2status; static HTAB* gtid2xid; static DtmNodeState* local; static DtmTransState dtm_tx; -static timestamp_t firstReportTime; -static timestamp_t prevReportTime; -static timestamp_t totalSleepTime; static uint64 totalSleepInterrupts; static int DtmVacuumDelay; @@ -144,6 +141,9 @@ static cid_t dtm_sync(cid_t global_cid) #if TRACE_SLEEP_TIME { timestamp_t now = dtm_get_current_time(); + static timestamp_t firstReportTime; + static timestamp_t prevReportTime; + static timestamp_t totalSleepTime; #endif dtm_sleep(global_cid - local_cid); #if TRACE_SLEEP_TIME @@ -153,7 +153,7 @@ static cid_t dtm_sync(cid_t global_cid) if (firstReportTime == 0) { firstReportTime = now; } else { - fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + fprintf(stderr, "Sync sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); } } } @@ -405,8 +405,9 @@ static TransactionId DtmAdjustOldestXid(TransactionId xid) } } if (prev != NULL) { + *(int*)0 = 0; local->trans_list_head = prev; - xid = prev->xid; + xid = prev->xid; } else { xid = FirstNormalTransactionId; } @@ -454,6 +455,9 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) #if TRACE_SLEEP_TIME { timestamp_t now = dtm_get_current_time(); + static timestamp_t firstReportTime; + static timestamp_t prevReportTime; + static timestamp_t totalSleepTime; #endif dtm_sleep(delay); #if TRACE_SLEEP_TIME @@ -463,7 +467,7 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) if (firstReportTime == 0) { firstReportTime = now; } else { - fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + fprintf(stderr, "Snapshot sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); } } } From 062a09ced7038899e3edee2d9908c5ecee1920d3 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 19:31:09 +0300 Subject: [PATCH 19/46] point to new repo#2 --- tests/deploy/cluster.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 84520da..6398609 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -16,7 +16,7 @@ tasks: - name: clone dtm sources - git: repo=https://github.com/kelvich/pg_tsdtm.git + git: repo=https://github.com/postgrespro/pg_tsdtm.git dest=./pg_tsdtm accept_hostkey=yes update=yes From dc88d68e3c2aa700bd626e9d2d585ed1a84e26c2 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 20:02:15 +0300 Subject: [PATCH 20/46] copy go sources to the server instead of pre-built binary --- tests/perf.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index 69d02a5..35f1402 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -16,13 +16,16 @@ connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" - name: copy transfers binary - copy: src=perf/perf.linux dest=~/perf mode=0755 + copy: src=./perf/{{item}} dest=~/{{item}} mode=0755 + with_items: + - "perf.go" + - "transfers.go" - hosts: clients[0] gather_facts: no tasks: - name: fill the databases - shell: "~/perf {{connections}} -g -i" + shell: "go run ~/perf.go ~/transfers.go {{connections}} -g -i" register: transfers_result - debug: "var=transfers_result" @@ -30,7 +33,7 @@ gather_facts: no tasks: - name: run transfers - shell: "~/perf {{connections}} {{runkeys | d('-g -w 8 -r 1 -n 1000 -a 10000')}}" + shell: "go run ~/perf.go ~/transfers.go {{connections}} {{runkeys | d('-g -w 400 -r 1 -n 1000 -a 100000')}}" register: transfers_result - debug: var=transfers_result From dfd867005d1acfd3288d01ee169f9f5aa3b4a0ad Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 20:22:35 +0300 Subject: [PATCH 21/46] Undo Assert --- pg_dtm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/pg_dtm.c b/pg_dtm.c index 9c559e3..51e84ad 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -405,7 +405,6 @@ static TransactionId DtmAdjustOldestXid(TransactionId xid) } } if (prev != NULL) { - *(int*)0 = 0; local->trans_list_head = prev; xid = prev->xid; } else { From f17aa84a8776dc4ef469dead762eb0d6b4f09a64 Mon Sep 17 00:00:00 2001 From: knizhnik Date: Sun, 8 Nov 2015 00:35:42 +0300 Subject: [PATCH 22/46] Add dtmbench --- tests/dtmbench.cpp | 273 ++++++++++++++++++++++++++++++++++++++++ tests/makefile | 10 ++ tests/perf/perf.go | 15 +++ tests/perf/run.sh | 5 + tests/perf/transfers.go | 50 +++++--- tests/run.sh | 5 + 6 files changed, 338 insertions(+), 20 deletions(-) create mode 100644 tests/dtmbench.cpp create mode 100644 tests/makefile create mode 100755 tests/perf/run.sh create mode 100755 tests/run.sh diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp new file mode 100644 index 0000000..af4b421 --- /dev/null +++ b/tests/dtmbench.cpp @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +using namespace std; +using namespace pqxx; + +template +class unique_ptr +{ + T* ptr; + + public: + unique_ptr(T* p = NULL) : ptr(p) {} + ~unique_ptr() { delete ptr; } + T& operator*() { return *ptr; } + T* operator->() { return ptr; } + void operator=(T* p) { ptr = p; } + void operator=(unique_ptr& other) { + ptr = other.ptr; + other.ptr = NULL; + } +}; + +typedef void* (*thread_proc_t)(void*); +typedef int64_t csn_t; + +struct thread +{ + pthread_t t; + size_t proceeded; + int id; + + void start(int tid, thread_proc_t proc) { + id = tid; + proceeded = 0; + pthread_create(&t, NULL, proc, this); + } + + void wait() { + pthread_join(t, NULL); + } +}; + +struct config +{ + int nReaders; + int nWriters; + int nIterations; + int nAccounts; + vector connections; + + config() { + nReaders = 1; + nWriters = 10; + nIterations = 1000; + nAccounts = 1000; + } +}; + +config cfg; +bool running; + +#define USEC 1000000 + +static time_t getCurrentTime() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (time_t)tv.tv_sec*USEC + tv.tv_usec; +} + + +void exec(transaction_base& txn, char const* sql, ...) +{ + va_list args; + va_start(args, sql); + char buf[1024]; + vsprintf(buf, sql, args); + va_end(args); + txn.exec(buf); +} + +int64_t execQuery( transaction_base& txn, char const* sql, ...) +{ + va_list args; + va_start(args, sql); + char buf[1024]; + vsprintf(buf, sql, args); + va_end(args); + result r = txn.exec(buf); + return r[0][0].as(int64_t()); +} + +void* reader(void* arg) +{ + thread& t = *(thread*)arg; + vector< unique_ptr > conns(cfg.connections.size()); + for (size_t i = 0; i < conns.size(); i++) { + conns[i] = new connection(cfg.connections[i]); + } + int64_t prevSum = 0; + + while (running) { + csn_t snapshot; + vector< unique_ptr > txns(conns.size()); + for (size_t i = 0; i < conns.size(); i++) { + txns[i] = new work(*conns[i]); + } + for (size_t i = 0; i < txns.size(); i++) { + if (i == 0) { + snapshot = execQuery(*txns[i], "select dtm_extend()"); + } else { + snapshot = execQuery(*txns[i], "select dtm_access(%ld)", snapshot); + } + } + int64_t sum = 0; + for (size_t i = 0; i < txns.size(); i++) { + sum += execQuery(*txns[i], "select sum(v) from t"); + } + if (sum != prevSum) { + printf("Total=%ld snapshot=%ld\n", sum, snapshot); + prevSum = sum; + } + t.proceeded += 1; + } + return NULL; +} + +void* writer(void* arg) +{ + thread& t = *(thread*)arg; + vector< unique_ptr > conns(cfg.connections.size()); + for (size_t i = 0; i < conns.size(); i++) { + conns[i] = new connection(cfg.connections[i]); + } + for (int i = 0; i < cfg.nIterations; i++) + { + char gtid[32]; + int srcCon, dstCon; + int srcAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; + int dstAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; + + sprintf(gtid, "%d.%d", t.id, i); + + do { + srcCon = random() % cfg.connections.size(); + dstCon = random() % cfg.connections.size(); + } while (srcCon == dstCon); + + nontransaction srcTx(*conns[srcCon]); + nontransaction dstTx(*conns[dstCon]); + + exec(srcTx, "begin transaction"); + exec(dstTx, "begin transaction"); + + csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); + snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); + + exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); + exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); + + exec(srcTx, "prepare transaction '%s'", gtid); + exec(dstTx, "prepare transaction '%s'", gtid); + exec(srcTx, "select dtm_begin_prepare('%s')", gtid); + exec(dstTx, "select dtm_begin_prepare('%s')", gtid); + csn_t csn = execQuery(srcTx, "select dtm_prepare('%s', 0)", gtid); + csn = execQuery(dstTx, "select dtm_prepare('%s', %ld)", gtid, csn); + exec(srcTx, "select dtm_end_prepare('%s', %ld)", gtid, csn); + exec(dstTx, "select dtm_end_prepare('%s', %ld)", gtid, csn); + exec(srcTx, "commit prepared '%s'", gtid); + exec(dstTx, "commit prepared '%s'", gtid); + + t.proceeded += 1; + } + return NULL; +} + +void initializeDatabase() +{ + for (size_t i = 0; i < cfg.connections.size(); i++) { + connection conn(cfg.connections[i]); + work txn(conn); + exec(txn, "drop extension if exists pg_dtm"); + exec(txn, "create extension pg_dtm"); + exec(txn, "drop table if exists t"); + exec(txn, "create table t(u int primary key, v int)"); + exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts, 0); + txn.commit(); + } +} + +int main (int argc, char* argv[]) +{ + bool initialize = false; + for (int i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 'r': + cfg.nReaders = atoi(argv[++i]); + continue; + case 'w': + cfg.nWriters = atoi(argv[++i]); + continue; + case 'a': + cfg.nAccounts = atoi(argv[++i]); + continue; + case 'n': + cfg.nIterations = atoi(argv[++i]); + continue; + case 'c': + cfg.connections.push_back(string(argv[++i])); + continue; + case 'i': + initialize = true; + continue; + } + } + printf("Options:\n" + "\t-r N\tnumber of readers (1)\n" + "\t-w N\tnumber of writers (10)\n" + "\t-a N\tnumber of accounts (1000)\n" + "\t-n N\tnumber of iterations (1000)\n" + "\t-c STR\tdatabase connection string\n" + "\t-i\tinitialize datanase\n"); + return 1; + } + if (initialize) { + initializeDatabase(); + } + + time_t start = getCurrentTime(); + running = true; + + vector readers(cfg.nReaders); + vector writers(cfg.nWriters); + size_t nReads = 0; + size_t nWrites = 0; + + for (int i = 0; i < cfg.nReaders; i++) { + readers[i].start(i, reader); + } + for (int i = 0; i < cfg.nWriters; i++) { + writers[i].start(i, writer); + } + + for (int i = 0; i < cfg.nWriters; i++) { + writers[i].wait(); + nWrites += writers[i].proceeded; + } + + running = false; + + for (int i = 0; i < cfg.nReaders; i++) { + readers[i].wait(); + nReads += writers[i].proceeded; + } + + time_t elapsed = getCurrentTime() - start; + printf("TPS(updates)=%f, TPS(selects)=%f\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed); + return 0; +} diff --git a/tests/makefile b/tests/makefile new file mode 100644 index 0000000..bcd7ee6 --- /dev/null +++ b/tests/makefile @@ -0,0 +1,10 @@ +CXX=g++ +CXXFLAGS=-g -Wall -O2 -pthread + +all: dtmbench + +dtmbench: dtmbench.cpp + $(CXX) $(CXXFLAGS) -o dtmbench dtmbench.cpp -lpqxx + +clean: + rm -f dtmbench \ No newline at end of file diff --git a/tests/perf/perf.go b/tests/perf/perf.go index 42bef7b..302aa8c 100644 --- a/tests/perf/perf.go +++ b/tests/perf/perf.go @@ -6,7 +6,9 @@ import ( "os" "sync" "time" + "runtime" "github.com/jackc/pgx" + "runtime/pprof" ) type ConnStrings []string @@ -28,6 +30,7 @@ var cfg struct { AccountsNum int ReadersNum int IterNum int + Profile string Writers struct { Num int @@ -99,6 +102,7 @@ func init() { "Show progress and other stuff for mortals") flag.BoolVar(&cfg.Parallel, "p", false, "Use parallel execs") + flag.StringVar(&cfg.Profile, "cpuprofile", "", "write cpu profile to file") repread := flag.Bool("l", false, "Use 'repeatable read' isolation level instead of 'read committed'") flag.Parse() @@ -129,6 +133,17 @@ func main() { fmt.Println("ERROR: This test needs at leas two connections") os.Exit(1) } + runtime.GOMAXPROCS(100) + + if cfg.Profile != "" { + f, err := os.Create(cfg.Profile) + if err != nil { + fmt.Println("Failed to create profile file") + os.Exit(1) + } + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + } // switch cfg.Backend { // case "transfers": diff --git a/tests/perf/run.sh b/tests/perf/run.sh new file mode 100755 index 0000000..4056ec3 --- /dev/null +++ b/tests/perf/run.sh @@ -0,0 +1,5 @@ +go run *.go \ +-C "dbname=postgres user=knizhnik port=5432 sslmode=disable" \ +-C "dbname=postgres user=knizhnik port=5433 sslmode=disable" \ +-C "dbname=postgres user=knizhnik port=5434 sslmode=disable" \ +-g -n 1000 -a 1000 -w 10 -r 1 $* diff --git a/tests/perf/transfers.go b/tests/perf/transfers.go index 90d762c..1fb1a62 100644 --- a/tests/perf/transfers.go +++ b/tests/perf/transfers.go @@ -47,6 +47,7 @@ func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *syn var nGlobalTrans = 0 var snapshot int64 var csn int64 + nWriters := cfg.Writers.Num if len(cfg.ConnStrs) == 1 { cfg.ConnStrs.Set(cfg.ConnStrs[0]) @@ -63,36 +64,45 @@ func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *syn for i := 0; i < cfg.IterNum; i++ { - - gtid := strconv.Itoa(id) + "." + strconv.Itoa(i) amount := 2*rand.Intn(2) - 1 - from_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 1 - to_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 2 - + //from_acc := cfg.Writers.StartId + 2*id + 1 + //to_acc := cfg.Writers.StartId + 2*id + 2 + from_acc := rand.Intn((cfg.AccountsNum-nWriters)/nWriters)*nWriters+id + to_acc := rand.Intn((cfg.AccountsNum-nWriters)/nWriters)*nWriters+id + + conn1 := conns[rand.Intn(len(conns))] conn2 := conns[rand.Intn(len(conns))] + for conn1 == conn2 { - conn1 = conns[rand.Intn(len(conns))] - conn2 = conns[rand.Intn(len(conns))] - } + conn1 = conns[rand.Intn(len(conns))] + conn2 = conns[rand.Intn(len(conns))] + } exec(conn1, "begin transaction") exec(conn2, "begin transaction") - snapshot = _execQuery(conn1, "select dtm_extend($1)", gtid) - snapshot = _execQuery(conn2, "select dtm_access($1, $2)", snapshot, gtid) + if cfg.UseDtm { + snapshot = _execQuery(conn1, "select dtm_extend($1)", gtid) + snapshot = _execQuery(conn2, "select dtm_access($1, $2)", snapshot, gtid) + } exec(conn1, "update t set v = v - $1 where u=$2", amount, from_acc) exec(conn2, "update t set v = v + $1 where u=$2", amount, to_acc) - exec(conn1, "prepare transaction '" + gtid + "'") - exec(conn2, "prepare transaction '" + gtid + "'") - exec(conn1, "select dtm_begin_prepare($1)", gtid) - exec(conn2, "select dtm_begin_prepare($1)", gtid) - csn = _execQuery(conn1, "select dtm_prepare($1, 0)", gtid) - csn = _execQuery(conn2, "select dtm_prepare($1, $2)", gtid, csn) - exec(conn1, "select dtm_end_prepare($1, $2)", gtid, csn) - exec(conn2, "select dtm_end_prepare($1, $2)", gtid, csn) - exec(conn1, "commit prepared '" + gtid + "'") - exec(conn2, "commit prepared '" + gtid + "'") + if cfg.UseDtm { + exec(conn1, "prepare transaction '" + gtid + "'") + exec(conn2, "prepare transaction '" + gtid + "'") + exec(conn1, "select dtm_begin_prepare($1)", gtid) + exec(conn2, "select dtm_begin_prepare($1)", gtid) + csn = _execQuery(conn1, "select dtm_prepare($1, 0)", gtid) + csn = _execQuery(conn2, "select dtm_prepare($1, $2)", gtid, csn) + exec(conn1, "select dtm_end_prepare($1, $2)", gtid, csn) + exec(conn2, "select dtm_end_prepare($1, $2)", gtid, csn) + exec(conn1, "commit prepared '" + gtid + "'") + exec(conn2, "commit prepared '" + gtid + "'") + } else { + exec(conn1, "commit") + exec(conn2, "commit") + } nGlobalTrans++ } diff --git a/tests/run.sh b/tests/run.sh new file mode 100755 index 0000000..6b9f342 --- /dev/null +++ b/tests/run.sh @@ -0,0 +1,5 @@ +./dtmbench \ +-c "dbname=postgres host=localhost user=knizhnik port=5432 sslmode=disable" \ +-c "dbname=postgres host=localhost user=knizhnik port=5433 sslmode=disable" \ +-c "dbname=postgres host=localhost user=knizhnik port=5434 sslmode=disable" \ +-n 1000 -a 1000 -w 10 -r 1 $* From ed4f3e360000d24f693f2aa1c507dd96c4c09da5 Mon Sep 17 00:00:00 2001 From: knizhnik Date: Sun, 8 Nov 2015 11:55:25 +0300 Subject: [PATCH 23/46] Fix bugs in dtmbench --- tests/dtmbench.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index af4b421..fe6c71d 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -196,7 +196,7 @@ void initializeDatabase() exec(txn, "create extension pg_dtm"); exec(txn, "drop table if exists t"); exec(txn, "create table t(u int primary key, v int)"); - exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts, 0); + exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts-1, 0); txn.commit(); } } @@ -264,7 +264,7 @@ int main (int argc, char* argv[]) for (int i = 0; i < cfg.nReaders; i++) { readers[i].wait(); - nReads += writers[i].proceeded; + nReads += readers[i].proceeded; } time_t elapsed = getCurrentTime() - start; From 754e495d6281335c190a247bcd9380074c3561a5 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Mon, 9 Nov 2015 12:34:49 +0300 Subject: [PATCH 24/46] perf.go: do not produce unused connections --- tests/perf.yml | 2 +- tests/perf/transfers.go | 66 ++++++++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index 35f1402..0a5442a 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -33,7 +33,7 @@ gather_facts: no tasks: - name: run transfers - shell: "go run ~/perf.go ~/transfers.go {{connections}} {{runkeys | d('-g -w 400 -r 1 -n 1000 -a 100000')}}" + shell: "go run ~/perf.go ~/transfers.go {{connections}} {{runkeys | d('-g -w 200 -r 1 -n 1000 -a 100000')}}" register: transfers_result - debug: var=transfers_result diff --git a/tests/perf/transfers.go b/tests/perf/transfers.go index 90d762c..78cb9c7 100644 --- a/tests/perf/transfers.go +++ b/tests/perf/transfers.go @@ -43,7 +43,6 @@ func (t TransfersTS) prepare_one(connstr string, wg *sync.WaitGroup) { } func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *sync.WaitGroup) { - var conns []*pgx.Conn var nGlobalTrans = 0 var snapshot int64 var csn int64 @@ -52,45 +51,64 @@ func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *syn cfg.ConnStrs.Set(cfg.ConnStrs[0]) } - for _, connstr := range cfg.ConnStrs { - dbconf, err := pgx.ParseDSN(connstr) - checkErr(err) - conn, err := pgx.Connect(dbconf) - checkErr(err) - defer conn.Close() - conns = append(conns, conn) - } + // for _, connstr := range cfg.ConnStrs { + // dbconf, err := pgx.ParseDSN(connstr) + // checkErr(err) + // conn, err := pgx.Connect(dbconf) + // checkErr(err) + // defer conn.Close() + // conns = append(conns, conn) + // } + + dbconf1, err := pgx.ParseDSN(cfg.ConnStrs[ id % len(cfg.ConnStrs) ]) + checkErr(err) + conn1, err := pgx.Connect(dbconf1) + checkErr(err) + defer conn1.Close() + + dbconf2, err := pgx.ParseDSN(cfg.ConnStrs[ (id + 1) % len(cfg.ConnStrs) ]) + checkErr(err) + conn2, err := pgx.Connect(dbconf2) + checkErr(err) + defer conn2.Close() for i := 0; i < cfg.IterNum; i++ { - gtid := strconv.Itoa(id) + "." + strconv.Itoa(i) amount := 2*rand.Intn(2) - 1 from_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 1 to_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 2 - conn1 := conns[rand.Intn(len(conns))] - conn2 := conns[rand.Intn(len(conns))] - for conn1 == conn2 { - conn1 = conns[rand.Intn(len(conns))] - conn2 = conns[rand.Intn(len(conns))] - } + // conn1 := conns[rand.Intn(len(conns))] + // conn2 := conns[rand.Intn(len(conns))] + // for conn1 == conn2 { + // conn1 = conns[rand.Intn(len(conns))] + // conn2 = conns[rand.Intn(len(conns))] + // } exec(conn1, "begin transaction") exec(conn2, "begin transaction") - snapshot = _execQuery(conn1, "select dtm_extend($1)", gtid) - snapshot = _execQuery(conn2, "select dtm_access($1, $2)", snapshot, gtid) + + if cfg.UseDtm { + snapshot = _execQuery(conn1, "select dtm_extend($1)", gtid) + snapshot = _execQuery(conn2, "select dtm_access($1, $2)", snapshot, gtid) + } + exec(conn1, "update t set v = v - $1 where u=$2", amount, from_acc) exec(conn2, "update t set v = v + $1 where u=$2", amount, to_acc) exec(conn1, "prepare transaction '" + gtid + "'") exec(conn2, "prepare transaction '" + gtid + "'") - exec(conn1, "select dtm_begin_prepare($1)", gtid) - exec(conn2, "select dtm_begin_prepare($1)", gtid) - csn = _execQuery(conn1, "select dtm_prepare($1, 0)", gtid) - csn = _execQuery(conn2, "select dtm_prepare($1, $2)", gtid, csn) - exec(conn1, "select dtm_end_prepare($1, $2)", gtid, csn) - exec(conn2, "select dtm_end_prepare($1, $2)", gtid, csn) + + if cfg.UseDtm { + exec(conn1, "select dtm_begin_prepare($1)", gtid) + exec(conn2, "select dtm_begin_prepare($1)", gtid) + csn = _execQuery(conn1, "select dtm_prepare($1, 0)", gtid) + csn = _execQuery(conn2, "select dtm_prepare($1, $2)", gtid, csn) + exec(conn1, "select dtm_end_prepare($1, $2)", gtid, csn) + exec(conn2, "select dtm_end_prepare($1, $2)", gtid, csn) + } + exec(conn1, "commit prepared '" + gtid + "'") exec(conn2, "commit prepared '" + gtid + "'") nGlobalTrans++ From 5c4cded2c2aca737fd6454545b59e95fbfe9c80b Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 9 Nov 2015 14:21:43 +0300 Subject: [PATCH 25/46] Auto adjust time --- pg_dtm.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pg_dtm.c b/pg_dtm.c index 51e84ad..fd8a779 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -54,6 +54,7 @@ typedef struct DtmTransStatus typedef struct { cid_t cid; + long time_shift; volatile slock_t lock; DtmTransStatus* trans_list_head; DtmTransStatus** trans_list_tail; @@ -105,7 +106,7 @@ static timestamp_t dtm_get_current_time() { struct timeval tv; gettimeofday(&tv, NULL); - return (timestamp_t)tv.tv_sec*USEC + tv.tv_usec; + return (timestamp_t)tv.tv_sec*USEC + tv.tv_usec + local->time_shift; } static void dtm_sleep(timestamp_t interval) @@ -136,6 +137,11 @@ static cid_t dtm_get_cid() static cid_t dtm_sync(cid_t global_cid) { cid_t local_cid; +#if 1 + while ((local_cid = dtm_get_cid()) < global_cid) { + local->time_shift += global_cid - local_cid; + } +#else while ((local_cid = dtm_get_cid()) < global_cid) { SpinLockRelease(&local->lock); #if TRACE_SLEEP_TIME @@ -160,6 +166,7 @@ static cid_t dtm_sync(cid_t global_cid) #endif SpinLockAcquire(&local->lock); } +#endif return global_cid; } @@ -525,6 +532,7 @@ void DtmInitialize() local = (DtmNodeState*)ShmemInitStruct("dtm", sizeof(DtmNodeState), &found); if (!found) { + local->time_shift = 0; local->cid = dtm_get_current_time(); local->trans_list_head = NULL; local->trans_list_tail = &local->trans_list_head; From baa904606b3fd85c196a2f8fdb75166e718f926b Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Tue, 10 Nov 2015 20:31:21 +0300 Subject: [PATCH 26/46] change deploy directory structure; change dtmbench output format to json; --- tests/deploy/cluster.yml | 13 ++++++------ tests/deploy/roles/postgres/tasks/main.yml | 4 ++++ tests/deploy/roles/postgres/vars/main.yml | 23 ++++------------------ tests/dtmbench.cpp | 15 +++++++++++++- tests/perf.yml | 22 ++++++++++++--------- 5 files changed, 42 insertions(+), 35 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 6398609..d060bd2 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -9,7 +9,6 @@ pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true - pg_datadir: ./postgrespro-data pg_config_role: - line: "dtm.vacuum_delay=60" @@ -17,24 +16,26 @@ - name: clone dtm sources git: repo=https://github.com/postgrespro/pg_tsdtm.git - dest=./pg_tsdtm + dest={{pg_prefix}}/pg_tsdtm accept_hostkey=yes update=yes force=yes register: dtm_sources - name: build dtm - shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make clean && PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" + shell: "make clean && make -j {{makejobs}} install" args: - chdir: ./pg_tsdtm + chdir: "{{pg_prefix}}/pg_tsdtm" + environment: + PG_CONFIG: "{{pg_dst}}/bin/pg_config" when: dtm_sources.changed - name: enable dtm extension on datanodes lineinfile: dest: "{{pg_datadir}}/postgresql.conf" - regexp: "^shared_preload_libraries " + regexp: "^shared_preload_libraries" line: "shared_preload_libraries = 'pg_dtm'" state: present - name: restart postgrespro - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 6df0e0d..e692175 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -30,6 +30,10 @@ when: ansible_os_family == "RedHat" sudo: yes +- name: increase semaphores + shell: sysctl kernel.sem='1000 128000 128 512' + sudo: yes + - name: clone postgres sources git: repo={{pg_repo}} dest={{pg_src}} diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 2a73cea..982cc42 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -2,17 +2,11 @@ --- makejobs: 4 -deploy_postgres: false -deploy_dtm: false -deploy_pg_shard: false - pg_repo: git://git.postgresql.org/git/postgresql.git pg_version_tag: master - pg_destroy_and_init: false - pg_port: 5432 pg_dtm_enable: false pg_dtm_host: "127.0.0.1" @@ -27,18 +21,9 @@ pg_config: - line: "port = {{pg_port}}" pg_config_role: - line: "#pg_config_role" -pg_src: ~/postgrespro -pg_dst: /tmp/postgrespro-build -pg_datadir: ~/postgrespro-data - -libuv: - version: v1.7.5 - src: ./libuv - dst: /tmp/libuv-build -dtmd: - port: 5431 - dst: ./dtmd - datadir: ./dtmd-data - log: ./dtmd.log +pg_prefix: "{{ansible_env.HOME}}/pg_cluster" +pg_src: "{{pg_prefix}}/src" +pg_dst: "{{pg_prefix}}/install" +pg_datadir: "{{pg_prefix}}/data_{{pg_port}}" diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index 71548be..4baefc3 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -271,6 +271,19 @@ int main (int argc, char* argv[]) } time_t elapsed = getCurrentTime() - start; - printf("TPS(updates)=%f, TPS(selects)=%f\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed); + + + + printf( + "{\"update_tps\":%f, \"read_tps\":%f, \"readers\":%d, \"writers\":%d, \"accounts\":%d, \"iterations\":%d, \"hosts\":%d}\n", + (double)(nWrites*USEC)/elapsed, + (double)(nReads*USEC)/elapsed, + cfg.nReaders, + cfg.nWriters, + cfg.nAccounts, + cfg.nIterations, + cfg.connections.size() + ); + return 0; } diff --git a/tests/perf.yml b/tests/perf.yml index ab31ba0..387f82d 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -1,6 +1,6 @@ --- -- hosts: clients[0] +- hosts: clients gather_facts: no tasks: @@ -15,21 +15,25 @@ set_fact: connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" - - name: copy transfers binary + # - name: copy transfers binary + # copy: src=./{{item}} dest=~/{{item}} mode=0755 + # with_items: + # - "dtmbench" + # - "libpqxx-4.0.so" + + - name: copy transfers source copy: src=./{{item}} dest=~/{{item}} mode=0755 with_items: - "dtmbench.cpp" - name: compile dtmbench - shell: "g++ -g -Wall -O2 -o dtmbench dtmbench.cpp -lpqxx -pthread " + shell: "g++ -g -Wall -O2 -o dtmbench dtmbench.cpp -lpqxx -pthread" -- hosts: clients[0] - gather_facts: no - tasks: - name: run transfers - shell: "./dtmbench {{connections}} -w {{item}} -r 1 -n 1000 -a 100000 -i " + shell: "./dtmbench {{connections}} -w {{item}} -r 1 -n 100 -a 100000 -i " register: transfers_result - with_sequence: start=20 end=400 stride=20 + with_sequence: start=100 end=200 stride=100 - - debug: msg={{transfers_result.results | map(attribute='stdout_lines') | join }} + - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> x.out + - debug: msg="{{ transfers_result.results | map(attribute='stdout') | join('\n') }}" From 7b4257c530b3af523296d75ff90b9947606eb4a4 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Tue, 10 Nov 2015 22:35:39 +0300 Subject: [PATCH 27/46] ability to copy compiled postgres instead of building it --- tests/deploy/cluster.yml | 38 ++++++++++--------- tests/deploy/roles/postgres/tasks/main.yml | 43 ++++++++++++++-------- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index d060bd2..e0bf808 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -1,34 +1,38 @@ --- - hosts: nodes + # gather_facts: no + # pre_tasks: + # - name: make a list + # set_fact: + # ansible_os_family: "Debian" roles: - - role: postgres pg_port: 15432 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true + pg_copydist: true pg_config_role: - line: "dtm.vacuum_delay=60" tasks: - - - name: clone dtm sources - git: repo=https://github.com/postgrespro/pg_tsdtm.git - dest={{pg_prefix}}/pg_tsdtm - accept_hostkey=yes - update=yes - force=yes - register: dtm_sources - - - name: build dtm - shell: "make clean && make -j {{makejobs}} install" - args: - chdir: "{{pg_prefix}}/pg_tsdtm" - environment: - PG_CONFIG: "{{pg_dst}}/bin/pg_config" - when: dtm_sources.changed + # - name: clone dtm sources + # git: repo=https://github.com/postgrespro/pg_tsdtm.git + # dest={{pg_prefix}}/pg_tsdtm + # accept_hostkey=yes + # update=yes + # force=yes + # register: dtm_sources + + # - name: build dtm + # shell: "make clean && make -j {{makejobs}} install" + # args: + # chdir: "{{pg_prefix}}/pg_tsdtm" + # environment: + # PG_CONFIG: "{{pg_dst}}/bin/pg_config" + # when: dtm_sources.changed - name: enable dtm extension on datanodes lineinfile: diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index e692175..d813e09 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -15,7 +15,7 @@ - name: ensure dependencies (RedHat) yum: name="@Development tools" state=present - when: ansible_os_family == "RedHat" + when: (pg_copydist is undefined) and ansible_os_family == "RedHat" sudo: yes - name: ensure dependencies (RedHat) @@ -27,13 +27,15 @@ - bison - flex - readline-devel - when: ansible_os_family == "RedHat" + when: (pg_copydist is undefined) and ansible_os_family == "RedHat" sudo: yes - name: increase semaphores shell: sysctl kernel.sem='1000 128000 128 512' sudo: yes +############################################################################# + - name: clone postgres sources git: repo={{pg_repo}} dest={{pg_src}} @@ -41,25 +43,39 @@ depth=1 accept_hostkey=True register: pg_sources - -############################################################################# - -- stat: path={{pg_datadir}}/postmaster.pid - register: pg_pidfile - -- name: stop postgres if it was running - command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" - when: pg_pidfile.stat.exists + when: pg_copydist is undefined - name: force rebuild on changed sources command: "rm -f {{pg_dst}}/bin/postgres" - when: pg_sources.changed + when: (pg_copydist is undefined) and pg_sources.changed - name: build and install shell: ./configure --prefix={{pg_dst}} --without-zlib && make clean && make -j {{makejobs}} && make install args: chdir: "{{pg_src}}" creates: "{{pg_dst}}/bin/postgres" + when: pg_copydist is undefined + +############################################################################# + +- name: copy pg source + copy: src=./{{item}} dest=~/{{item}} mode=0755 + with_items: + - "pg_cluster_install.tgz" + when: pg_copydist is defined + +- name: extract postgres + command: "tar xzf pg_cluster_install.tgz" + when: pg_copydist is defined + +############################################################################# + +- stat: path={{pg_datadir}}/postmaster.pid + register: pg_pidfile + +- name: stop postgres if it was running + command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" + when: pg_pidfile.stat.exists - name: remove datadirs on datanodes command: "rm -rf {{pg_datadir}}" @@ -89,9 +105,6 @@ dest: "{{pg_datadir}}/pg_hba.conf" line: "host all all 0.0.0.0/0 trust" -# - include: pg_shard.yml -# when: deploy_pg_shard - - name: start postgrespro command: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" From a6e5d317668364a00ff97ca0b60eb181b300052f Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 16:44:24 +0300 Subject: [PATCH 28/46] dtmbench deploy on several servers --- tests/deploy/cluster.yml | 13 ++++ tests/deploy/hosts | 12 ++-- tests/deploy/roles/postgres/tasks/main.yml | 10 ++- tests/deploy/roles/postgres/vars/main.yml | 3 - tests/dtmbench.cpp | 80 +++++++++++++++------- tests/perf.yml | 34 +++++---- 6 files changed, 103 insertions(+), 49 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index e0bf808..3397d66 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -43,3 +43,16 @@ - name: restart postgrespro command: "{{pg_dst}}/bin/pg_ctl restart -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" + environment: + LD_LIBRARY_PATH: "{{pg_dst}}/lib/" + + +- hosts: clients + tasks: + - name: copy pg source + copy: src=./{{item}} dest=~/{{item}} mode=0755 + with_items: + - "pg_cluster_install.tgz" + + - name: extract postgres + command: "tar xzf pg_cluster_install.tgz" diff --git a/tests/deploy/hosts b/tests/deploy/hosts index c9d4501..a31b9db 100644 --- a/tests/deploy/hosts +++ b/tests/deploy/hosts @@ -1,12 +1,12 @@ [clients] -158.250.29.4 ansible_ssh_user=cluster offset=6001 -158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=3001 +158.250.29.4 ansible_ssh_user=cluster offset=600001 +158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=300001 [nodes] -158.250.29.5 ansible_ssh_user=cluster offset=5001 -158.250.29.6 ansible_ssh_user=cluster offset=4001 -158.250.29.8 ansible_ssh_user=cluster offset=2001 -158.250.29.9 ansible_ssh_user=cluster offset=1001 +158.250.29.5 ansible_ssh_user=cluster offset=500001 +158.250.29.6 ansible_ssh_user=cluster offset=400001 +158.250.29.8 ansible_ssh_user=cluster offset=200001 +158.250.29.9 ansible_ssh_user=cluster offset=100001 158.250.29.10 ansible_ssh_user=cluster offset=1 [master] diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index d813e09..f3b5d3c 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -75,6 +75,8 @@ - name: stop postgres if it was running command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" + environment: + LD_LIBRARY_PATH: "{{pg_dst}}/lib" when: pg_pidfile.stat.exists - name: remove datadirs on datanodes @@ -83,6 +85,8 @@ - name: create datadirs on datanodes command: "{{pg_dst}}/bin/initdb {{pg_datadir}}" + environment: + LD_LIBRARY_PATH: "{{pg_dst}}/lib/" args: creates: "{{pg_datadir}}" @@ -106,7 +110,7 @@ line: "host all all 0.0.0.0/0 trust" - name: start postgrespro - command: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" - - + shell: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" + environment: + LD_LIBRARY_PATH: "{{pg_dst}}/lib/" diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 982cc42..45e948f 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -8,8 +8,6 @@ pg_version_tag: master pg_destroy_and_init: false pg_port: 5432 -pg_dtm_enable: false -pg_dtm_host: "127.0.0.1" pg_config: - line: "shared_buffers = 3GB" - line: "wal_keep_segments = 128" @@ -26,4 +24,3 @@ pg_prefix: "{{ansible_env.HOME}}/pg_cluster" pg_src: "{{pg_prefix}}/src" pg_dst: "{{pg_prefix}}/install" pg_datadir: "{{pg_prefix}}/data_{{pg_port}}" - diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index 4baefc3..ce3bcc5 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -59,13 +59,17 @@ struct config int nWriters; int nIterations; int nAccounts; + int startId; + int diapason; vector connections; config() { nReaders = 1; nWriters = 10; nIterations = 1000; - nAccounts = 1000; + nAccounts = 100000; + startId = 1; + diapason = 100000; } }; @@ -141,36 +145,41 @@ void* reader(void* arg) void* writer(void* arg) { thread& t = *(thread*)arg; - vector< unique_ptr > conns(cfg.connections.size()); - for (size_t i = 0; i < conns.size(); i++) { - conns[i] = new connection(cfg.connections[i]); - } + connection *srcCon, *dstCon; + + srcCon = new connection(cfg.connections[t.id % cfg.connections.size()]); + dstCon = new connection(cfg.connections[(t.id + 1) % cfg.connections.size()]); + for (int i = 0; i < cfg.nIterations; i++) { char gtid[32]; - int srcCon, dstCon; - int srcAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - int dstAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - sprintf(gtid, "%d.%d", t.id, i); + // int srcAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; + // int dstAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - do { - srcCon = random() % cfg.connections.size(); - dstCon = random() % cfg.connections.size(); - } while (srcCon == dstCon); - - nontransaction srcTx(*conns[srcCon]); - nontransaction dstTx(*conns[dstCon]); + int srcAcc = cfg.startId + random() % cfg.diapason; + int dstAcc = cfg.startId + random() % cfg.diapason; + + if (srcAcc > dstAcc) { + int tmpAcc = dstAcc; + dstAcc = srcAcc; + srcAcc = tmpAcc; + } + + sprintf(gtid, "%d.%d.%d", cfg.startId, t.id, i); + + nontransaction srcTx(*srcCon); + nontransaction dstTx(*dstCon); exec(srcTx, "begin transaction"); exec(dstTx, "begin transaction"); csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); - + exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); - + exec(srcTx, "prepare transaction '%s'", gtid); exec(dstTx, "prepare transaction '%s'", gtid); exec(srcTx, "select dtm_begin_prepare('%s')", gtid); @@ -196,17 +205,20 @@ void initializeDatabase() exec(txn, "create extension pg_dtm"); exec(txn, "drop table if exists t"); exec(txn, "create table t(u int primary key, v int)"); - exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts-1, 0); + exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts, 0); txn.commit(); - - // nontransaction vacTx(conn); - // exec(vacTx, "vacuum full"); } } int main (int argc, char* argv[]) { bool initialize = false; + + if (argc == 1){ + printf("Use -h to show usage options\n"); + return 1; + } + for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { @@ -222,6 +234,12 @@ int main (int argc, char* argv[]) case 'n': cfg.nIterations = atoi(argv[++i]); continue; + case 's': + cfg.startId = atoi(argv[++i]); + continue; + case 'd': + cfg.diapason = atoi(argv[++i]); + continue; case 'C': cfg.connections.push_back(string(argv[++i])); continue; @@ -233,14 +251,24 @@ int main (int argc, char* argv[]) printf("Options:\n" "\t-r N\tnumber of readers (1)\n" "\t-w N\tnumber of writers (10)\n" - "\t-a N\tnumber of accounts (1000)\n" + "\t-a N\tnumber of accounts (100000)\n" + "\t-s N\tperform updates starting from this id (1)\n" + "\t-d N\tperform updates in this diapason (100000)\n" "\t-n N\tnumber of iterations (1000)\n" - "\t-c STR\tdatabase connection string\n" + "\t-C STR\tdatabase connection string\n" "\t-i\tinitialize datanase\n"); return 1; } + + if (cfg.startId + cfg.diapason - 1 > cfg.nAccounts) { + printf("startId + diapason should be less that nAccounts. Exiting.\n"); + return 1; + } + if (initialize) { initializeDatabase(); + printf("%d account inserted\n", cfg.nAccounts); + return 0; } time_t start = getCurrentTime(); @@ -275,7 +303,9 @@ int main (int argc, char* argv[]) printf( - "{\"update_tps\":%f, \"read_tps\":%f, \"readers\":%d, \"writers\":%d, \"accounts\":%d, \"iterations\":%d, \"hosts\":%d}\n", + "{\"update_tps\":%f, \"read_tps\":%f," + " \"readers\":%d, \"writers\":%d," + " \"accounts\":%d, \"iterations\":%d, \"hosts\":%d}\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed, cfg.nReaders, diff --git a/tests/perf.yml b/tests/perf.yml index 387f82d..10c9656 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -6,7 +6,7 @@ - name: generate connstrings set_fact: - connstr: "-C 'host={{item}} user=cluster port=15432 dbname=postgres' " + connstr: "-C 'host={{item}} user={{ansible_ssh_user}} port=15432 dbname=postgres' " with_items: groups['nodes'] | reverse | batch(nnodes | d(2) | int) | first register: connstrs @@ -15,25 +15,35 @@ set_fact: connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" - # - name: copy transfers binary + # - name: copy transfers source # copy: src=./{{item}} dest=~/{{item}} mode=0755 # with_items: - # - "dtmbench" - # - "libpqxx-4.0.so" + # - "dtmbench.cpp" - - name: copy transfers source - copy: src=./{{item}} dest=~/{{item}} mode=0755 - with_items: - - "dtmbench.cpp" + # - name: compile dtmbench + # shell: "g++ -g -Wall -O2 -o dtmbench dtmbench.cpp -lpqxx -lpq -pthread" + + # - name: compile dtmbench + # shell: "mv dtmbench ~/pg_cluster/install/bin/dtmbench" - - name: compile dtmbench - shell: "g++ -g -Wall -O2 -o dtmbench dtmbench.cpp -lpqxx -pthread" +- hosts: clients[0] + gather_facts: no + tasks: + - name: init database + shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -a 1000000 -i" + register: init_result + - debug: var=init_result +- hosts: clients + gather_facts: no + tasks: - name: run transfers - shell: "./dtmbench {{connections}} -w {{item}} -r 1 -n 100 -a 100000 -i " + shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 1000000" register: transfers_result + environment: + LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" with_sequence: start=100 end=200 stride=100 - - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> x.out + - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> perf.results - debug: msg="{{ transfers_result.results | map(attribute='stdout') | join('\n') }}" From 8944b3ec99e111f3ff2bd4bd4ad1b398008ada0b Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 16:55:41 +0300 Subject: [PATCH 29/46] prepend hostname to results --- tests/perf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/perf.yml b/tests/perf.yml index 10c9656..eee5e2f 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -38,7 +38,7 @@ gather_facts: no tasks: - name: run transfers - shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 1000000" + shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 1000000 | sed "s/^/`hostname`:/"' register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" From 7f4dd6b76a61d1b47d2c8f8027646d236ed2ad02 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 17:06:59 +0300 Subject: [PATCH 30/46] some tests params change --- tests/perf.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index eee5e2f..1200a0b 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -38,11 +38,11 @@ gather_facts: no tasks: - name: run transfers - shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 1000000 | sed "s/^/`hostname`:/"' + shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | sed "s/^/`hostname`:/"' register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" - with_sequence: start=100 end=200 stride=100 + with_sequence: start=100 end=200 stride=50 - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> perf.results From 88ea1e19cebdeef835bf2fb9aea81dddec915bb1 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 20:16:25 +0300 Subject: [PATCH 31/46] increase open files; save intermediate bench results; force postgres stop --- tests/deploy/cluster.yml | 6 ++++++ tests/deploy/hosts.sample | 14 +++++++++++--- tests/deploy/roles/postgres/tasks/main.yml | 14 +++++++++++++- tests/perf.yml | 3 ++- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 3397d66..c1e8745 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -49,6 +49,12 @@ - hosts: clients tasks: + - name: increase open files + shell: "echo '{{ansible_ssh_user}} soft nofile 65535' > /etc/security/limits.d/cluster.conf" + args: + creates: "/etc/security/limits.d/cluster.conf" + sudo: yes + - name: copy pg source copy: src=./{{item}} dest=~/{{item}} mode=0755 with_items: diff --git a/tests/deploy/hosts.sample b/tests/deploy/hosts.sample index 61a49c3..46a55c5 100644 --- a/tests/deploy/hosts.sample +++ b/tests/deploy/hosts.sample @@ -1,8 +1,16 @@ [clients] -client1 ansible_ssh_user=cluster offset=6001 +158.250.29.4 ansible_ssh_user=cluster offset=1 +158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=100001 [nodes] -nodes1 ansible_ssh_user=cluster offset=2001 +158.250.29.5 ansible_ssh_user=cluster +158.250.29.6 ansible_ssh_user=cluster +158.250.29.8 ansible_ssh_user=cluster +158.250.29.9 ansible_ssh_user=cluster +158.250.29.10 ansible_ssh_user=cluster [master] -master1 ansible_ssh_user=cluster offset=1 +158.250.29.10 ansible_ssh_user=cluster + +[local] +localhost diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index f3b5d3c..6a86773 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -34,6 +34,12 @@ shell: sysctl kernel.sem='1000 128000 128 512' sudo: yes +- name: increase open files + shell: "echo '{{ansible_ssh_user}} soft nofile 65535' > /etc/security/limits.d/cluster.conf" + args: + creates: "/etc/security/limits.d/cluster.conf" + sudo: yes + ############################################################################# - name: clone postgres sources @@ -73,8 +79,14 @@ - stat: path={{pg_datadir}}/postmaster.pid register: pg_pidfile +# - name: stop postgres if it was running +# command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" +# environment: +# LD_LIBRARY_PATH: "{{pg_dst}}/lib" +# when: pg_pidfile.stat.exists + - name: stop postgres if it was running - command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" + shell: "kill -9 `head -n 1 {{pg_datadir}}/postmaster.pid`" environment: LD_LIBRARY_PATH: "{{pg_dst}}/lib" when: pg_pidfile.stat.exists diff --git a/tests/perf.yml b/tests/perf.yml index 1200a0b..fabf97d 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -37,8 +37,9 @@ - hosts: clients gather_facts: no tasks: + - name: run transfers - shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | sed "s/^/`hostname`:/"' + shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | tee -a perf.results | sed "s/^/`hostname`:/"' register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" From d364f40a734fe705b443f69f9ca821d62cf4557e Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 20:16:52 +0300 Subject: [PATCH 32/46] rm hosts --- tests/deploy/hosts | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 tests/deploy/hosts diff --git a/tests/deploy/hosts b/tests/deploy/hosts deleted file mode 100644 index a31b9db..0000000 --- a/tests/deploy/hosts +++ /dev/null @@ -1,16 +0,0 @@ -[clients] -158.250.29.4 ansible_ssh_user=cluster offset=600001 -158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=300001 - -[nodes] -158.250.29.5 ansible_ssh_user=cluster offset=500001 -158.250.29.6 ansible_ssh_user=cluster offset=400001 -158.250.29.8 ansible_ssh_user=cluster offset=200001 -158.250.29.9 ansible_ssh_user=cluster offset=100001 -158.250.29.10 ansible_ssh_user=cluster offset=1 - -[master] -158.250.29.10 ansible_ssh_user=cluster offset=1 - -[local] -localhost From 812cfb919abfa5e0a946ae14c1b8443ec8f0746a Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 20:20:39 +0300 Subject: [PATCH 33/46] bigger range of connections --- tests/perf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/perf.yml b/tests/perf.yml index fabf97d..baab945 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -43,7 +43,7 @@ register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" - with_sequence: start=100 end=200 stride=50 + with_sequence: start=100 end=400 stride=50 - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> perf.results From b652c1d1e3ac71d9c75c5d29c62a243c2c63f785 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 21:00:50 +0300 Subject: [PATCH 34/46] do not loop transfers inside ansible role; better logging --- tests/perf.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index baab945..dd0d2f8 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -30,7 +30,7 @@ gather_facts: no tasks: - name: init database - shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -a 1000000 -i" + shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -a 2000000 -i" register: init_result - debug: var=init_result @@ -38,13 +38,21 @@ gather_facts: no tasks: + - local_action: shell echo "Bench started at `date`" >> perf.results + - name: run transfers - shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | tee -a perf.results | sed "s/^/`hostname`:/"' + shell: > + ~/pg_cluster/install/bin/dtmbench {{connections}} + -w {{conns | d(200)}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | + tee -a perf.results | + sed "s/^/`hostname`:/" register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" - with_sequence: start=100 end=400 stride=50 - - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> perf.results + - debug: var=transfers_result + + - local_action: 'shell echo "{{transfers_result.stdout }}" >> perf.results' + + - local_action: shell echo "Bench finished at `date`" >> perf.results - - debug: msg="{{ transfers_result.results | map(attribute='stdout') | join('\n') }}" From 72e2fc38ef9087c0b3738cab298b6b87f0db7edc Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 21:14:19 +0300 Subject: [PATCH 35/46] max open files #2 --- tests/deploy/cluster.yml | 13 ++++++++----- tests/deploy/roles/postgres/tasks/main.yml | 14 +++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index c1e8745..770e2cd 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -46,13 +46,16 @@ environment: LD_LIBRARY_PATH: "{{pg_dst}}/lib/" - - hosts: clients tasks: - - name: increase open files - shell: "echo '{{ansible_ssh_user}} soft nofile 65535' > /etc/security/limits.d/cluster.conf" - args: - creates: "/etc/security/limits.d/cluster.conf" + - name: increase max open files + lineinfile: + dest: /etc/security/limits.d/cluster.conf + line: "{{item}}" + state: present + with_items: + - '{{ansible_ssh_user}} soft nofile 65535' + - '{{ansible_ssh_user}} hard nofile 65535' sudo: yes - name: copy pg source diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 6a86773..ef3028d 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -10,7 +10,7 @@ - bison - flex - libreadline-dev - when: ansible_os_family == "Debian" + when: (pg_copydist is undefined) and ansible_os_family == "Debian" sudo: yes - name: ensure dependencies (RedHat) @@ -34,10 +34,14 @@ shell: sysctl kernel.sem='1000 128000 128 512' sudo: yes -- name: increase open files - shell: "echo '{{ansible_ssh_user}} soft nofile 65535' > /etc/security/limits.d/cluster.conf" - args: - creates: "/etc/security/limits.d/cluster.conf" +- name: increase max open files + lineinfile: + dest: /etc/security/limits.d/cluster.conf + line: "{{item}}" + state: present + with_items: + - '{{ansible_ssh_user}} soft nofile 65535' + - '{{ansible_ssh_user}} hard nofile 65535' sudo: yes ############################################################################# From bf4de8dc8eaaf4ce76a57bd5c57fbf3f8ff4aa63 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 21:41:50 +0300 Subject: [PATCH 36/46] nconns now means number of node connections --- tests/perf.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/perf.yml b/tests/perf.yml index dd0d2f8..847b80d 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -43,7 +43,8 @@ - name: run transfers shell: > ~/pg_cluster/install/bin/dtmbench {{connections}} - -w {{conns | d(200)}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | + -w {{ (nconns | d(100)| int)*(nnodes | d(2) | int)/(2*( groups['clients'] | count))}} + -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | tee -a perf.results | sed "s/^/`hostname`:/" register: transfers_result From cbe347577ffb2dd099c33417bfac4ff49ab8f520 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 21:55:45 +0300 Subject: [PATCH 37/46] create limits file --- tests/deploy/cluster.yml | 1 + tests/deploy/roles/postgres/tasks/main.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 770e2cd..e8d94cd 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -53,6 +53,7 @@ dest: /etc/security/limits.d/cluster.conf line: "{{item}}" state: present + create: true with_items: - '{{ansible_ssh_user}} soft nofile 65535' - '{{ansible_ssh_user}} hard nofile 65535' diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index ef3028d..44dbdf5 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -39,6 +39,7 @@ dest: /etc/security/limits.d/cluster.conf line: "{{item}}" state: present + create: true with_items: - '{{ansible_ssh_user}} soft nofile 65535' - '{{ansible_ssh_user}} hard nofile 65535' From 0510958cf24837fc2887068644d6646b39979f58 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Wed, 11 Nov 2015 22:43:15 +0300 Subject: [PATCH 38/46] fix LD_LIBRARY_PATH --- tests/.gitignore | 3 +++ tests/deploy/cluster.yml | 2 +- tests/deploy/roles/postgres/tasks/main.yml | 6 +++--- tests/perf.yml | 4 +++- 4 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 tests/.gitignore diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..10ba26b --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,3 @@ +/deploy/hosts +/deploy/pg_cluster_install.tgz +/perf.results diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index e8d94cd..aa295c0 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -44,7 +44,7 @@ - name: restart postgrespro command: "{{pg_dst}}/bin/pg_ctl restart -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" environment: - LD_LIBRARY_PATH: "{{pg_dst}}/lib/" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:{{pg_dst}}/lib/" - hosts: clients tasks: diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 44dbdf5..12aa2df 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -93,7 +93,7 @@ - name: stop postgres if it was running shell: "kill -9 `head -n 1 {{pg_datadir}}/postmaster.pid`" environment: - LD_LIBRARY_PATH: "{{pg_dst}}/lib" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:{{pg_dst}}/lib" when: pg_pidfile.stat.exists - name: remove datadirs on datanodes @@ -103,7 +103,7 @@ - name: create datadirs on datanodes command: "{{pg_dst}}/bin/initdb {{pg_datadir}}" environment: - LD_LIBRARY_PATH: "{{pg_dst}}/lib/" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:{{pg_dst}}/lib/" args: creates: "{{pg_datadir}}" @@ -129,5 +129,5 @@ - name: start postgrespro shell: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" environment: - LD_LIBRARY_PATH: "{{pg_dst}}/lib/" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:{{pg_dst}}/lib" diff --git a/tests/perf.yml b/tests/perf.yml index 847b80d..57109c0 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -30,6 +30,8 @@ gather_facts: no tasks: - name: init database + environment: + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:/home/{{ansible_ssh_user}}/pg_cluster/install/lib" shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -a 2000000 -i" register: init_result - debug: var=init_result @@ -49,7 +51,7 @@ sed "s/^/`hostname`:/" register: transfers_result environment: - LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:/home/{{ansible_ssh_user}}/pg_cluster/install/lib" - debug: var=transfers_result From e2050fa468a3afd42a3e9ad4f927e63f5ca8c182 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 13 Nov 2015 14:32:50 +0300 Subject: [PATCH 39/46] Imporove sleep statistic reporting --- pg_dtm.c | 15 +++++++++++---- tests/deploy/cluster.yml | 2 +- tests/run.sh | 3 +-- tests/transfers.go | 12 ++++++------ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index fd8a779..6fd9833 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -438,11 +438,21 @@ TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum) bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) { +#if TRACE_SLEEP_TIME + static timestamp_t firstReportTime; + static timestamp_t prevReportTime; + static timestamp_t totalSleepTime; +#endif timestamp_t delay = MIN_WAIT_TIMEOUT; Assert(xid != InvalidTransactionId); SpinLockAcquire(&local->lock); +#if TRACE_SLEEP_TIME + if (firstReportTime == 0) { + firstReportTime = dtm_get_current_time(); + } +#endif while (true) { DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); @@ -461,14 +471,11 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) #if TRACE_SLEEP_TIME { timestamp_t now = dtm_get_current_time(); - static timestamp_t firstReportTime; - static timestamp_t prevReportTime; - static timestamp_t totalSleepTime; #endif dtm_sleep(delay); #if TRACE_SLEEP_TIME totalSleepTime += dtm_get_current_time() - now; - if (now > prevReportTime + USEC*10) { + if (now > prevReportTime + USEC*1) { prevReportTime = now; if (firstReportTime == 0) { firstReportTime = now; diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 6398609..088a766 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -11,7 +11,7 @@ pg_destroy_and_init: true pg_datadir: ./postgrespro-data pg_config_role: - - line: "dtm.vacuum_delay=60" + - line: "dtm.vacuum_delay=1000" tasks: diff --git a/tests/run.sh b/tests/run.sh index 6b9f342..7bd17c6 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -1,5 +1,4 @@ ./dtmbench \ -c "dbname=postgres host=localhost user=knizhnik port=5432 sslmode=disable" \ -c "dbname=postgres host=localhost user=knizhnik port=5433 sslmode=disable" \ --c "dbname=postgres host=localhost user=knizhnik port=5434 sslmode=disable" \ --n 1000 -a 1000 -w 10 -r 1 $* +-n 10000 -a 1000 -w 10 -r 1 $* diff --git a/tests/transfers.go b/tests/transfers.go index 514910d..efe7655 100644 --- a/tests/transfers.go +++ b/tests/transfers.go @@ -18,14 +18,14 @@ const ( var cfg1 = pgx.ConnConfig{ - Host: "astro9", - Port: 15432, + Host: "127.0.0.1", + Port: 5432, Database: "postgres", } var cfg2 = pgx.ConnConfig{ - Host: "astro9", - Port: 15433, + Host: "127.0.0.1", + Port: 5433, Database: "postgres", } @@ -109,8 +109,8 @@ func transfer(id int, wg *sync.WaitGroup) { gtid := strconv.Itoa(id) + "." + strconv.Itoa(i) amount := 2*rand.Intn(2) - 1 - account1 := 2*id+1 - account2 := 2*id+2 + account1 := rand.Intn(N_ACCOUNTS) + account2 := rand.Intn(N_ACCOUNTS) exec(conn1, "begin transaction") exec(conn2, "begin transaction") From fc142bad326aa35fcd8c8dc9f7794d10fa619021 Mon Sep 17 00:00:00 2001 From: knizhnik Date: Thu, 26 Nov 2015 23:36:30 +0300 Subject: [PATCH 40/46] Support subtransactions --- pg_dtm.c | 6 +++++- tests/dtmbench.cpp | 11 +++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index 6fd9833..a2f241b 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -21,6 +21,7 @@ #include "access/xact.h" #include "access/xtm.h" #include "access/transam.h" +#include "access/subtrans.h" #include "access/xlog.h" #include "access/clog.h" #include "access/twophase.h" @@ -455,7 +456,10 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) #endif while (true) { - DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + DtmTransStatus* ts; + TransactionId subxid = xid; + while ((ts = (DtmTransStatus*)hash_search(xid2status, &subxid, HASH_FIND, NULL)) == NULL + && TransactionIdIsValid(subxid = SubTransGetParent(subxid))); if (ts != NULL) { if (ts->cid > dtm_tx.snapshot) { diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index ce3bcc5..2c89b72 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -68,7 +68,7 @@ struct config nWriters = 10; nIterations = 1000; nAccounts = 100000; - startId = 1; + startId = 0; diapason = 100000; } }; @@ -177,7 +177,10 @@ void* writer(void* arg) csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); - exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); + exec(srcTx, "savepoint c1"); + exec(dstTx, "savepoint c2"); + + exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); exec(srcTx, "prepare transaction '%s'", gtid); @@ -260,7 +263,7 @@ int main (int argc, char* argv[]) return 1; } - if (cfg.startId + cfg.diapason - 1 > cfg.nAccounts) { + if (cfg.startId + cfg.diapason > cfg.nAccounts) { printf("startId + diapason should be less that nAccounts. Exiting.\n"); return 1; } @@ -305,7 +308,7 @@ int main (int argc, char* argv[]) printf( "{\"update_tps\":%f, \"read_tps\":%f," " \"readers\":%d, \"writers\":%d," - " \"accounts\":%d, \"iterations\":%d, \"hosts\":%d}\n", + " \"accounts\":%d, \"iterations\":%d, \"hosts\":%ld}\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed, cfg.nReaders, From d9e190eefc6fe5bc936acca76ca6f59b96cbdb51 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 27 Nov 2015 13:19:19 +0300 Subject: [PATCH 41/46] Support subtransactions --- pg_dtm.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index a2f241b..91dd1fe 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -83,8 +83,9 @@ static Snapshot DtmGetSnapshot(Snapshot snapshot); static TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum); static bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); static TransactionId DtmAdjustOldestXid(TransactionId xid); +static void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); -static TransactionManager DtmTM = { PgTransactionIdGetStatus, PgTransactionIdSetTreeStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot }; +static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot }; void _PG_init(void); void _PG_fini(void); @@ -456,10 +457,11 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) #endif while (true) { - DtmTransStatus* ts; - TransactionId subxid = xid; - while ((ts = (DtmTransStatus*)hash_search(xid2status, &subxid, HASH_FIND, NULL)) == NULL - && TransactionIdIsValid(subxid = SubTransGetParent(subxid))); + DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + if (ts == NULL && TransactionIdFollowsOrEquals(xid, TransactionXmin)) { + xid = SubTransGetTopmostTransaction(xid); + ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + } if (ts != NULL) { if (ts->cid > dtm_tx.snapshot) { @@ -679,8 +681,8 @@ void DtmLocalCommit(DtmTransState* x) if (x->is_prepared) { Assert(found); Assert(x->is_global); - } else { - Assert(!found); + } else if (!found) { + //Assert(!found); ts->cid = dtm_get_cid(); IncludeInTransactionList(ts); } @@ -718,8 +720,8 @@ void DtmLocalAbort(DtmTransState* x) if (x->is_prepared) { Assert(found); Assert(x->is_global); - } else { - Assert(!found); + } else if (!found) { + //Assert(!found); ts->cid = dtm_get_cid(); IncludeInTransactionList(ts); } @@ -738,3 +740,28 @@ void DtmLocalEnd(DtmTransState* x) x->cid = INVALID_CID; } +void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn) +{ + if (nsubxids != 0) { + SpinLockAcquire(&local->lock); + { + int i; + bool found; + DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_ENTER, &found); + if (!found) { + ts->cid = dtm_get_cid(); + } + ts->status = status; + for (i = 0; i < nsubxids; i++) { + DtmTransStatus* sts = (DtmTransStatus*)hash_search(xid2status, &subxids[i], HASH_ENTER, &found); + Assert(!found); + sts->status = status; + sts->cid = ts->cid; + sts->next = ts->next; + ts->next = sts; + } + } + SpinLockRelease(&local->lock); + } + PgTransactionIdSetTreeStatus(xid, nsubxids, subxids, status, lsn); +} From 7841007581fb7647ed666694094436777652327b Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 27 Nov 2015 19:42:56 +0300 Subject: [PATCH 42/46] Support subtransactions --- pg_dtm.c | 9 ++++++++- tests/dtmbench.cpp | 25 ++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index 91dd1fe..831e8a2 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -84,8 +84,9 @@ static TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum); static bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); static TransactionId DtmAdjustOldestXid(TransactionId xid); static void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); +static bool DtmDetectGlobalDeadLock(PGPROC* proc); -static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot }; +static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot, DtmDetectGlobalDeadLock }; void _PG_init(void); void _PG_fini(void); @@ -765,3 +766,9 @@ void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *sub } PgTransactionIdSetTreeStatus(xid, nsubxids, subxids, status, lsn); } + +bool DtmDetectGlobalDeadLock(PGPROC* proc) +{ + elog(WARNING, "Global deadlock?"); + return true; +} diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index 2c89b72..28cbf05 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -40,11 +40,13 @@ struct thread { pthread_t t; size_t proceeded; + size_t aborts; int id; void start(int tid, thread_proc_t proc) { id = tid; proceeded = 0; + aborts = 0; pthread_create(&t, NULL, proc, this); } @@ -160,12 +162,13 @@ void* writer(void* arg) int srcAcc = cfg.startId + random() % cfg.diapason; int dstAcc = cfg.startId + random() % cfg.diapason; + #if 1 // avoid deadlocks if (srcAcc > dstAcc) { int tmpAcc = dstAcc; dstAcc = srcAcc; srcAcc = tmpAcc; } - + #endif sprintf(gtid, "%d.%d.%d", cfg.startId, t.id, i); nontransaction srcTx(*srcCon); @@ -180,8 +183,16 @@ void* writer(void* arg) exec(srcTx, "savepoint c1"); exec(dstTx, "savepoint c2"); - exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); - exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); + try { + exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); + exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); + } catch (pqxx_exception const& x) { + exec(srcTx, "rollback"); + exec(dstTx, "rollback"); + t.aborts += 1; + i -= 1; + continue; + } exec(srcTx, "prepare transaction '%s'", gtid); exec(dstTx, "prepare transaction '%s'", gtid); @@ -281,7 +292,8 @@ int main (int argc, char* argv[]) vector writers(cfg.nWriters); size_t nReads = 0; size_t nWrites = 0; - + size_t nAborts = 0; + for (int i = 0; i < cfg.nReaders; i++) { readers[i].start(i, reader); } @@ -292,6 +304,7 @@ int main (int argc, char* argv[]) for (int i = 0; i < cfg.nWriters; i++) { writers[i].wait(); nWrites += writers[i].proceeded; + nAborts += writers[i].aborts; } running = false; @@ -307,12 +320,14 @@ int main (int argc, char* argv[]) printf( "{\"update_tps\":%f, \"read_tps\":%f," - " \"readers\":%d, \"writers\":%d," + " \"readers\":%d, \"writers\":%d, \"aborts\":%ld, \"abort_percent\": %d," " \"accounts\":%d, \"iterations\":%d, \"hosts\":%ld}\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed, cfg.nReaders, cfg.nWriters, + nAborts, + (int)(nAborts*100/nWrites), cfg.nAccounts, cfg.nIterations, cfg.connections.size() From 610f7c57d4cd12faaa20c4f30150fe7d9017367a Mon Sep 17 00:00:00 2001 From: knizhnik Date: Sun, 29 Nov 2015 22:08:11 +0300 Subject: [PATCH 43/46] Fix handlings of subtransactions --- pg_dtm--1.0.sql | 4 ++ pg_dtm.c | 54 +++++++++++++++++----- tests/dtmbench.cpp | 110 ++++++++++++++++++++++++++++++++++----------- tests/makefile | 2 +- 4 files changed, 132 insertions(+), 38 deletions(-) diff --git a/pg_dtm--1.0.sql b/pg_dtm--1.0.sql index 1e6766f..dcd81ac 100644 --- a/pg_dtm--1.0.sql +++ b/pg_dtm--1.0.sql @@ -20,3 +20,7 @@ LANGUAGE C; CREATE FUNCTION dtm_end_prepare(gtid cstring, csn bigint) RETURNS void AS 'MODULE_PATHNAME','dtm_end_prepare' LANGUAGE C; + +CREATE FUNCTION dtm_get_csn(xid integer) RETURNS bigint +AS 'MODULE_PATHNAME','dtm_get_csn' +LANGUAGE C; diff --git a/pg_dtm.c b/pg_dtm.c index 831e8a2..7f10ba8 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -85,6 +85,7 @@ static bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); static TransactionId DtmAdjustOldestXid(TransactionId xid); static void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); static bool DtmDetectGlobalDeadLock(PGPROC* proc); +static cid_t DtmGetCsn(TransactionId xid); static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot, DtmDetectGlobalDeadLock }; @@ -308,6 +309,7 @@ PG_FUNCTION_INFO_V1(dtm_access); PG_FUNCTION_INFO_V1(dtm_begin_prepare); PG_FUNCTION_INFO_V1(dtm_prepare); PG_FUNCTION_INFO_V1(dtm_end_prepare); +PG_FUNCTION_INFO_V1(dtm_get_csn); Datum dtm_extend(PG_FUNCTION_ARGS) @@ -357,7 +359,13 @@ dtm_end_prepare(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } - +Datum +dtm_get_csn(PG_FUNCTION_ARGS) +{ + TransactionId xid = PG_GETARG_INT32(0); + cid_t csn = DtmGetCsn(xid); + PG_RETURN_INT64(csn); +} /* * *************************************************************************** */ @@ -392,13 +400,22 @@ static int dtm_gtid_match_fn(const void *key1, const void *key2, Size keysize) return strcmp((GlobalTransactionId)key1, (GlobalTransactionId)key2); } -static void IncludeInTransactionList(DtmTransStatus* ts) +static void DtmTransactionListAppend(DtmTransStatus* ts) { ts->next = NULL; *local->trans_list_tail = ts; local->trans_list_tail = &ts->next; } +static void DtmTransactionListInsertAfter(DtmTransStatus* after, DtmTransStatus* ts) +{ + ts->next = after->next; + after->next = ts; + if (local->trans_list_tail == &after->next) { + local->trans_list_tail = &ts->next; + } +} + static TransactionId DtmAdjustOldestXid(TransactionId xid) { if (TransactionIdIsValid(xid)) { @@ -459,9 +476,12 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) while (true) { DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); - if (ts == NULL && TransactionIdFollowsOrEquals(xid, TransactionXmin)) { - xid = SubTransGetTopmostTransaction(xid); - ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + if (ts == NULL && + !(TransactionIdFollowsOrEquals(xid, snapshot->xmax) || TransactionIdPrecedes(xid, snapshot->xmin))) + { + //TransactionIdFollowsOrEquals(xid, TransactionXmin)) { + TransactionId subxid = SubTransGetTopmostTransaction(xid); + ts = (DtmTransStatus*)hash_search(xid2status, &subxid, HASH_FIND, NULL); } if (ts != NULL) { @@ -618,7 +638,7 @@ void DtmLocalBeginPrepare(GlobalTransactionId gtid) ts = (DtmTransStatus*)hash_search(xid2status, &id->xid, HASH_ENTER, NULL); ts->status = TRANSACTION_STATUS_IN_PROGRESS; ts->cid = dtm_get_cid(); - IncludeInTransactionList(ts); + DtmTransactionListAppend(ts); } SpinLockRelease(&local->lock); } @@ -685,7 +705,7 @@ void DtmLocalCommit(DtmTransState* x) } else if (!found) { //Assert(!found); ts->cid = dtm_get_cid(); - IncludeInTransactionList(ts); + DtmTransactionListAppend(ts); } x->cid = ts->cid; ts->status = TRANSACTION_STATUS_COMMITTED; @@ -724,7 +744,7 @@ void DtmLocalAbort(DtmTransState* x) } else if (!found) { //Assert(!found); ts->cid = dtm_get_cid(); - IncludeInTransactionList(ts); + DtmTransactionListAppend(ts); } x->cid = ts->cid; ts->status = TRANSACTION_STATUS_ABORTED; @@ -758,8 +778,7 @@ void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *sub Assert(!found); sts->status = status; sts->cid = ts->cid; - sts->next = ts->next; - ts->next = sts; + DtmTransactionListInsertAfter(ts, sts); } } SpinLockRelease(&local->lock); @@ -772,3 +791,18 @@ bool DtmDetectGlobalDeadLock(PGPROC* proc) elog(WARNING, "Global deadlock?"); return true; } + +static cid_t DtmGetCsn(TransactionId xid) +{ + cid_t csn = 0; + SpinLockAcquire(&local->lock); + { + DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + if (ts != NULL) { + csn = ts->cid; + } + } + SpinLockRelease(&local->lock); + return csn; +} + diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index 28cbf05..c4570d2 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -41,12 +41,14 @@ struct thread pthread_t t; size_t proceeded; size_t aborts; + time_t max_trans_duration; int id; void start(int tid, thread_proc_t proc) { id = tid; proceeded = 0; aborts = 0; + max_trans_duration = 0; pthread_create(&t, NULL, proc, this); } @@ -63,6 +65,9 @@ struct config int nAccounts; int startId; int diapason; + bool deadlockFree; + bool maxSnapshot; + bool makeSavepoints; vector connections; config() { @@ -72,6 +77,8 @@ struct config nAccounts = 100000; startId = 0; diapason = 100000; + deadlockFree = false; + makeSavepoints = false; } }; @@ -87,6 +94,9 @@ static time_t getCurrentTime() return (time_t)tv.tv_sec*USEC + tv.tv_usec; } +inline csn_t max(csn_t t1, csn_t t2) { + return t1 < t2 ? t2 : t1; +} void exec(transaction_base& txn, char const* sql, ...) { @@ -119,16 +129,26 @@ void* reader(void* arg) int64_t prevSum = 0; while (running) { - csn_t snapshot; + csn_t snapshot = 0; vector< unique_ptr > txns(conns.size()); + time_t start = getCurrentTime(); for (size_t i = 0; i < conns.size(); i++) { txns[i] = new work(*conns[i]); } - for (size_t i = 0; i < txns.size(); i++) { - if (i == 0) { - snapshot = execQuery(*txns[i], "select dtm_extend()"); - } else { - snapshot = execQuery(*txns[i], "select dtm_access(%ld)", snapshot); + if (cfg.maxSnapshot) { + for (size_t i = 0; i < txns.size(); i++) { + snapshot = max(snapshot, execQuery(*txns[i], "select dtm_extend()")); + } + for (size_t i = 0; i < txns.size(); i++) { + execQuery(*txns[i], "select dtm_access(%ld)", snapshot); + } + } else { + for (size_t i = 0; i < txns.size(); i++) { + if (i == 0) { + snapshot = execQuery(*txns[i], "select dtm_extend()"); + } else { + snapshot = execQuery(*txns[i], "select dtm_access(%ld)", snapshot); + } } } int64_t sum = 0; @@ -136,10 +156,14 @@ void* reader(void* arg) sum += execQuery(*txns[i], "select sum(v) from t"); } if (sum != prevSum) { - printf("Total=%ld snapshot=%ld\n", sum, snapshot); + printf("Total=%ld snapshot=%ldm delta=%ld usec\n", sum, snapshot, getCurrentTime()-snapshot); prevSum = sum; } t.proceeded += 1; + time_t elapsed = getCurrentTime() - start; + if (elapsed > t.max_trans_duration) { + t.max_trans_duration = elapsed; + } } return NULL; } @@ -156,33 +180,37 @@ void* writer(void* arg) { char gtid[32]; - // int srcAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - // int dstAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - int srcAcc = cfg.startId + random() % cfg.diapason; int dstAcc = cfg.startId + random() % cfg.diapason; - #if 1 // avoid deadlocks - if (srcAcc > dstAcc) { + if (cfg.deadlockFree && srcAcc > dstAcc) { // avoid deadlocks int tmpAcc = dstAcc; dstAcc = srcAcc; srcAcc = tmpAcc; } - #endif sprintf(gtid, "%d.%d.%d", cfg.startId, t.id, i); nontransaction srcTx(*srcCon); nontransaction dstTx(*dstCon); + time_t start = getCurrentTime(); + exec(srcTx, "begin transaction"); exec(dstTx, "begin transaction"); - csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); - snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); - - exec(srcTx, "savepoint c1"); - exec(dstTx, "savepoint c2"); - + if (cfg.maxSnapshot) { + csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); + snapshot = max(snapshot, execQuery(dstTx, "select dtm_extend('%s')", gtid)); + execQuery(srcTx, "select dtm_access(%ld, '%s')", snapshot, gtid); + execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); + } else { + csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); + snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); + } + if (cfg.makeSavepoints) { + exec(srcTx, "savepoint c1"); + exec(dstTx, "savepoint c2"); + } try { exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); @@ -204,7 +232,12 @@ void* writer(void* arg) exec(dstTx, "select dtm_end_prepare('%s', %ld)", gtid, csn); exec(srcTx, "commit prepared '%s'", gtid); exec(dstTx, "commit prepared '%s'", gtid); - + + time_t elapsed = getCurrentTime() - start; + if (elapsed > t.max_trans_duration) { + t.max_trans_duration = elapsed; + } + t.proceeded += 1; } return NULL; @@ -219,7 +252,7 @@ void initializeDatabase() exec(txn, "create extension pg_dtm"); exec(txn, "drop table if exists t"); exec(txn, "create table t(u int primary key, v int)"); - exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts, 0); + exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts-1, 0); txn.commit(); } } @@ -255,8 +288,18 @@ int main (int argc, char* argv[]) cfg.diapason = atoi(argv[++i]); continue; case 'C': + case 'c': cfg.connections.push_back(string(argv[++i])); continue; + case 'f': + cfg.deadlockFree = true; + continue; + case 'm': + cfg.maxSnapshot = true; + continue; + case 'x': + cfg.makeSavepoints = true; + continue; case 'i': initialize = true; continue; @@ -266,16 +309,19 @@ int main (int argc, char* argv[]) "\t-r N\tnumber of readers (1)\n" "\t-w N\tnumber of writers (10)\n" "\t-a N\tnumber of accounts (100000)\n" - "\t-s N\tperform updates starting from this id (1)\n" - "\t-d N\tperform updates in this diapason (100000)\n" + "\t-s N\tperform updates starting from this id (0)\n" + "\t-d N\tperform updates in this diapason (#accounts)\n" "\t-n N\tnumber of iterations (1000)\n" - "\t-C STR\tdatabase connection string\n" + "\t-c STR\tdatabase connection string\n" + "\t-f\tavoid deadlocks by ordering accounts\n" + "\t-m\tchoose maximal snapshot\n" + "\t-x\tmake savepoints\n" "\t-i\tinitialize datanase\n"); return 1; } if (cfg.startId + cfg.diapason > cfg.nAccounts) { - printf("startId + diapason should be less that nAccounts. Exiting.\n"); + cfg.diapason = cfg.nAccounts - cfg.startId; return 1; } @@ -293,7 +339,9 @@ int main (int argc, char* argv[]) size_t nReads = 0; size_t nWrites = 0; size_t nAborts = 0; - + time_t maxReadDuration = 0; + time_t maxWriteDuration = 0; + for (int i = 0; i < cfg.nReaders; i++) { readers[i].start(i, reader); } @@ -305,6 +353,9 @@ int main (int argc, char* argv[]) writers[i].wait(); nWrites += writers[i].proceeded; nAborts += writers[i].aborts; + if (writers[i].max_trans_duration > maxWriteDuration) { + maxWriteDuration = writers[i].max_trans_duration; + } } running = false; @@ -312,7 +363,10 @@ int main (int argc, char* argv[]) for (int i = 0; i < cfg.nReaders; i++) { readers[i].wait(); nReads += readers[i].proceeded; - } + if (readers[i].max_trans_duration > maxReadDuration) { + maxReadDuration = readers[i].max_trans_duration; + } + } time_t elapsed = getCurrentTime() - start; @@ -321,6 +375,7 @@ int main (int argc, char* argv[]) printf( "{\"update_tps\":%f, \"read_tps\":%f," " \"readers\":%d, \"writers\":%d, \"aborts\":%ld, \"abort_percent\": %d," + " \"max_read_duration\":%ld, \"max_write_duration\":%ld," " \"accounts\":%d, \"iterations\":%d, \"hosts\":%ld}\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed, @@ -328,6 +383,7 @@ int main (int argc, char* argv[]) cfg.nWriters, nAborts, (int)(nAborts*100/nWrites), + maxReadDuration, maxWriteDuration, cfg.nAccounts, cfg.nIterations, cfg.connections.size() diff --git a/tests/makefile b/tests/makefile index bcd7ee6..5246334 100644 --- a/tests/makefile +++ b/tests/makefile @@ -1,5 +1,5 @@ CXX=g++ -CXXFLAGS=-g -Wall -O2 -pthread +CXXFLAGS=-g -Wall -O0 -pthread all: dtmbench From c7ed87efab814ec4a0680fb6c0f70367237d3551 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 30 Nov 2015 15:26:21 +0300 Subject: [PATCH 44/46] Rewrite support if subtransactions --- pg_dtm.c | 146 +++++++++++++++++++++++++++++++++---------------------- pg_dtm.h | 20 ++++---- 2 files changed, 100 insertions(+), 66 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index 7f10ba8..8441a49 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -48,6 +48,7 @@ typedef struct DtmTransStatus { TransactionId xid; XidStatus status; + int nSubxids; cid_t cid; struct DtmTransStatus* next; } DtmTransStatus; @@ -65,6 +66,8 @@ typedef struct { char gtid[MAX_GTID_SIZE]; TransactionId xid; + TransactionId* subxids; + int nSubxids; } DtmTransId; @@ -75,7 +78,7 @@ static shmem_startup_hook_type prev_shmem_startup_hook; static HTAB* xid2status; static HTAB* gtid2xid; static DtmNodeState* local; -static DtmTransState dtm_tx; +static DtmCurrentTrans dtm_tx; static uint64 totalSleepInterrupts; static int DtmVacuumDelay; @@ -83,11 +86,11 @@ static Snapshot DtmGetSnapshot(Snapshot snapshot); static TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum); static bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); static TransactionId DtmAdjustOldestXid(TransactionId xid); -static void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); static bool DtmDetectGlobalDeadLock(PGPROC* proc); static cid_t DtmGetCsn(TransactionId xid); +static void DtmAddSubtransactions(DtmTransStatus* ts, TransactionId* subxids, int nSubxids); -static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot, DtmDetectGlobalDeadLock }; +static TransactionManager DtmTM = { PgTransactionIdGetStatus, PgTransactionIdSetTreeStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot, DtmDetectGlobalDeadLock }; void _PG_init(void); void _PG_fini(void); @@ -290,6 +293,7 @@ dtm_xact_callback(XactEvent event, void *arg) break; case XACT_EVENT_PREPARE: + DtmLocalSavePreparedState(dtm_get_global_trans_id()); DtmLocalEnd(&dtm_tx); break; @@ -462,6 +466,7 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) static timestamp_t firstReportTime; static timestamp_t prevReportTime; static timestamp_t totalSleepTime; + static timestamp_t maxSleepTime; #endif timestamp_t delay = MIN_WAIT_TIMEOUT; Assert(xid != InvalidTransactionId); @@ -476,13 +481,6 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) while (true) { DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); - if (ts == NULL && - !(TransactionIdFollowsOrEquals(xid, snapshot->xmax) || TransactionIdPrecedes(xid, snapshot->xmin))) - { - //TransactionIdFollowsOrEquals(xid, TransactionXmin)) { - TransactionId subxid = SubTransGetTopmostTransaction(xid); - ts = (DtmTransStatus*)hash_search(xid2status, &subxid, HASH_FIND, NULL); - } if (ts != NULL) { if (ts->cid > dtm_tx.snapshot) { @@ -497,17 +495,21 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) SpinLockRelease(&local->lock); #if TRACE_SLEEP_TIME { - timestamp_t now = dtm_get_current_time(); + timestamp_t delta, now = dtm_get_current_time(); #endif dtm_sleep(delay); #if TRACE_SLEEP_TIME - totalSleepTime += dtm_get_current_time() - now; - if (now > prevReportTime + USEC*1) { + delta = dtm_get_current_time() - now; + totalSleepTime += delta; + if (delta > maxSleepTime) { + maxSleepTime = delta; + } + if (now > prevReportTime + USEC*10) { prevReportTime = now; if (firstReportTime == 0) { firstReportTime = now; } else { - fprintf(stderr, "Snapshot sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + fprintf(stderr, "Snapshot sleep %lu of %lu usec (%f%%), maximum=%lu\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime), maxSleepTime); } } } @@ -577,7 +579,7 @@ void DtmInitialize() } -void DtmLocalBegin(DtmTransState* x) +void DtmLocalBegin(DtmCurrentTrans* x) { if (x->xid == InvalidTransactionId) { SpinLockAcquire(&local->lock); @@ -592,23 +594,23 @@ void DtmLocalBegin(DtmTransState* x) } } -cid_t DtmLocalExtend(DtmTransState* x, GlobalTransactionId gtid) +cid_t DtmLocalExtend(DtmCurrentTrans* x, GlobalTransactionId gtid) { if (gtid != NULL) { SpinLockAcquire(&local->lock); { DtmTransId* id = (DtmTransId*)hash_search(gtid2xid, gtid, HASH_ENTER, NULL); - x->is_global = true; id->xid = x->xid; + id->nSubxids = 0; + id->subxids = 0; } SpinLockRelease(&local->lock); - } else { - x->is_global = true; - } + } + x->is_global = true; return x->snapshot; } -cid_t DtmLocalAccess(DtmTransState* x, GlobalTransactionId gtid, cid_t global_cid) +cid_t DtmLocalAccess(DtmCurrentTrans* x, GlobalTransactionId gtid, cid_t global_cid) { cid_t local_cid; SpinLockAcquire(&local->lock); @@ -616,6 +618,8 @@ cid_t DtmLocalAccess(DtmTransState* x, GlobalTransactionId gtid, cid_t global_ci if (gtid != NULL) { DtmTransId* id = (DtmTransId*)hash_search(gtid2xid, gtid, HASH_ENTER, NULL); id->xid = x->xid; + id->nSubxids = 0; + id->subxids = 0; } local_cid = dtm_sync(global_cid); x->snapshot = local_cid; @@ -638,7 +642,9 @@ void DtmLocalBeginPrepare(GlobalTransactionId gtid) ts = (DtmTransStatus*)hash_search(xid2status, &id->xid, HASH_ENTER, NULL); ts->status = TRANSACTION_STATUS_IN_PROGRESS; ts->cid = dtm_get_cid(); + ts->nSubxids = id->nSubxids; DtmTransactionListAppend(ts); + DtmAddSubtransactions(ts, id->subxids, id->nSubxids); } SpinLockRelease(&local->lock); } @@ -661,6 +667,7 @@ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid) { DtmTransStatus* ts; DtmTransId* id; + int i; id = (DtmTransId*)hash_search(gtid2xid, gtid, HASH_FIND, NULL); Assert(id != NULL); @@ -668,7 +675,10 @@ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid) ts = (DtmTransStatus*)hash_search(xid2status, &id->xid, HASH_FIND, NULL); Assert(ts != NULL); ts->cid = cid; - + for (i = 0; i < ts->nSubxids; i++) { + ts = ts->next; + ts->cid = cid; + } dtm_sync(cid); DTM_TRACE((stderr, "Prepare transaction %u(%s) with CSN %lu\n", id->xid, gtid, cid)); @@ -676,7 +686,7 @@ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid) SpinLockRelease(&local->lock); } -void DtmLocalCommitPrepared(DtmTransState* x, GlobalTransactionId gtid) +void DtmLocalCommitPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid) { Assert(gtid != NULL); @@ -688,33 +698,45 @@ void DtmLocalCommitPrepared(DtmTransState* x, GlobalTransactionId gtid) x->is_global = true; x->is_prepared = true; x->xid = id->xid; + free(id->subxids); + DTM_TRACE((stderr, "Global transaction %u(%s) is precommitted\n", x->xid, gtid)); } SpinLockRelease(&local->lock); } -void DtmLocalCommit(DtmTransState* x) +void DtmLocalCommit(DtmCurrentTrans* x) { SpinLockAcquire(&local->lock); { bool found; DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &x->xid, HASH_ENTER, &found); + ts->status = TRANSACTION_STATUS_COMMITTED; if (x->is_prepared) { + int i; + DtmTransStatus* sts = ts; Assert(found); Assert(x->is_global); - } else if (!found) { - //Assert(!found); + for (i = 0; i < ts->nSubxids; i++) { + sts = sts->next; + Assert(sts->cid == ts->cid); + sts->status = TRANSACTION_STATUS_COMMITTED; + } + } else { + TransactionId* subxids; + Assert(!found); ts->cid = dtm_get_cid(); DtmTransactionListAppend(ts); + ts->nSubxids = xactGetCommittedChildren(&subxids); + DtmAddSubtransactions(ts, subxids, ts->nSubxids); } x->cid = ts->cid; - ts->status = TRANSACTION_STATUS_COMMITTED; DTM_TRACE((stderr, "Local transaction %u is committed at %lu\n", x->xid, x->cid)); } SpinLockRelease(&local->lock); } -void DtmLocalAbortPrepared(DtmTransState* x, GlobalTransactionId gtid) +void DtmLocalAbortPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid) { Assert (gtid != NULL); @@ -726,13 +748,14 @@ void DtmLocalAbortPrepared(DtmTransState* x, GlobalTransactionId gtid) x->is_global = true; x->is_prepared = true; x->xid = id->xid; + free(id->subxids); DTM_TRACE((stderr, "Global transaction %u(%s) is preaborted\n", x->xid, gtid)); } SpinLockRelease(&local->lock); } -void DtmLocalAbort(DtmTransState* x) +void DtmLocalAbort(DtmCurrentTrans* x) { SpinLockAcquire(&local->lock); { @@ -741,9 +764,10 @@ void DtmLocalAbort(DtmTransState* x) if (x->is_prepared) { Assert(found); Assert(x->is_global); - } else if (!found) { - //Assert(!found); + } else { + Assert(!found); ts->cid = dtm_get_cid(); + ts->nSubxids = 0; DtmTransactionListAppend(ts); } x->cid = ts->cid; @@ -753,7 +777,7 @@ void DtmLocalAbort(DtmTransState* x) SpinLockRelease(&local->lock); } -void DtmLocalEnd(DtmTransState* x) +void DtmLocalEnd(DtmCurrentTrans* x) { x->is_global = false; x->is_prepared = false; @@ -761,31 +785,6 @@ void DtmLocalEnd(DtmTransState* x) x->cid = INVALID_CID; } -void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn) -{ - if (nsubxids != 0) { - SpinLockAcquire(&local->lock); - { - int i; - bool found; - DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_ENTER, &found); - if (!found) { - ts->cid = dtm_get_cid(); - } - ts->status = status; - for (i = 0; i < nsubxids; i++) { - DtmTransStatus* sts = (DtmTransStatus*)hash_search(xid2status, &subxids[i], HASH_ENTER, &found); - Assert(!found); - sts->status = status; - sts->cid = ts->cid; - DtmTransactionListInsertAfter(ts, sts); - } - } - SpinLockRelease(&local->lock); - } - PgTransactionIdSetTreeStatus(xid, nsubxids, subxids, status, lsn); -} - bool DtmDetectGlobalDeadLock(PGPROC* proc) { elog(WARNING, "Global deadlock?"); @@ -806,3 +805,36 @@ static cid_t DtmGetCsn(TransactionId xid) return csn; } +void DtmLocalSavePreparedState(GlobalTransactionId gtid) +{ + if (gtid != NULL) { + SpinLockAcquire(&local->lock); + { + DtmTransId* id = (DtmTransId*)hash_search(gtid2xid, gtid, HASH_FIND, NULL); + if (id != NULL) { + TransactionId* subxids; + int nSubxids = xactGetCommittedChildren(&subxids); + if (nSubxids != 0) { + id->subxids = (TransactionId*)malloc(nSubxids*sizeof(TransactionId)); + id->nSubxids = nSubxids; + memcpy(id->subxids, subxids, nSubxids*sizeof(TransactionId)); + } + } + } + SpinLockRelease(&local->lock); + } +} + +static void DtmAddSubtransactions(DtmTransStatus* ts, TransactionId* subxids, int nSubxids) +{ + int i; + for (i = 0; i < nSubxids; i++) { + bool found; + DtmTransStatus* sts = (DtmTransStatus*)hash_search(xid2status, &subxids[i], HASH_ENTER, &found); + Assert(!found); + sts->status = ts->status; + sts->cid = ts->cid; + sts->nSubxids = 0; + DtmTransactionListInsertAfter(ts, sts); + } +} diff --git a/pg_dtm.h b/pg_dtm.h index eedd3b2..f84892b 100644 --- a/pg_dtm.h +++ b/pg_dtm.h @@ -10,18 +10,18 @@ typedef struct { bool is_prepared; cid_t cid; cid_t snapshot; -} DtmTransState; +} DtmCurrentTrans; typedef char const* GlobalTransactionId; /* Initialize DTM extension */ void DtmInitialize(void); /* Invoked at start of any local or global transaction */ -void DtmLocalBegin(DtmTransState* x); +void DtmLocalBegin(DtmCurrentTrans* x); /* Extend local transaction to global by assigning upper bound CSN which is returned to coordinator */ -cid_t DtmLocalExtend(DtmTransState* x, GlobalTransactionId gtid); +cid_t DtmLocalExtend(DtmCurrentTrans* x, GlobalTransactionId gtid); /* Function called at first access to any datanode except first one involved in distributed transaction */ -cid_t DtmLocalAccess(DtmTransState* x, GlobalTransactionId gtid, cid_t snapshot); +cid_t DtmLocalAccess(DtmCurrentTrans* x, GlobalTransactionId gtid, cid_t snapshot); /* Mark transaction as in-doubt */ void DtmLocalBeginPrepare(GlobalTransactionId gtid); /* Choose CSN for global transaction */ @@ -29,14 +29,16 @@ cid_t DtmLocalPrepare(GlobalTransactionId gtid, cid_t cid); /* Assign CSN to global transaction */ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid); /* Do local commit of global transaction */ -void DtmLocalCommitPrepared(DtmTransState* x, GlobalTransactionId gtid); +void DtmLocalCommitPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid); /* Do local abort of global transaction */ -void DtmLocalAbortPrepared(DtmTransState* x, GlobalTransactionId gtid); +void DtmLocalAbortPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid); /* Do local commit of global transaction */ -void DtmLocalCommit(DtmTransState* x); +void DtmLocalCommit(DtmCurrentTrans* x); /* Do local abort of global transaction */ -void DtmLocalAbort(DtmTransState* x); +void DtmLocalAbort(DtmCurrentTrans* x); /* Invoked at the end of any local or global transaction: free transaction state */ -void DtmLocalEnd(DtmTransState* x); +void DtmLocalEnd(DtmCurrentTrans* x); +/* Save global preapred transactoin state */ +void DtmLocalSavePreparedState(GlobalTransactionId gtid); #endif From 877f5cb03fb97ed922aaaddcd4f681374dac2b16 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Thu, 3 Dec 2015 12:35:12 +0300 Subject: [PATCH 45/46] Add dtm_recovery --- dtm_recovery/dtm_recovery.cpp | 129 ++++++++++++++++++++++++++++++++++ dtm_recovery/makefile | 10 +++ pg_dtm.c | 26 +++++++ tests/dtmbench.cpp | 12 ++-- 4 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 dtm_recovery/dtm_recovery.cpp create mode 100644 dtm_recovery/makefile diff --git a/dtm_recovery/dtm_recovery.cpp b/dtm_recovery/dtm_recovery.cpp new file mode 100644 index 0000000..338dfdd --- /dev/null +++ b/dtm_recovery/dtm_recovery.cpp @@ -0,0 +1,129 @@ +#include +#include +#include +#include + +#include +#include +#include + +using namespace std; +using namespace pqxx; + +int main (int argc, char* argv[]) +{ + if (argc == 1){ + printf("Use -h to show usage options\n"); + return 1; + } + vector connections; + set prepared_xacts; + set committed_xacts; + bool verbose = false; + for (int i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 'C': + case 'c': + connections.push_back(string(argv[++i])); + continue; + case 'v': + verbose = true; + continue; + } + } + printf("Perform recovery of pg_tsdtm cluster.\n" + "Usage: dtm_recovery {options}\n" + "Options:\n" + "\t-c STR\tdatabase connection string\n" + "\t-v\tverbose mode: print extra information while processing\n"); + return 1; + } + if (verbose) { + cout << "Collecting information about prepared transactions...\n"; + } + for (vector::iterator ic = connections.begin(); ic != connections.end(); ++ic) + { + if (verbose) { + cout << "Connecting to " << *ic << "...\n"; + } + connection con(*ic); + work txn(con); + result r = txn.exec("select gid from pg_prepared_xacts"); + for (result::const_iterator it = r.begin(); it != r.end(); ++it) + { + string gid = it.at("gid").as(string()); + prepared_xacts.insert(gid); + } + txn.commit(); + } + if (verbose) { + cout << "Prepared transactions: "; + for (set::iterator it = prepared_xacts.begin(); it != prepared_xacts.end(); ++it) + { + cout << *it << ", "; + } + cout << "\nChecking which of them are committed...\n"; + } + for (vector::iterator ic = connections.begin(); ic != connections.end(); ++ic) + { + if (verbose) { + cout << "Connecting to " << *ic << "...\n"; + } + connection con(*ic); + work txn(con); + con.prepare("commit-check", "select * from pg_committed_xacts where gid=$1"); + for (set::iterator it = prepared_xacts.begin(); it != prepared_xacts.end(); ++it) + { + string gid = *it; + result r = txn.prepared("commit-check")(gid).exec(); + if (!r.empty()) { + committed_xacts.insert(gid); + } + } + txn.commit(); + } + if (verbose) { + cout << "Committed transactions: "; + for (set::iterator it = committed_xacts.begin(); it != committed_xacts.end(); ++it) + { + cout << *it << ", "; + } + cout << "\nCommitting them at all nodes...\n"; + } + for (vector::iterator ic = connections.begin(); ic != connections.end(); ++ic) + { + if (verbose) { + cout << "Connecting to " << *ic << "...\n"; + } + connection con(*ic); + work txn(con); + con.prepare("commit-check", "select * from pg_committed_xacts where gid=$1"); + con.prepare("commit-prepared", "commit prepared $1"); + con.prepare("rollback-prepared", "rollback prepared $1"); + result r = txn.exec("select gid from pg_prepared_xacts"); + for (result::const_iterator it = r.begin(); it != r.end(); ++it) + { + string gid = it.at("gid").as(string()); + result rc = txn.prepared("commit-check")(gid).exec(); + if (rc.empty()) { + if (committed_xacts.find(gid) != committed_xacts.end()) { + if (verbose) { + cout << "Commit transaction " << gid << "\n"; + } + txn.prepared("commit-prepared")(gid); + } else { + if (verbose) { + cout << "Rollback transaction " << gid << "\n"; + } + txn.prepared("rollback-prepared")(gid); + } + } + } + txn.commit(); + } + if (verbose) { + cout << "Recovery completed\n"; + } + return 0; +} diff --git a/dtm_recovery/makefile b/dtm_recovery/makefile new file mode 100644 index 0000000..27bdf3f --- /dev/null +++ b/dtm_recovery/makefile @@ -0,0 +1,10 @@ +CXX=g++ +CXXFLAGS=-g -Wall -O0 -pthread + +all: dtm_recovery + +dtm_recovery: dtm_recovery.cpp + $(CXX) $(CXXFLAGS) -o dtm_recovery dtm_recovery.cpp -lpqxx + +clean: + rm -f dtm_recovery diff --git a/pg_dtm.c b/pg_dtm.c index 8441a49..6afb19b 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -25,6 +25,7 @@ #include "access/xlog.h" #include "access/clog.h" #include "access/twophase.h" +#include "executor/spi.h" #include "utils/hsearch.h" #include "utils/tqual.h" #include @@ -81,6 +82,7 @@ static DtmNodeState* local; static DtmCurrentTrans dtm_tx; static uint64 totalSleepInterrupts; static int DtmVacuumDelay; +static bool DtmRecordCommits; static Snapshot DtmGetSnapshot(Snapshot snapshot); static TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum); @@ -211,6 +213,19 @@ _PG_init(void) NULL ); + DefineCustomBoolVariable( + "dtm.record_commits", + "Store information about committed global transactions in pg_committed_xacts table", + NULL, + &DtmRecordCommit, + false, + PGC_BACKEND, + 0, + NULL, + NULL, + NULL + ); + /* * Install hooks. @@ -684,6 +699,17 @@ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid) DTM_TRACE((stderr, "Prepare transaction %u(%s) with CSN %lu\n", id->xid, gtid, cid)); } SpinLockRelease(&local->lock); + if (DtmRecordCommits) { + char stmt[MAX_GTID_SIZE + 64]; + int rc; + sprintf(stmt, "insert into pg_committed_xacts values ('%s')", gtid); + SPI_connect(); + rc = SPI_execute(stmt, true, 0); + SPI_finish(); + if (rc != SPI_OK_INSERT) { + elog(ERROR, "Failed to insert GTID %s in table pg_committed_xacts", gtid); + } + } } void DtmLocalCommitPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid) diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index c4570d2..37aee0e 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -17,17 +17,17 @@ using namespace std; using namespace pqxx; template -class unique_ptr +class my_unique_ptr { T* ptr; public: - unique_ptr(T* p = NULL) : ptr(p) {} - ~unique_ptr() { delete ptr; } + my_unique_ptr(T* p = NULL) : ptr(p) {} + ~my_unique_ptr() { delete ptr; } T& operator*() { return *ptr; } T* operator->() { return ptr; } void operator=(T* p) { ptr = p; } - void operator=(unique_ptr& other) { + void operator=(my_unique_ptr& other) { ptr = other.ptr; other.ptr = NULL; } @@ -122,7 +122,7 @@ int64_t execQuery( transaction_base& txn, char const* sql, ...) void* reader(void* arg) { thread& t = *(thread*)arg; - vector< unique_ptr > conns(cfg.connections.size()); + vector< my_unique_ptr > conns(cfg.connections.size()); for (size_t i = 0; i < conns.size(); i++) { conns[i] = new connection(cfg.connections[i]); } @@ -130,7 +130,7 @@ void* reader(void* arg) while (running) { csn_t snapshot = 0; - vector< unique_ptr > txns(conns.size()); + vector< my_unique_ptr > txns(conns.size()); time_t start = getCurrentTime(); for (size_t i = 0; i < conns.size(); i++) { txns[i] = new work(*conns[i]); From 5ac02f84890926631d2aab4a41c2ef350c1ac167 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 9 Dec 2015 19:29:47 +0300 Subject: [PATCH 46/46] typo --- pg_dtm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pg_dtm.c b/pg_dtm.c index 6afb19b..0dc53f0 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -217,7 +217,7 @@ _PG_init(void) "dtm.record_commits", "Store information about committed global transactions in pg_committed_xacts table", NULL, - &DtmRecordCommit, + &DtmRecordCommits, false, PGC_BACKEND, 0,