{"id":329,"date":"2018-09-06T13:18:29","date_gmt":"2018-09-06T11:18:29","guid":{"rendered":"https:\/\/blog.kurschies.de\/?p=329"},"modified":"2019-10-15T14:45:25","modified_gmt":"2019-10-15T12:45:25","slug":"oracle-dataguard-in-5-minutes","status":"publish","type":"post","link":"https:\/\/blog.kurschies.de\/index.php\/2018\/09\/06\/oracle-dataguard-in-5-minutes\/","title":{"rendered":"Oracle Dataguard in 5 Minutes"},"content":{"rendered":"<p>ok, although I wrote that there are plenty of websites and blogs describing how to create a dataguard standby, I&#8217;m doing one on my own&#8230; specially because my colleague asked me to write them a manual, so I decided to do it here.<\/p>\n<p>In my example I&#8217;m using two Servers with Oracle 12.2 clusterware (Oracle restart) including an ASM instance and a 12.2 db home. On the first server &#8211; lets call it the primary node &#8211; I&#8217;ve also installed a non-CDB Database with the database create assistant (dbca). The name of the database is ORCL, the db_unique_name is ORCLRA (the db_unique_name is quite important for dataguard to distinguish the different sites)<\/p>\n<ul>\n<li>Prepare the source<\/li>\n<\/ul>\n<p>there are some mandatory things that must be checked or adjusted before we can start to create the standby&#8230; the database must be in archivelog mode (dataguard is a log shipping technology, so this is obvious) and we must enable force logging, so we can transport also the changes executed with &#8220;nologging&#8221;<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nSQL&gt; shutdown immediate;\r\nSQL&gt; startup mount;\r\nSQL&gt; alter database archivelog;\r\nSQL&gt; alter database force logging;\r\nSQL&gt; alter database open;\r\n<\/pre>\n<ul>\n<li>add standby redo logs<\/li>\n<\/ul>\n<p>for those who are asking what the hell standby redo logs are &#8211; here a short explanation: the primary database is transferring the redo information to the standby via sql.net&#8230; this means there must be an oracle instance receiving this information and store it somewhere. And because oracle wants to separate standby and redo information, there is a new log type called standby log. The easiest way is to create it on the primary site &#8211; when the primary becomes a standby, the standby logs are already there&#8230; and if the logs are present before duplicating the database, they will be created automatically during the copy \ud83d\ude09 So we are creating one more standby logs than we have redo logs &#8211; this is because we have one extra source that could copy data from the primary: there can be a stream from each redo log group and one directly from the log buffer. For further information you may want to watch <a href=\"https:\/\/community.oracle.com\/docs\/DOC-1007036\">this<\/a> site&#8230;<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nSQL&gt; select count(*) from v$log;\r\n  COUNT(*)\r\n----------\r\n         3\r\n\r\nSQL&gt; select distinct bytes from v$log;\r\n     BYTES\r\n----------\r\n 209715200\r\n\r\nSQL&gt; alter database add standby logfile group 11 size 209715200;\r\nSQL&gt; alter database add standby logfile group 12 size 209715200;\r\nSQL&gt; alter database add standby logfile group 13 size 209715200;\r\nSQL&gt; alter database add standby logfile group 14 size 209715200;\r\n<\/pre>\n<ul>\n<li>enable standby_file_management<\/li>\n<\/ul>\n<p>often forgotten, but in my opinion an important parameter. The default of this parameter is &#8220;manual&#8221;, which means when adding a datafile on the primary site, you have to do the same on the standby site. If you forget to do so, the replication will stop&#8230; and we are humans and humans do forget things sometimes. So just set the parameter to &#8220;auto&#8221; and oracle will take care of it.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nSQL&gt; alter system set STANDBY_FILE_MANAGEMENT=AUTO;\r\n<\/pre>\n<ul>\n<li>modify listener.ora<\/li>\n<\/ul>\n<p>OK, now we need to modify the listener.ora file &#8211; oracle dataguard need access to the database via sql.net under any circumstances, even when the database is down. To solve this problem, we have to add a static entry to the listener.ora&#8230;<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nvi $GRID_HOME\/network\/admin\/listener.ora\r\nLISTENER =\r\n  (DESCRIPTION_LIST =\r\n    (DESCRIPTION =\r\n      (ADDRESS = (PROTOCOL = TCP)(HOST = primary)(PORT = 1521))\r\n      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))\r\n    )\r\n  )\r\n\r\nENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=ON              # line added by Agent\r\nVALID_NODE_CHECKING_REGISTRATION_LISTENER=SUBNET        # line added by Agent\r\n\r\n# add static listener entry starts here:\r\nSID_LIST_LISTENER =\r\n  (SID_LIST =\r\n    (SID_DESC =\r\n      (SID_NAME = ORCL)\r\n      (GLOBAL_DBNAME=ORCLRA_DGMGRL)\r\n      (ORACLE_HOME = \/u00\/app\/oracle\/product\/12.2.0\/db_1)\r\n    )\r\n  )\r\n<\/pre>\n<p>the same must be done on the standby site, too &#8211; only change the &#8220;GLOBAL_DBNAME&#8221; to a proper value &#8211; the &#8220;_DGMGRL&#8221; extension is mandatory for oracle dataguard&#8230; regarding the db_unique_name: I usually use the db_name with the suffix RA (for &#8220;recovery site A&#8221;), RB, RC, etc&#8230; and finaly restart or reload the listener to enable the new configuration.<\/p>\n<ul>\n<li>init and password file<\/li>\n<\/ul>\n<p>now we are doing the last few steps of preparation&#8230; to start the standby database, we need an pfile&#8230; so we a just creating one from the primary:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nSQL&gt; create pfile='\/tmp\/initORCL.ora' from spfile;\r\n<\/pre>\n<p>to be able to logon as sys via sql.net, we need the password file on the standby site&#8230; so we just copy the file together with the pfile to the other server:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nBASH&gt; scp \/tmp\/init${ORACLE_SID}.ora standby:\/${ORACLE_HOME}\/dbs\/\r\nBASH&gt; scp ${ORACLE_HOME}\/dbs\/orapw${ORACLE_SID} standby:\/${ORACLE_HOME}\/dbs\/\r\n<\/pre>\n<p>And now just edit the pfile and replace all values containing the db_unique_name with the now value.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n# do on standby site!\r\nBASH&gt; sed -i 's\/ORCLRA\/ORCLRB\/g' ${ORACLE_HOME}\/dbs\/init${ORACLE_SID}.ora\r\n<\/pre>\n<p>to startup the instance, you have to create the audit file destination manually<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nBASH&gt; grep audit_file_dest ${ORACLE_HOME}\/dbs\/init${ORACLE_SID}.ora\r\nBASH&gt; mkdir -p \/u00\/app\/oracle\/admin\/ORCLRB\/adump\r\n<\/pre>\n<ul>\n<li>create spfile<\/li>\n<\/ul>\n<p>Oracle dataguard requires an spfile, so we have to create it&#8230;<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nBASH&gt; echo &quot;ORCL:\/u00\/app\/oracle\/product\/12.2.0\/db_1:N&quot; &gt;&gt; \/etc\/oratab\r\nBASH&gt; . oraenv &lt;&lt;&lt; ORCL\r\nSQL&gt; startup nomount;\r\nSQL&gt; create spfile='+DATA\/ORCLRB\/spfileORCL.ora' from pfile;\r\nSQL&gt; shutdown;\r\nBASH&gt; mv ${ORACLE_HOME}\/dbs\/init${ORACLE_SID}.ora ${ORACLE_HOME}\/dbs\/init${ORACLE_SID}.ora.bak\r\nBASH&gt; echo &quot;spfile='+DATA\/ORCLRB\/spfileORCL.ora'&amp;amp;amp;quot; ${ORACLE_HOME}\/dbs\/init${ORACLE_SID}.ora\r\nSQL&gt; startup nomount;\r\nSQL&gt; show parameter spfile\r\nNAME                                 TYPE        VALUE\r\n------------------------------------ ----------- -----------------------------------------------\r\nspfile                               string      +DATA\/ORCLRB\/spfileorcl.ora\r\n<\/pre>\n<ul>\n<li>final checks before copy<\/li>\n<\/ul>\n<p>ok, now we have got a primary database in archivelog mode with force logging enabled and a standby instance in nomount state with the same password file, using an spfile. Furthermore, both instances are accessable via sql.net&#8230; so lets check if it&#8217;s working!<br \/>\nthe easiest way is just to logon to the database via sqlplus:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nsqlplus sys\/oracle@primary:1521\/orclra_dgmgrl as sysdba\r\nsqlplus sys\/oracle@standby:1521\/orclrb_dgmgrl as sysdba\r\n<\/pre>\n<p>if both are working, we can continue, otherwise check the password file and listener entries again. Also checking the sqlnet.ora if ezconnect is allowed could be a good idea.<\/p>\n<ul>\n<li>duplicate<\/li>\n<\/ul>\n<p>the next step is the easiest one, although it might take a while, depending on the size of your database&#8230; we do an rman duplicate:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nrman target sys\/oracle@primary:1521\/orclra_dgmgrl auxiliary sys\/oracle@standby:1521\/orclrb_dgmgrl\r\nRMAN&gt; duplicate target database for standby from active database;\r\n<\/pre>\n<p>when done you should also add the database to the clusterware, so the database will be started automatically after a reboot etc<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nBASH&gt; srvctl add database -db ORCLRB -oraclehome \/u00\/app\/oracle\/product\/12.2.0\/db_1 -role physical_standby -instance ORCL -startoption MOUNT\r\n<\/pre>\n<ul>\n<li>enable log shipping<\/li>\n<\/ul>\n<p>ok, and now the last step: configure the dataguard broker. First we have to enable the broker on both sites&#8230;<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nSQL&gt; alter system set dg_broker_start=true;\r\n<\/pre>\n<p>and now (maybe wait a few seconds until the broker process is really up) we have to configure it&#8230; if you once understand the syntax, it&#8217;s really a no brainer.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nBASH&gt; dgmgrl \/\r\nDGMGRL&gt; create configuration 'DG' as primary database is 'ORCLRA' connect identifier is '192.168.56.21:1521\/ORCLRA_DGMGRL';\r\nDGMGRL&gt; add database 'ORCLRB' as connect identifier is '192.168.56.22:1521\/ORCLRB_DGMGRL';\r\nDGMGRL&gt; enable configuration;\r\n<\/pre>\n<p>thats it&#8230; you can check your success via the broker (check the lines &#8220;Transport LAG&#8221; and &#8220;Apply Lag&#8221;) or by checking the alert.log of the standby database (just check if the media recovery process is waiting for an archivelog in transit)&#8230; suspicious people may do both \ud83d\ude09<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nDGMGRL&gt; show database 'ORCLRB'\r\nDatabase - ORCLRB\r\n\r\n  Role:               PHYSICAL STANDBY\r\n  Intended State:     APPLY-ON\r\n  Transport Lag:      0 seconds (computed 0 seconds ago)\r\n  Apply Lag:          0 seconds (computed 0 seconds ago)\r\n  Average Apply Rate: 4.00 KByte\/s\r\n  Real Time Query:    OFF\r\n  Instance(s):\r\n    ORCL\r\n\r\nBASH&gt; tail \/u00\/app\/oracle\/diag\/rdbms\/orclrb\/ORCL\/trace\/alert_ORCL.log\r\nMedia Recovery Waiting for thread 1 sequence 15 (in transit)\r\n2018-09-06T12:59:27.551097+02:00\r\nRecovery of Online Redo Log: Thread 1 Group 12 Seq 15 Reading mem 0\r\n  Mem# 0: +DATA\/ORCLRB\/ONLINELOG\/group_12.274.986057281\r\n  Mem# 1: +DATA\/ORCLRB\/ONLINELOG\/group_12.275.986057283\r\n<\/pre>\n<p>just tell me if I have missed something&#8230;<\/p>\n<p>so far<br \/>\nBenjamin<\/p>\n","protected":false},"excerpt":{"rendered":"<p>ok, although I wrote that there are plenty of websites and blogs describing how to create a dataguard standby, I&#8217;m doing one on my own&#8230; specially because my colleague asked me to write them a manual, so I decided to &hellip; <a href=\"https:\/\/blog.kurschies.de\/index.php\/2018\/09\/06\/oracle-dataguard-in-5-minutes\/\">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":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[14,7],"class_list":["post-329","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-dataguard","tag-oracle"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8m6YC-5j","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/posts\/329","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/comments?post=329"}],"version-history":[{"count":25,"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/posts\/329\/revisions"}],"predecessor-version":[{"id":383,"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/posts\/329\/revisions\/383"}],"wp:attachment":[{"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/media?parent=329"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/categories?post=329"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.kurschies.de\/index.php\/wp-json\/wp\/v2\/tags?post=329"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}