{"id":1657,"date":"2017-10-30T18:46:08","date_gmt":"2017-10-30T16:46:08","guid":{"rendered":"http:\/\/www.ludovicocaldara.net\/dba\/?p=1657"},"modified":"2020-08-18T16:13:15","modified_gmt":"2020-08-18T14:13:15","slug":"dbvrep-grid-infrastructure","status":"publish","type":"post","link":"https:\/\/www.ludovicocaldara.net\/dba\/dbvrep-grid-infrastructure\/","title":{"rendered":"My own Dbvisit Replicate integration with Grid Infrastructure"},"content":{"rendered":"<p>I am helping my customer for a PoC of Dbvisit Replicate as a logical replication tool. I will not discuss (at least, not in this post) about the capabilities of the tool itself, its configuration or the caveats that you should beware of when you do logical replication. Instead, I will concentrate on how we will likely integrate it in the current environment.<\/p>\n<p>My role in this PoC is to make sure that the tool will be easy to operate from the operational point of view, and the database operations, here, are supported by Oracle Grid Infrastructure and cold failover clusters.<\/p>\n<p><strong>Note<\/strong>: there are official Dbvisit\u00a0 <a href=\"https:\/\/dbvisit.atlassian.net\/wiki\/spaces\/ugd8\/pages\/60784832\/RAC+and+HA+Best+Practices\">online resources<\/a>\u00a0 about how to configure Dbvisit Replicate in a cluster. I aim to <strong>complement<\/strong> those informations, not copy them.<\/p>\n<p><strong>Quick overview<\/strong><\/p>\n<p>If you know Dbvisit replicate, skip this paragraph.<\/p>\n<p>There are three main components of Dbvisit Replicate: The FETCHER, the MINE and the APPLY processes. The FETCHER gets the redo stream from the source and sends it to the MINE process. The MINE process elaborates the redo streams and converts it in proprietary transaction log files (named plog). The APPLY process gets the plog files and applies the transactions on the destination database.<\/p>\n<p>From an architectural point of view, MINE and APPLY do not need to run close to the databases that are part of the configuration. The FETCHER process, by opposite, needs to be local to the source database online log files (and archived logs).<\/p>\n<p>Because the MINE process is the most resource intensive, it is not convenient to run it where the databases reside, as it might consume precious CPU resources that are licensed for Oracle Database. So, first step in this PoC: the <strong>FETCHER processes will run on the cluster<\/strong>, while <strong>MINE and APPLY will run on a dedicated Virtual Machine<\/strong>.<\/p>\n<p><a href=\"https:\/\/www.ludovicocaldara.net\/dba\/wp-content\/uploads\/2017\/10\/dbvisit_gi_overview.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1658\" src=\"https:\/\/www.ludovicocaldara.net\/dba\/wp-content\/uploads\/2017\/10\/dbvisit_gi_overview.png\" alt=\"dbvisit_gi_overview\" width=\"719\" height=\"580\" srcset=\"https:\/\/www.ludovicocaldara.net\/dba\/wp-content\/uploads\/2017\/10\/dbvisit_gi_overview.png 719w, https:\/\/www.ludovicocaldara.net\/dba\/wp-content\/uploads\/2017\/10\/dbvisit_gi_overview-300x242.png 300w, https:\/\/www.ludovicocaldara.net\/dba\/wp-content\/uploads\/2017\/10\/dbvisit_gi_overview-372x300.png 372w\" sizes=\"auto, (max-width: 719px) 100vw, 719px\" \/><\/a><\/p>\n<p><strong>Clustering considerations<\/strong><\/p>\n<ul>\n<li>the FETCHER does NOT need to run on the server of the source database: having access to the online logs through the ASM instance is enough<\/li>\n<li>to avoid SPoF, the fetcher should be a cluster resource that can relocate without problems<\/li>\n<li>to simplify the configuration, the FETCHER configuration and the Dbvisit binaries should be on a shared filesystem (the FETCHER does not persist any data, just the logs)<\/li>\n<li>the destination database might be literally anywhere: the APPLY connects via SQL*Net, so a correct name resolution and routing to the destination database are enough<\/li>\n<\/ul>\n<p>so the implementation steps are:<\/p>\n<ol>\n<li>create a shared filesystem<\/li>\n<li>install dbvisit in the shared filesystem<\/li>\n<li>create the Dbvisit Replicate configuration on the dedicated VM<\/li>\n<li>copy the configuration files on the cluster<\/li>\n<li>prepare an action script<\/li>\n<li>configure the resource<\/li>\n<li>test!<\/li>\n<\/ol>\n<p><strong>Convention over configuration: the importance of a strong naming convention<\/strong><\/p>\n<p>Before starting the implementation, I decided to put all the caveats related to the FETCHER\u00a0 resource relocation on paper:<\/p>\n<ul>\n<li>Where will the configuration files reside? Dbvisit has an important variable: the<strong> Configuration Name<\/strong>. All the operations are done by passing a configuration file named <strong>\/{PATH}\/{CONFIG_NAME}\/{CONFIG_NAME}-{PROCESS_TYPE}.ddc<\/strong> to the dbvrep binary. So, I decided to put ALL the configuration directories under the same path: given the Configuration Name, I will always be able to get the configuration file path.<\/li>\n<li>How will the configuration files relocate from one node to the other? Easy here: they won&#8217;t. I will use an ACFS filesystem<\/li>\n<li>How can I link the cluster resource with its configuration name? Easy again: I call my resources dbvrep.CONFIGNAME.PROCESS_TYPE. e.g. <strong>dbvrep.FROM_A_TO_B.fetcher<\/strong><\/li>\n<li>How will I manage the need to use a new version of dbvisit in the future? Old and new versions must coexist: Instead of using external configuration files, I will just use a custom resource attribute named DBVREP_HOME inside my resource type definition. (see later)<\/li>\n<li>What port number should I use? Of course, many fetchers started on different servers should not have conflicts. This is something that might be either planned or made dynamic. I will opt for the first one. But instead of getting the port number inside the Dbvisit configuration, I will use a custom resource attribute: DBVREP_PORT.<\/li>\n<\/ul>\n<p><strong>Considerations on the FETCHER listen address<\/strong><\/p>\n<p>This requires a dedicated paragraph. The <a href=\"https:\/\/dbvisit.atlassian.net\/wiki\/spaces\/ugd8\/pages\/60784832\/RAC+and+HA+Best+Practices\">Dbvisit documentation<\/a> suggest to\u00a0 create a VIP, bind on the VIP address and create a dependency between the FETCHER resource and the VIP. Here is where my configuration will differ.<\/p>\n<p>Having a separate VIP per FETCHER resource might, potentially, lead to dozens of VIPs in the cluster. Everything will depend on the success of the PoC and on how many internal clients will decide to ask for such implementation. Many VIPs == many interactions with network admins for address reservation, DNS configurations, etc. Long story short, it might slow down the creation and maintenance of new configurations.<\/p>\n<p>Instead, each FETCHER will listen to the local server address, and the action script will take care of:<\/p>\n<ul>\n<li>getting the current host name<\/li>\n<li>getting the current ASM instance<\/li>\n<li>changing the settings of the specific Dbvisit Replicate configuration (ASM instance and FETCHER listen address)<\/li>\n<li>starting the FETCHER<\/li>\n<\/ul>\n<p><strong>Implementation<\/strong><\/p>\n<p>Now that all the caveats and steps are clear, I can show how I implemented it:<\/p>\n<p>Create a shared filesystem<\/p>\n<pre class=\"lang:sh decode:true \">asmcmd volcreate -G ACFS -s 10G dbvisit --column 1\r\n\/sbin\/mkfs -t acfs \/dev\/asm\/dbvisit-293\r\nsudo \/u01\/app\/grid\/product\/12.1.0.2\/grid\/bin\/srvctl add filesystem -d \/dev\/asm\/dbvisit-293 -m \/u02\/data\/oracle\/dbvisit -u oracle -fstype ACFS -autostart ALWAYS\r\nsrvctl start filesystem -d \/dev\/asm\/dbvisit-293<\/pre>\n<p>Install dbvisit in the shared filesystem<\/p>\n<pre class=\"lang:plsql decode:true\">out of scope!<\/pre>\n<p>Create the Dbvisit Replicate configuration on the dedicated VM<\/p>\n<pre class=\"lang:plsql decode:true\">out of scope!<\/pre>\n<p>Copy the configuration files from the Dbvisit VM to the cluster<\/p>\n<pre class=\"lang:plsql decode:true\">scp \/u02\/data\/oracle\/dbvisit\/FROM_A_TO_B\/FROM_A_TO_B-FETCHER.ddc \\ \r\n cluster-scan:\/u02\/data\/oracle\/dbvisit\/FROM_A_TO_B<\/pre>\n<p>Prepare an action script<\/p>\n<pre class=\"lang:sh decode:true\">$ cat dbvrep.sh\r\n#!\/bin\/ksh\r\n########################################\r\n# Name   : dbvrep.sh\r\n# Author : Ludovico Caldara, Trivadis AG\r\n\r\n# the DBVISIT FETCHER process needs to know 2 attributes: DBVREP_HOME and DBVREP_PORT.\r\n# If you want to call the action script directly set:\r\n# _CRS_NAME=&lt;resource name in format dbvrep.CONFIGNAME.fetcher&gt;\r\n# _CRS_DBVREP_HOME=&lt;dbvrep installation path&gt;\r\n# _CRS_DBVREP_PORT=&lt;listening port&gt;\r\n\r\nDBVREP_RES_NAME=${_CRS_NAME}\r\nDBVREP_CONFIG_NAME=`echo $DBVREP_RES_NAME | awk -F. '{print $2}'`\r\n\r\n# MINE, FETCHER or APPLY?\r\nDBVREP_PROCESS_TYPE=`echo $DBVREP_RES_NAME | awk -F. '{print toupper($3)}'`\r\n\r\nDBVREP_HOME=${_CRS_DBVREP_HOME}\r\nDBVREP=${DBVREP_HOME}\/dbvrep\r\nDBVREP_PORT=${_CRS_DBVREP_PORT}\r\nDBVREP_CONFIG_PATH=\/u02\/data\/oracle\/dbvisit\r\n\r\nDBVREP_CONFIG_FILE=${DBVREP_CONFIG_PATH}\/${DBVREP_CONFIG_NAME}\/${DBVREP_CONFIG_NAME}-${DBVREP_PROCESS_TYPE}.ddc\r\n\r\nfunction F_verify_dbvrep_up {\r\n        ps -eaf | grep \"[d]bvrep ${DBVREP_PROCESS_TYPE} $DBVREP_CONFIG_NAME\" &gt; \/dev\/null\r\n        if [ $? -eq 0 ] ; then\r\n                echo \"OK\"\r\n        else\r\n                echo \"KO\"\r\n                exit 1\r\n        fi\r\n}\r\n\r\nACTION=\"${1}\"\r\ncase \"$ACTION\" in\r\n\r\n        'start')\r\n        LOCAL_ASM=\"+\"`ps -eaf | grep [a]sm_pmon | awk -F+ '{print $NF}'`;\r\n\r\n        if [ \"${DBVREP_PROCESS_TYPE}\" == \"FETCHER\" ] ; then\r\n                $DBVREP --daemon --ddcfile ${DBVREP_CONFIG_FILE} --silent &lt;&lt;EOF\r\nset FETCHER.FETCHER_REMOTE_INTERFACE=${HOSTNAME}:${DBVREP_PORT}\r\nset FETCHER.FETCHER_LISTEN_INTERFACE=${HOSTNAME}:${DBVREP_PORT}\r\nset FETCHER.MINE_ASM=${LOCAL_ASM}\r\nstart FETCHER\r\nEOF\r\n        fi\r\n;;\r\n\r\n        'stop')\r\n        $DBVREP --daemon --ddcfile ${DBVREP_CONFIG_FILE} shutdown ${DBVREP_PROCESS_TYPE}\r\n\r\n;;\r\n\r\n        'check')\r\n        F_verify_dbvrep_up\r\n;;\r\n\r\n        'clean')\r\n        sleep 1\r\n        exit 0\r\n;;\r\n\r\n        *)\r\nusage\r\n;;\r\n\r\nesac<\/pre>\n<p>Configure the resource<\/p>\n<pre class=\"lang:plsql decode:true\">$ cat dbvrep.type\r\nATTRIBUTE=ACTION_SCRIPT\r\nDEFAULT_VALUE=\/path_to_action_script\/dbvrep.ksh\r\nTYPE=STRING\r\nFLAGS=CONFIG\r\n\r\nATTRIBUTE=SCRIPT_TIMEOUT\r\nDEFAULT_VALUE=120\r\nTYPE=INT\r\nFLAGS=CONFIG\r\n\r\nATTRIBUTE=DBVREP_PORT\r\nDEFAULT_VALUE=\r\nTYPE=INT\r\nFLAGS=CONFIG\r\n\r\nATTRIBUTE=DBVREP_HOME\r\nDEFAULT_VALUE=\/u02\/data\/oracle\/dbvisit\/replicate\r\nTYPE=STRING\r\nFLAGS=CONFIG\r\n\r\nATTRIBUTE=SERVER_POOLS\r\nDEFAULT_VALUE=*\r\nTYPE=STRING\r\nFLAGS=CONFIG|HOTMOD\r\n\r\nATTRIBUTE=START_DEPENDENCIES\r\nDEFAULT_VALUE=hard() weak(type:ora.listener.type,global:type:ora.scan_listener.type) pullup()\r\nTYPE=STRING\r\nFLAGS=CONFIG\r\n\r\nATTRIBUTE=STOP_DEPENDENCIES\r\nDEFAULT_VALUE=hard()\r\nTYPE=STRING\r\nFLAGS=CONFIG\r\n\r\n\r\nATTRIBUTE=RESTART_ATTEMPTS\r\nDEFAULT_VALUE=2\r\nTYPE=INT\r\nFLAGS=CONFIG\r\n\r\nATTRIBUTE=CHECK_INTERVAL\r\nDEFAULT_VALUE=60\r\nTYPE=INT\r\nFLAGS=CONFIG\r\n\r\nATTRIBUTE=FAILURE_THRESHOLD\r\nDEFAULT_VALUE=2\r\nTYPE=INT\r\nFLAGS=CONFIG\r\n\r\nATTRIBUTE=UPTIME_THRESHOLD\r\nDEFAULT_VALUE=8h\r\nTYPE=STRING\r\nFLAGS=CONFIG\r\n\r\nATTRIBUTE=FAILURE_INTERVAL\r\nDEFAULT_VALUE=3600\r\nTYPE=INT\r\nFLAGS=CONFIG\r\n\r\n$ crsctl add type dbvrep.type -basetype cluster_resource -file dbvrep.type\r\n$ crsctl add resource dbvrep.FROM_A_TO_B.fetcher -type dbvrep.type \\\r\n  -attr \"START_DEPENDENCIES=hard(db.source) pullup:always(db.source),STOP_DEPENDENCIES=hard(db.source),DBVREP_PORT=7901\"\r\n<\/pre>\n<p>Test!<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:plsql decode:true \">$ crsctl start res dbvrep.FROM_A_TO_B.fetcher\r\nCRS-2672: Attempting to start 'dbvrep.FROM_A_TO_B.fetcher' on 'server1'\r\nCRS-2676: Start of 'dbvrep.FROM_A_TO_B.fetcher' on 'server1' succeeded\r\n\r\n..in the logs..\r\n2017-10-30 15:24:34.992478 :    AGFW:1127589632: {1:30181:30166} Agent received the message: RESOURCE_START[dbvrep.FROM_A_TO_B.fetcher 1 1] ID 4098:5175912\r\n2017-10-30 15:24:34.992512 :    AGFW:1127589632: {1:30181:30166} Preparing START command for: dbvrep.FROM_A_TO_B.fetcher 1 1\r\n2017-10-30 15:24:34.992521 :    AGFW:1127589632: {1:30181:30166} dbvrep.FROM_A_TO_B.fetcher 1 1 state changed from: OFFLINE to: STARTING\r\n2017-10-30 15:24:34.993195 :CLSDYNAM:1106577152: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30166} [start] Executing action script: dbvrep.ksh[start]\r\n2017-10-30 15:24:41.254703 :CLSDYNAM:1106577152: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30166} [start] Variable FETCHER_REMOTE_INTERFACE set to server1:7901 for process\r\n2017-10-30 15:24:41.254726 :CLSDYNAM:1106577152: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30166} [start] FETCHER.\r\n2017-10-30 15:24:41.354916 :CLSDYNAM:1106577152: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30166} [start] Variable FETCHER_LISTEN_INTERFACE set to server1:7901 for process\r\n2017-10-30 15:24:41.354935 :CLSDYNAM:1106577152: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30166} [start] FETCHER.\r\n2017-10-30 15:24:41.405052 :CLSDYNAM:1106577152: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30166} [start] Variable MINE_ASM set to +ASM1 for process FETCHER.\r\n2017-10-30 15:24:41.605423 :CLSDYNAM:1106577152: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30166} [start] Starting process FETCHER...started\r\n2017-10-30 15:24:41.655660 :    AGFW:1106577152: {1:30181:30166} Command: start for resource: dbvrep.FROM_A_TO_B.fetcher 1 1 completed with status: SUCCESS\r\n2017-10-30 15:24:41.656100 :CLSDYNAM:1081362176: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30166} [check] Executing action script: dbvrep.ksh[check]\r\n2017-10-30 15:24:41.658242 :    AGFW:1127589632: {1:30181:30166} Agent sending reply for: RESOURCE_START[dbvrep.FROM_A_TO_B.fetcher 1 1] ID 4098:5175912\r\n2017-10-30 15:24:41.908256 :CLSDYNAM:1081362176: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30166} [check] OK\r\n2017-10-30 15:24:41.908440 :    AGFW:1127589632: {1:30181:30166} dbvrep.FROM_A_TO_B.fetcher 1 1 state changed from: STARTING to: ONLINE\r\n2017-10-30 15:24:41.908486 :    AGFW:1127589632: {1:30181:30166} Started implicit monitor for [dbvrep.FROM_A_TO_B.fetcher 1 1] interval=60000 delay=60000\r\n2017-10-30 15:24:41.908696 :    AGFW:1127589632: {1:30181:30166} Agent sending last reply for: RESOURCE_START[dbvrep.FROM_A_TO_B.fetcher 1 1] ID 4098:5175912\r\n\r\n\r\n$ crsctl stop res dbvrep.FROM_A_TO_B.fetcher\r\nCRS-2673: Attempting to stop 'dbvrep.FROM_A_TO_B.fetcher' on 'server1'\r\nCRS-2677: Stop of 'dbvrep.FROM_A_TO_B.fetcher' on 'server1' succeeded\r\n\r\n..in the logs..\r\n2017-10-30 15:22:14.891730 :    AGFW:1127589632: {1:30181:30156} Agent received the message: RESOURCE_STOP[dbvrep.FROM_A_TO_B.fetcher 1 1] ID 4099:5175818\r\n2017-10-30 15:22:14.891762 :    AGFW:1127589632: {1:30181:30156} Preparing STOP command for: dbvrep.FROM_A_TO_B.fetcher 1 1\r\n2017-10-30 15:22:14.891772 :    AGFW:1127589632: {1:30181:30156} dbvrep.FROM_A_TO_B.fetcher 1 1 state changed from: ONLINE to: STOPPING\r\n2017-10-30 15:22:14.892400 :CLSDYNAM:1091868416: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [stop] Executing action script: dbvrep.ksh[stop]\r\n2017-10-30 15:22:20.957375 :CLSDYNAM:1091868416: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [stop] DDC loaded from database (458 variables).\r\n2017-10-30 15:22:21.007939 :CLSDYNAM:1091868416: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [stop] Dbvisit Replicate version 2.9.04\r\n2017-10-30 15:22:21.007963 :CLSDYNAM:1091868416: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [stop] Copyright (C) Dbvisit Software Limited. All rights reserved.\r\n2017-10-30 15:22:21.007976 :CLSDYNAM:1091868416: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [stop] DDC file\r\n2017-10-30 15:22:21.007994 :CLSDYNAM:1091868416: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [stop] \/u02\/data\/oracle\/dbvisit\/FROM_A_TO_B\/FROM_A_TO_B\r\n2017-10-30 15:22:21.008005 :CLSDYNAM:1091868416: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [stop] -FETCHER.ddc loaded.\r\n2017-10-30 15:22:21.108340 :CLSDYNAM:1091868416: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [stop] Dbvisit Replicate FETCHER process shutting down.\r\n2017-10-30 15:22:21.108361 :CLSDYNAM:1091868416: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [stop] OK-0: Completed successfully.\r\n2017-10-30 15:22:45.747531 :    AGFW:1091868416: {1:30181:30156} Command: stop for resource: dbvrep.FROM_A_TO_B.fetcher 1 1 completed with status: SUCCESS\r\n2017-10-30 15:22:45.747898 :    AGFW:1127589632: {1:30181:30156} Agent sending reply for: RESOURCE_STOP[dbvrep.FROM_A_TO_B.fetcher 1 1] ID 4099:5175818\r\n2017-10-30 15:22:45.747902 :CLSDYNAM:1123387136: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [check] Executing action script: dbvrep.ksh[check]\r\n2017-10-30 15:22:45.949702 :CLSDYNAM:1123387136: [dbvrep.FROM_A_TO_B.fetcher]{1:30181:30156} [check] KO\r\n2017-10-30 15:22:45.949913 :    AGFW:1127589632: {1:30181:30156} dbvrep.FROM_A_TO_B.fetcher 1 1 state changed from: STOPPING to: OFFLINE\r\n2017-10-30 15:22:45.950014 :    AGFW:1127589632: {1:30181:30156} Agent sending last reply for: RESOURCE_STOP[dbvrep.dbvrep.FROM_A_TO_B.fetcher 1 1] ID 4098:5175818<\/pre>\n<p>Also the relocation worked as expected: when the settings are modified through:<\/p>\n<pre class=\"lang:sh decode:true \">set FETCHER.FETCHER_REMOTE_INTERFACE=${HOSTNAME}:${DBVREP_PORT}\r\nset FETCHER.FETCHER_LISTEN_INTERFACE=${HOSTNAME}:${DBVREP_PORT}\r\nset FETCHER.MINE_ASM=${LOCAL_ASM}<\/pre>\n<p>The MINE process get the change dynamically, so no need to restart it.<\/p>\n<p><strong>Last consideration<\/strong><\/p>\n<p>Adding a hard dependency between the DB and the FETCHER will require to stop the DB with the force option or to always stop the fetcher before the database. Also, the start of the DB will pullup the FETCHER (pullup:always) and the opposite as well. We will consider furtherly if we will use this dependency or if we will manage it differently (e.g. through the action script).<\/p>\n<p>The\u00a0hard dependency declared without the <strong>global <\/strong>keyword, will always start the fetcher on the server where the database runs. This is not required, but it might be nice to see the fetcher on the same node. Again, a consideration that we will discuss furtherly.<\/p>\n<p>HTH<\/p>\n<p>&#8212;<\/p>\n<p>Ludovico<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I am helping my customer for a PoC of Dbvisit Replicate as a logical replication tool. I will not discuss (at least, not in this post) about the capabilities of the tool itself, its configuration or the caveats that you &hellip; <a href=\"https:\/\/www.ludovicocaldara.net\/dba\/dbvrep-grid-infrastructure\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[326,3,330,149,132],"tags":[],"class_list":["post-1657","post","type-post","status-publish","format-standard","hentry","category-oracle","category-oracledb","category-oracle-inst-upg","category-oracle-rac","category-triblog"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/posts\/1657","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/comments?post=1657"}],"version-history":[{"count":3,"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/posts\/1657\/revisions"}],"predecessor-version":[{"id":1661,"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/posts\/1657\/revisions\/1661"}],"wp:attachment":[{"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/media?parent=1657"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/categories?post=1657"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ludovicocaldara.net\/dba\/wp-json\/wp\/v2\/tags?post=1657"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}