{"id":14736,"date":"2020-09-23T16:54:37","date_gmt":"2020-09-23T14:54:37","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/"},"modified":"2020-09-23T16:54:37","modified_gmt":"2020-09-23T14:54:37","slug":"instant-postgresql-cloning-with-suse-and-btrfs","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/","title":{"rendered":"Instant PostgreSQL Cloning with SUSE and Btrfs"},"content":{"rendered":"<p>What if you could clone a PostgreSQL database instantly without affecting the original source database, without impacting performance, without any external tool but using your linux Btrfs storage layer.<br \/>\nThis is what I will demonstrate in the following blogpost.<br \/>\n<!--more--><\/p>\n<h2>Introduction<\/h2>\n<p>Sometimes developpers need urgently a copy of a PostgreSQL database where they can test new developments or make changes that won&#8217;t modify the source database.<br \/>\nThe usual way is to ask for the most recent backup of the database and restore it on another server (staging or test).<br \/>\nThe major problem of this solution is the time needed which is exponential with the database size and nowadays it is not affordable to wait every time several hours.<br \/>\nBut with SUSE Btrfs, it is possible to circumvent this pitfal by using a nice feature called &#8220;Copy-On-Write&#8221; snapshot which is default since SLES version 12 .<br \/>\nOf course, and as a prerequisite, your source Postgres cluster must reside on a Btrfs filesystem.<\/p>\n<h2>Installation<\/h2>\n<p>For my demonstration that you can easily reproduce, I will use a SLES version 15 minimal installation.<br \/>\nAs usual we start to create a PostgreSQL user and Group. We add it to the sudo configuration so we don&#8217;t need everytime to jump from postgres to root and conversely.<br \/>\n<code>sles15:~ # <span style=\"color: orange\">groupadd postgres<\/span><br \/>\nsles15:~ # <span style=\"color: orange\">useradd -g postgres -m postgres<\/span><br \/>\nsles15:~ # <span style=\"color: orange\">passwd postgres<\/span><\/code><br \/>\nWe need now to install the required packages, prepare the installation, download and install PostgreSQL 12.4<br \/>\n<code>postgres@sles15:~&gt; <span style=\"color: orange\">sudo zypper -n install wget gcc readline-devel zlib-devel libopenssl-devel pam-devel libxml2-devel libxslt-devel openldap2-devel python3-devel sysstat make systemd-devel bzip2 llvm7-devel llvm7 clang7 libicu-devel<br \/>\nclang7 llvm7-devel llvm7 wget<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">sudo mkdir -p \/u01\/app\/postgres<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">sudo chown postgres:postgres \/u01\/app\/postgres<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">wget https:\/\/ftp.postgresql.org\/pub\/source\/v12.4\/postgresql-12.4.tar.bz2<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">tar -axf postgresql-12.4.tar.bz2<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">cd postgresql-12.4\/<\/span><br \/>\npostgres@sles15:~\/postgresql-12.4&gt; <span style=\"color: orange\">.\/configure --prefix=\/u01\/app\/postgres\/product\/12\/db_4<\/span><br \/>\npostgres@sles15:~\/postgresql-12.4&gt;<span style=\"color: orange\"> make all<\/span><br \/>\npostgres@sles15:~\/postgresql-12.4&gt; <span style=\"color: orange\">make install<\/span><br \/>\npostgres@sles15:~\/postgresql-12.4&gt; <span style=\"color: orange\">cd contrib<\/span><br \/>\npostgres@sles15:~\/postgresql-12.4\/contrib&gt; <span style=\"color: orange\">make install<\/span><br \/>\npostgres@sles15:~\/postgresql-12.4\/contrib&gt; <span style=\"color: orange\">cd ..\/..<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">rm -rf postgresql-12.4<\/span><\/code><br \/>\nWe create now a new Btrfs filesystem and a subvolume for the source PostgreSQL cluster.<br \/>\n<code>postgres@sles15:~&gt; <span style=\"color: orange\">sudo mkdir -p \/pgdatas<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">lsblk<\/span><br \/>\nNAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT<br \/>\nsda      8:0    0   30G  0 disk<br \/>\n\u251c\u2500sda1   8:1    0    8M  0 part<br \/>\n\u251c\u2500sda2   8:2    0 18.6G  0 part \/boot\/grub2\/i386-pc<br \/>\n\u251c\u2500sda3   8:3    0  9.4G  0 part \/home<br \/>\n\u2514\u2500sda4   8:4    0    2G  0 part [SWAP]<br \/>\nsdb      8:16   0 52.7G  0 disk<br \/>\nsr0     11:0    1  373M  0 rom<br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">sudo mkfs.btrfs \/dev\/sdb<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">exit<\/span><br \/>\nsles15:~ # <span style=\"color: orange\">echo \"\/dev\/sdb \/pgdatas btrfs defaults\" &gt;&gt; \/etc\/fstab<\/span><br \/>\nsles15:~ # <span style=\"color: orange\">mount -a<\/span><br \/>\nsles15:~ # <span style=\"color: orange\">df -h \/pgdatas<\/span><br \/>\n\/dev\/sdb 53G 3.8M 53G 1% \/pgdata<br \/>\nsles15:~ # <span style=\"color: orange\">su - postgres<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">sudo chown postgres:postgres \/pgdatas\/<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">sudo btrfs subvolume create \/pgdatas\/pg1<\/span><br \/>\nCreate subvolume '\/pgdatas\/pg1'<br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">sudo btrfs subvolume list \/pgdatas\/<\/span><br \/>\nID 257 gen 8 top level 5 path pg1<\/code><br \/>\nLet&#8217;s create and start the PostgreSQL cluster to be cloned.<br \/>\nAs we need a consistent database for our tests, we will populate some data by using pgbench, the PostgreSQL benchmarking tool, in order to get a 15Gb database.<br \/>\n<code>postgres@sles15:~&gt; <span style=\"color: orange\">sudo chown postgres:postgres \/pgdatas\/pg1<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">\/u01\/app\/postgres\/product\/12\/db_4\/bin\/initdb -D \/pgdatas\/pg1<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">\/u01\/app\/postgres\/product\/12\/db_4\/bin\/pg_ctl -D \/pgdatas\/pg1 -l \/dev\/null start<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">\/u01\/app\/postgres\/product\/12\/db_4\/bin\/psql -l<\/span><br \/>\nList of databases<br \/>\nName \u00a0 \u00a0 \u00a0   |  Owner. \u00a0   | Encoding |   Collate \u00a0 \u00a0  |    Ctype \u00a0 \u00a0 \u00a0    |   Access privileges<br \/>\n-----------+----------+----------+-------------+-------------+-----------------------<br \/>\npostgres \u00a0 | postgres | UTF8. \u00a0\u00a0     | en_US.UTF-8 | en_US.UTF-8 |<br \/>\ntemplate0\u00a0 | postgres | UTF8\u00a0\u00a0\u00a0\u00a0 | en_US.UTF-8 | en_US.UTF-8 | =c\/postgres          +<br \/>\ntemplate1\u00a0 | postgres | UTF8. \u00a0\u00a0     | en_US.UTF-8 | en_US.UTF-8 | =c\/postgres          +<br \/>\n(3 rows)<br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">export PATH=\/u01\/app\/postgres\/product\/12\/db_4\/bin\/:$PATH<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">createuser --login --pwprompt dbi<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">createdb -e --owner=dbi dbi<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">pgbench --initialize --scale=1000 -U dbi dbi<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">psql -c \"select pg_size_pretty(pg_database_size('dbi'))\"<\/span><br \/>\npg_size_pretty<br \/>\n----------------<br \/>\n15 GB<\/code><br \/>\nFor my demonstration to be effective, I need also to generate some load on the source cluster and I will use again pgbench for that, with 60 transactions per second and 16 simultaneous users. I let it run for 10mn and meanwhile in another session, I will create two clones, staging and test to show you that it will take no resources on the original database.<br \/>\n<code>postgres@sles15:~&gt; <span style=\"color: orange\">pgbench -U dbi --rate=60 --client=16 --progress=5 --time=600 dbi<\/span><br \/>\npostgres@sles15:~&gt; <span style=\"color: orange\">cd \/pgdatas\/<\/span><br \/>\npostgres@sles15:\/pgdatas&gt; <span style=\"color: orange\">time sudo btrfs subvolume snapshot PG1 staging<\/span><br \/>\nCreate a snapshot of 'pg1' in '.\/staging'<br \/>\n<span style=\"color: orange\">real    0m0.123s<\/span><br \/>\nuser    0m0.011s<br \/>\nsys     0m0.034s<br \/>\npostgres@sles15:\/pgdatas&gt; <span style=\"color: orange\">time sudo btrfs subvolume snapshot pg1 test<\/span><br \/>\nCreate a snapshot of 'pg1' in '.\/test'<br \/>\n<span style=\"color: orange\">real 0m0.098s<\/span><br \/>\nuser 0m0.024s<br \/>\nsys 0m0.014s<\/code><br \/>\nYou can see below that with the pgbench statistics, there is absolutely no impact on performances meaning that this could be easily done on a productive cluster.<br \/>\n<code>progress: 5.0 s, 51.8 tps, lat 945.726 ms stddev 203.743, lag 655.979 ms<br \/>\nprogress: 10.0 s, 67.0 tps, lat 245.902 ms stddev 259.702, lag 105.411 ms<br \/>\nprogress: 15.0 s, 61.8 tps, lat 77.370 ms stddev 52.207, lag 0.556 ms<br \/>\nprogress: 20.0 s, 61.2 tps, lat 67.853 ms stddev 42.487, lag 2.345 ms<br \/>\nprogress: 25.0 s, 60.6 tps, lat 63.429 ms stddev 71.115, lag 3.930 ms<br \/>\nprogress: 30.0 s, 66.2 tps, lat 49.639 ms stddev 49.599, lag 5.884 ms<\/code><br \/>\nOur 2 clones are ready but we need still some additional work.<br \/>\nAs it is an atomic snapshot of our PostgreSQL subvolume, and we have exactly the same content, the postmaster.pid file which contains the process id of the source cluster has to be removed because as you might know, we can&#8217;t start our new PostgreSQL instance with the same PID, so we remove it.<br \/>\nBut it&#8217;s not enough, we have also to change the port and we do that by echoing the new port in postgresql.auto.conf.<br \/>\n<code>postgres@sles15:\/u02\/pgdata&gt; <span style=\"color: orange\">rm -f \/pgdatas\/staging\/postmaster.pid<\/span><br \/>\npostgres@sles15:\/u02\/pgdata&gt; <span style=\"color: orange\">rm -f \/pgdatas\/test\/postmaster.pid<\/span><br \/>\npostgres@sles15:\/u02\/pgdata&gt; <span style=\"color: orange\">echo \"port=5433\" &gt; \/u02\/pgdata\/staging\/postgresql.auto.conf<\/span><br \/>\npostgres@sles15:\/u02\/pgdata&gt; <span style=\"color: orange\">echo \"port=5434\" &gt; \/u02\/pgdata\/test\/postgresql.auto.conf<\/span><\/code><br \/>\nThe starting process will take some time because clones must be consistent and include everything that has been committed. So PostgreSQL will perform a recovery.<br \/>\n<code>postgres@sles15:\/u02\/pgdata&gt; <span style=\"color: orange\">pg_ctl -D \/pgdatas\/staging\/ start<\/span><br \/>\n# \/u01\/app\/postgres\/product\/12\/db_4\/bin\/pg_ctl -D \/pgdatas\/staging start<br \/>\nwaiting for server to start....2020-09-23 16:03:41.930 CEST [4248] LOG:  starting PostgreSQL 12.4 dbi services build on x86_64-pc-linux-gnu, compiled by gcc (SUSE Linux) 7.5.0, 64-bit<br \/>\n2020-09-23 16:03:41.934 CEST [4248] LOG:  listening on IPv6 address \"::1\", port 5433<br \/>\n2020-09-23 16:03:41.934 CEST [4248] LOG:  listening on IPv4 address \"127.0.0.1\", port 5433<br \/>\n2020-09-23 16:03:41.943 CEST [4248] LOG:  listening on Unix socket \"\/tmp\/.s.PGSQL.5433\"<br \/>\n2020-09-23 16:03:41.980 CEST [4249] LOG:  database system was interrupted; last known up at 2020-09-23 15:48:30 CEST<br \/>\n2020-09-23 16:03:42.137 CEST [4249] LOG:  <span style=\"color: orange\">database system was not properly shut down; automatic recovery in progress<\/span><br \/>\n2020-09-23 16:03:42.144 CEST [4249] LOG:  redo starts at 11\/6545A890<br \/>\n.2020-09-23 16:03:43.034 CEST [4249] LOG:  invalid record length at 11\/66662ED8: wanted 24, got 0<br \/>\n2020-09-23 16:03:43.034 CEST [4249] LOG:  redo done at 11\/66662EB0<br \/>\n............2020-09-23 16:03:55.151 CEST [4248] LOG:  database system is ready to accept connections<br \/>\ndone<br \/>\nserver started<\/code><\/p>\n<h2>Test<\/h2>\n<p>To illustrate that our clones won&#8217;t affect the source database when performing queries, let&#8217;s make a simple test on both clones.<br \/>\nFirst we check the filler field of the pgbench_tellers on all 3 clusters. We update it on the clones and we remove most of the rows of the pgbench_telers on the test clone only and we check again.<br \/>\n<code><span style=\"color: orange\">for val in {2 3 4}<br \/>\ndo<br \/>\npsql -p 543${val} -U dbi -d dbi -c \"select * from pgbench_tellers order by 1 limit 2\"<br \/>\npsql -p 543${val} -U dbi -d dbi -c \"select count(*) from pgbench_tellers\"<br \/>\ndone<\/span><br \/>\nSource<br \/>\n------<br \/>\ntid\u00a0 | bid | tbalance | filler<br \/>\n-----+-----+----------+--------<br \/>\n1\u00a0\u00a0\u00a0 |   1\u00a0\u00a0 |    24028. \u00a0 |<br \/>\n2\u00a0\u00a0\u00a0 |   1.\u00a0 |   -27698.\u00a0 |<br \/>\ncount<br \/>\n-------<br \/>\n10000<br \/>\nClone staging<br \/>\n-------------<br \/>\ntid\u00a0 | bid | tbalance | filler<br \/>\n-----+-----+----------+--------<br \/>\n1\u00a0\u00a0\u00a0 |   1\u00a0\u00a0 |    22651. \u00a0 |<br \/>\n2\u00a0\u00a0\u00a0 |   1\u00a0\u00a0 |   -34706.\u00a0 |<br \/>\ncount<br \/>\n-------<br \/>\n10000<br \/>\nClone test<br \/>\n----------<br \/>\ntid\u00a0 | bid | tbalance | filler<br \/>\n-----+-----+----------+--------<br \/>\n1\u00a0\u00a0\u00a0 |   1\u00a0\u00a0 |    22651\u00a0\u00a0\u00a0 |<br \/>\n2\u00a0\u00a0\u00a0 |   1\u00a0\u00a0 |   -34706.\u00a0  |<br \/>\n<span style=\"color: orange\"># psql -p 5433 -d dbi -c update pgbench_tellers set filler = I am the Clone of pg1\"<\/span><br \/>\nUPDATE 10000<br \/>\n<span style=\"color: orange\"># psql -p 5434 -d dbi -c update pgbench_accounts set filler = I am the second Clone of pg1\"<\/span><br \/>\nUPDATE 10000<br \/>\n<span style=\"color: orange\"># psql -p 5434 -d dbi -c \"delete from pgbench_tellers where tid &gt; 100 and tid &lt; 9800\"<\/span><br \/>\nDELETE 9699<br \/>\nSource<br \/>\n------<br \/>\ntid \u00a0 | bid | tbalance | filler<br \/>\n------+-----+----------+--------<br \/>\n61 \u00a0\u00a0  | 7 \u00a0 | -27082 \u00a0  |<br \/>\n8892\u00a0  | 890 | 14471. \u00a0  |<br \/>\ncount<br \/>\n-------<br \/>\n10000<br \/>\nClone staging<br \/>\n-------------<br \/>\ntid   | bid | tbalance | filler<br \/>\n------+-----+----------+--------------------------------------------------------------------------------------<br \/>\n73\u00a0\u00a0\u00a0 | 8 | 25292. \u00a0 \u00a0  | I am the Clone of pg1<br \/>\n48 \u00a0\u00a0   | 5.| -34248 \u00a0 \u00a0   | I am the Clone of pg1<br \/>\ncount<br \/>\n-------<br \/>\n10000<br \/>\nClone test<br \/>\n----------<br \/>\ntid\u00a0  | bid | tbalance | filler<br \/>\n-----+-----+----------+--------------------------------------------------------------------------------------<br \/>\n73.\u00a0  | 8\u00a0\u00a0 | 25292. \u00a0   | I am the second Clone of pg1<br \/>\n48 \u00a0  | 5.\u00a0  | -34248 \u00a0  | I am the second Clone of pg1<br \/>\ncount<br \/>\n-------<br \/>\n301<\/code><br \/>\nSo, when tests are over, it&#8217;s easy to remove the clones but first, don&#8217;t forget to stop them and check that all subvolumes have been removed.<br \/>\n<code><span style=\"color: orange\"># pg_ctl -D \/pgdatas\/staging stop<\/span><br \/>\n<span style=\"color: orange\"># pg_ctl -D \/pgdatas\/test stop<\/span><br \/>\n<span style=\"color: orange\"># sudo btrfs subvolume delete staging<\/span><br \/>\nDelete subvolume (no-commit): '\/pgdatas\/staging'<br \/>\n<span style=\"color: orange\"># sudo btrfs subvolume delete test<\/span><br \/>\nDelete subvolume (no-commit): '\/pgdatas\/test'<br \/>\n<span style=\"color: orange\"># sudo btrfs subvolume list \/pgdatas<\/span><br \/>\nID 258 gen 6958 top level 5 path pg1<\/code><\/p>\n<h2>Conclusion<\/h2>\n<p>Instant cloning a PostgreSQL cluster with Btrfs is easy &amp; straight forward for developers (validation procedures), rapid testing and even PostgreSQL upgrade.<br \/>\nIt&#8217;s simple to setup, you don&#8217;t need a licence, there is no impact on performance and it does not affect the source cluster.<br \/>\nSo happy instant cloning.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What if you could clone a PostgreSQL database instantly without affecting the original source database, without impacting performance, without any external tool but using your linux Btrfs storage layer. This is what I will demonstrate in the following blogpost.<\/p>\n","protected":false},"author":28,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[229],"tags":[2122,1938,1856,77,309],"type_dbi":[],"class_list":["post-14736","post","type-post","status-publish","format-standard","hentry","category-database-administration-monitoring","tag-btrfs","tag-cloning","tag-pgbench","tag-postgresql","tag-suse"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.5) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Instant PostgreSQL Cloning with SUSE and Btrfs - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Instant PostgreSQL Cloning with SUSE and Btrfs\" \/>\n<meta property=\"og:description\" content=\"What if you could clone a PostgreSQL database instantly without affecting the original source database, without impacting performance, without any external tool but using your linux Btrfs storage layer. This is what I will demonstrate in the following blogpost.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-09-23T14:54:37+00:00\" \/>\n<meta name=\"author\" content=\"Open source Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Open source Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/instant-postgresql-cloning-with-suse-and-btrfs\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/instant-postgresql-cloning-with-suse-and-btrfs\\\/\"},\"author\":{\"name\":\"Open source Team\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/59554f0d99383431eb6ed427e338952b\"},\"headline\":\"Instant PostgreSQL Cloning with SUSE and Btrfs\",\"datePublished\":\"2020-09-23T14:54:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/instant-postgresql-cloning-with-suse-and-btrfs\\\/\"},\"wordCount\":634,\"commentCount\":0,\"keywords\":[\"Btrfs\",\"cloning\",\"pgBench\",\"PostgreSQL\",\"SuSE\"],\"articleSection\":[\"Database Administration &amp; Monitoring\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/instant-postgresql-cloning-with-suse-and-btrfs\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/instant-postgresql-cloning-with-suse-and-btrfs\\\/\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/instant-postgresql-cloning-with-suse-and-btrfs\\\/\",\"name\":\"Instant PostgreSQL Cloning with SUSE and Btrfs - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\"},\"datePublished\":\"2020-09-23T14:54:37+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/59554f0d99383431eb6ed427e338952b\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/instant-postgresql-cloning-with-suse-and-btrfs\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/instant-postgresql-cloning-with-suse-and-btrfs\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/instant-postgresql-cloning-with-suse-and-btrfs\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Instant PostgreSQL Cloning with SUSE and Btrfs\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/59554f0d99383431eb6ed427e338952b\",\"name\":\"Open source Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/eb4fb12e386e8c41fdef0733e8114594cf2653e4f55e9fa2161442b8eaf3f657?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/eb4fb12e386e8c41fdef0733e8114594cf2653e4f55e9fa2161442b8eaf3f657?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/eb4fb12e386e8c41fdef0733e8114594cf2653e4f55e9fa2161442b8eaf3f657?s=96&d=mm&r=g\",\"caption\":\"Open source Team\"},\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/author\\\/open-source-team\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Instant PostgreSQL Cloning with SUSE and Btrfs - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/","og_locale":"en_US","og_type":"article","og_title":"Instant PostgreSQL Cloning with SUSE and Btrfs","og_description":"What if you could clone a PostgreSQL database instantly without affecting the original source database, without impacting performance, without any external tool but using your linux Btrfs storage layer. This is what I will demonstrate in the following blogpost.","og_url":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/","og_site_name":"dbi Blog","article_published_time":"2020-09-23T14:54:37+00:00","author":"Open source Team","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Open source Team","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/"},"author":{"name":"Open source Team","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/59554f0d99383431eb6ed427e338952b"},"headline":"Instant PostgreSQL Cloning with SUSE and Btrfs","datePublished":"2020-09-23T14:54:37+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/"},"wordCount":634,"commentCount":0,"keywords":["Btrfs","cloning","pgBench","PostgreSQL","SuSE"],"articleSection":["Database Administration &amp; Monitoring"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/","url":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/","name":"Instant PostgreSQL Cloning with SUSE and Btrfs - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2020-09-23T14:54:37+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/59554f0d99383431eb6ed427e338952b"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/instant-postgresql-cloning-with-suse-and-btrfs\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Instant PostgreSQL Cloning with SUSE and Btrfs"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/59554f0d99383431eb6ed427e338952b","name":"Open source Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/eb4fb12e386e8c41fdef0733e8114594cf2653e4f55e9fa2161442b8eaf3f657?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/eb4fb12e386e8c41fdef0733e8114594cf2653e4f55e9fa2161442b8eaf3f657?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/eb4fb12e386e8c41fdef0733e8114594cf2653e4f55e9fa2161442b8eaf3f657?s=96&d=mm&r=g","caption":"Open source Team"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/open-source-team\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/14736","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/28"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=14736"}],"version-history":[{"count":0,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/14736\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=14736"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=14736"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=14736"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=14736"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}