Search

OakieTags

Who's online

There are currently 0 users and 41 guests online.

Recent comments

Affiliations

Oakies Blog Aggregator

Some new Oracle Database 12c Articles

I’ve recently put some new Oracle 12c articles on the website.

The privilege usage stuff is really cool. Normally, trying to figure out what you can remove from a user is always a complete pain in the ass. Some of the databases I’m currently working with have used GRANT like it’s going out of fashion. Trying to identify what is really necessary is a tough job. Features like this are going to be hard to wait for…

Cheers

Tim…

 


Some new Oracle Database 12c Articles was first posted on April 22, 2014 at 7:18 pm.
©2012 "The ORACLE-BASE Blog". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement.

RAC 12c enhancements: adding an additional SCAN-part 1

Based on customer request Oracle has added the functionality to add a second SCAN, completely independent of the SCAN defined/created during the cluster creation. Why would you want to use this feature? A few reasons that spring to mind are:

  • Consolidation: customers insist on using a different network
  • Separate network for Data Guard traffic

To demonstrate the concept I am going to show you in this blog post how I

  1. Add a new network resource
  2. Create new VIPs
  3. Add a new SCAN
  4. Add a new SCAN listener

It actually sounds more complex than it is, but I have a feeling I need to split this article in multiple parts as it’s far too long.

The lab setup

When you install RAC 11.2 and 12.1 you are prompted to specify a Single Client Access Name, or SCAN. This SCAN is usually defined in the corporate DNS server and resolves to 3 IP addresses. This allows for an easy way to implement client-side load balancing. The SCAN is explained in more detail in Pro Oracle Database 11g RAC on Linux for 11.2 and on OTN for 11.2 and 12.1. To spice the whole configuration up a little bit I decided to use RAC One Node on the clusters I am using for this demonstration.

I created 2 12.1.0.1.2 clusters for this Data Guard test. Hosts ron12cprinode1 and ron12cprinode2 form the primary cluster, ron12csbynode1 and ron12csbynode2 will form the standby cluster. The RAC One Node database is named RON:

[oracle@ron12cprinode1 ~]$ srvctl config database -db ron
Database unique name: ron
Database name: ron
Oracle home: /u01/app/oracle/product/12.1.0.1/dbhome_1
Oracle user: oracle
Spfile: +DATA/ron/spfilepri.ora
Password file: +DATA/ron/orapwpri
Domain:
Start options: open
Stop options: immediate
Database role: PRIMARY
Management policy: AUTOMATIC
Server pools: ron
Database instances:
Disk Groups: RECO
Mount point paths:
Services: ron12c
Type: RACOneNode
Online relocation timeout: 30
Instance name prefix: pri
Candidate servers: ron12cprinode1,ron12cprinode2
Database is administrator managed
[oracle@ron12cprinode1 ~]$

To make things even more interesting I defined my ORACLE_SID prefix on the primary to be “pri” and “sby” on the standby.

[oracle@ron12cprinode1 ~]$ ps -ef | grep smon
oracle    2553     1  0 Feb06 ?        00:00:09 asm_smon_+ASM1
oracle   15660 15578  0 05:05 pts/3    00:00:00 grep smon
oracle   28241     1  0 Feb07 ?        00:00:18 ora_smon_pri_1
[oracle@ron12cprinode1 ~]$

A quick check with gpnptool reveals the network usage before the addition of the second SCAN:


 
  
  
 

There is the default network, (“netnum 1″) that is created on the network defined as “public” during the installation. I have another spare network port (eth2) reserved for the new network and Data Guard traffic. Currently network 1 is the only one available.

[root@ron12cprinode1 ~]# srvctl config network
Network 1 exists
Subnet IPv4: 192.168.100.0/255.255.255.0/eth0, static
Subnet IPv6:

As you can see RAC 12c now supports IPv6. I have another network available that I want to make available for Data Guard traffic. For this purpose I added all nodes into DNS. I am a bit old-fashioned when it comes to DNS, I am still using bind most of the time. Here is an excerpt of my reverse name resolution file:

; hosts - primary cluster
50	PTR	ron12cprinode1.dg.example.com.
51	PTR	ron12cprinode1-vip.example.com.
52	PTR	ron12cprinode2.dg.example.com.
53	PTR	ron12cprinode2-vip.dg.example.com.
; Data Guard SCAN - primary cluster
54	PTR	ron12cpri-scan.dg.example.com.
55	PTR	ron12cpri-scan.dg.example.com.
56	PTR	ron12cpri-scan.dg.example.com.

; hosts - standby cluster
57	PTR	ron12csbynode1.dg.example.com.
58	PTR	ron12csbynode1-vip.dg.example.com.
59	PTR	ron12csbynode2.dg.example.com.
60	PTR	ron12csbynode2-vip.dg.example.com.
; Data Guard SCAN - standby cluster
61	PTR	ron12csby-scan.dg.example.com.
62	PTR	ron12csby-scan.dg.example.com.
63	PTR	ron12csby-scan.dg.example.com.

The domain is *.dg.example.com, the primary database client traffic will be routed through *.example.com.

Adding the new network

The first step to be performed is to make Clusterware aware of the second network. I am doing this on both sides of the cluster. Notice that the primary nodes are called *pri* whereas the standby cluster is called *sby*

[root@ron12cprinode1 ~]# srvctl add network -netnum 2 -subnet 192.168.102.0/255.255.255.0/eth2 -nettype static -verbose
Successfully added Network.

[root@ron12csbynode1 ~]# srvctl add network -netnum 2 -subnet 192.168.102.0/255.255.255.0/eth2 -nettype static -verbose
Successfully added Network.

So this worked, now I have 2 networks:

[root@ron12cprinode1 ~]# srvctl config network
Network 1 exists
Subnet IPv4: 192.168.100.0/255.255.255.0/eth0, static
Subnet IPv6:
Network 2 exists
Subnet IPv4: 192.168.102.0/255.255.255.0/eth2, static
Subnet IPv6:
[root@ron12cprinode1 ~]#

In the next step I have to add VIPs for the new nodes on the *.dg.example.com subnet. The VIPs must be added on all cluster nodes, 4 in my case.

[oracle@ron12cprinode2 ~]$ srvctl add vip -h

Adds a VIP to the Oracle Clusterware.

Usage: srvctl add vip -node  -netnum  -address {|}/[/if1[|if2...]] [-skip] [-verbose]
    -node               Node name
    -address                       /[/if1[|if2...]] VIP address specification for node applications
    -netnum               Network number (default number is 1)
    -skip                          Skip reachability check of VIP address
    -verbose                       Verbose output
    -help                          Print usage
[oracle@ron12cprinode2 ~]$

So I did this on each node in my cluster

[root@ron12cprinode1 ~]# srvctl add vip -node ron12cprinode1 -netnum 2 -address 192.168.102.51/255.255.255.0/eth2 -verbose
Network exists: 2/192.168.102.0/255.255.255.0/eth2, type static
Successfully added VIP.
[root@ron12cprinode2 ~]# srvctl add vip -node ron12cprinode2 -netnum 2 -address 192.168.102.53/255.255.255.0/eth2 -verbose
Network exists: 2/192.168.102.0/255.255.255.0/eth2, type static
Successfully added VIP.

[root@ron12csbynode1 ~]# srvctl add vip -node ron12csbynode1 -netnum 2 -address 192.168.102.58/255.255.255.0/eth2 -verbose
Network exists: 2/192.168.102.0/255.255.255.0/eth2, type static
Successfully added VIP.
[root@ron12csbynode2 ~]# srvctl add vip -node ron12csbynode2 -netnum 2 -address 192.168.102.60/255.255.255.0/eth2 -verbose
Network exists: 2/192.168.102.0/255.255.255.0/eth2, type static
Successfully added VIP.

And I need to start the VIPs. They have some funny names as you can see in crsctl status resource (the names can’t be defined, see output of srvctl add scan -h above)

[root@ron12cprinode1 ~]# srvctl status vip -vip ron12cprinode1_2
VIP 192.168.102.51 is enabled
VIP 192.168.102.51 is not running
[root@ron12cprinode1 ~]# srvctl start vip -vip ron12cprinode1_2
[root@ron12cprinode1 ~]# srvctl start vip -vip ron12cprinode2_2
[root@ron12cprinode1 ~]# srvctl status vip -vip ron12cprinode1_2
VIP 192.168.102.51 is enabled
VIP 192.168.102.51 is running on node: ron12cprinode1
[root@ron12cprinode1 ~]#

Add the second SCAN

At this time you can add the second SCAN. The command syntax is shown here:

[oracle@ron12cprinode1 ~]$ srvctl add scan -h

Adds a SCAN VIP to the Oracle Clusterware.

Usage: srvctl add scan -scanname  [-netnum ]
    -scanname           Domain name qualified SCAN name
    -netnum               Network number (default number is 1)
    -subnet                        /[/if1[|if2...]] NET address specification for network
    -help                          Print usage

Implemented on my first cluster node the command is easier to comprehend.

[root@ron12cprinode1 ~]# srvctl add scan -scanname ron12cpri-dgscan.dg.example.com -netnum 2

[root@ron12cprinode1 ~]# srvctl status scan
SCAN VIP scan1 is enabled
SCAN VIP scan1 is running on node ron12cprinode2
SCAN VIP scan2 is enabled
SCAN VIP scan2 is running on node ron12cprinode1
SCAN VIP scan3 is enabled
SCAN VIP scan3 is running on node ron12cprinode1

You need to create the SCAN on both clusters. On my primary cluster the SCAN has been created with the following configuration:

[root@ron12cprinode1 ~]# srvctl config scan -netnum 2
SCAN name: ron12cpri-dgscan.dg.example.com, Network: 2
Subnet IPv4: 192.168.102.0/255.255.255.0/eth2
Subnet IPv6:
SCAN 0 IPv4 VIP: 192.168.102.54
SCAN name: ron12cpri-dgscan.dg.example.com, Network: 2
Subnet IPv4: 192.168.102.0/255.255.255.0/eth2
Subnet IPv6:
SCAN 1 IPv4 VIP: 192.168.102.55
SCAN name: ron12cpri-dgscan.dg.example.com, Network: 2
Subnet IPv4: 192.168.102.0/255.255.255.0/eth2
Subnet IPv6:
SCAN 2 IPv4 VIP: 192.168.102.56
[root@ron12cprinode1 ~]#

You can see the new VIPs in the output of ifconfig, just as you would with the primary SCAN:

eth2      Link encap:Ethernet  HWaddr 52:54:00:FE:E2:D5
          inet addr:192.168.102.50  Bcast:192.168.102.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:ff:fefe:e2d5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:523 errors:0 dropped:0 overruns:0 frame:0
          TX packets:339 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:118147 (115.3 KiB)  TX bytes:72869 (71.1 KiB)

eth2:1    Link encap:Ethernet  HWaddr 52:54:00:FE:E2:D5
          inet addr:192.168.102.55  Bcast:192.168.102.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

So there is nothing too surprising in the output, it’s exactly the same as before with the public SCAN created during the installation.

End of part 1

This already seems like a lot of text to me so I think it’s time to pause here. The next parts will demonstrate the addition of the SCAN listeners, the new node listeners on the *.dg.example.com network and finally the duplication of the primary RAC One Node database for use as a standby database.

Indexing Foreign Key Constraints With Invisible Indexes (Invisible People)

In my previous post I discussed when deleting rows from parent tables, how Bitmap Indexes based on the FK constraint can prevent the expensive Full Tables Scans (FTS) on the child tables but not the associated exclusive table locks. Last year, I discussed how it was possible in Oracle Database 12c to have multiple indexes on the same column list. […]

ASH Analytics- Tracking Down an Issue, Part I

This is the first of many posts I’ll do where we take a particular issue and trouble-shoot.  I’ll go through multiple scenarios to show the common steps to take via the Enterprise Manager 12c from discovery to identification to research to explanation.

This blog will use the following features:

  • ASH Analytics
  • SQL Details
  • ASH Report

The first thing we need is an issue-

ash_b_0421

Note the CPU red line-  the IO is considerably over that and quite a lot of IO, along with Commit and Concurrency waits.  We’ll start with this as our issue that we can see, has quickly escalated over our timeline, (15 minutes was requested from the view…)

Scanning down to the Top SQL, (by default) we can then see that this IO pressure is primarily caused by two-three SQL_ID during the timeline:

ash_b_0421_2

We can click on the first SQL_ID and display the insert statement.  We also note the escalation from 1pm to 1:15pm in the Statistics tab that shows the active sessions.

ash_b_0421_3

So I know a few of you are asking, “Why isn’t there any Plan Hash Value?  If it is a simple insert, with no subquery, etc. then would it have a Plan Hash Value?   Think about that as we inspect the next tab, Activity.

ash_b_0421_4

We are now inspecting just the wait events connected with THIS SQL_ID and the sessions that are involved with it.  On the right, we can quickly see that there is a huge percentage of cell single block physical read waits involved with this insert.  What does that tell you about the hardware that the insert is running on?  Yes, it’s part of an Exadata environment.

Scrolling down allows us to view the sessions involved in this timeline.  This is not just the sessions for the 15 minutes of escalation we are interested in.  These are ALL the sessions in the timeline shown above.  We can view from the top, .77% of the activity for the first one and note that it decreases as we go through the list.  Also notice that it’s 1-10 of 200 sessions total that have been captured during the total timeline.  We already know a majority of them are part of our escalation in IO on the system.

ash_b_0421_5

Inspecting the last 10 helps us see the decrease in IO resources as concurrency waits increased-

ash_b_0421_8

We are down to .39% by the time we get to the 200th session captured in this timeline.  Now getting back to our “Should we have a plan hash value for our insert statement?” question.  No, we shouldn’t and there isn’t a plan, nor is there plan control that will be found for this simple insert.  This is verified when you inspect the Plan and Plan Control tabs for this SQL_ID.

ash_b_0421_6

We then can look at the Tuning History.

ash_b_0421_7

You might wonder how could it be that this insert, that doesn’t have a plan or plan hash value is found in the tuning task?  If it is a top SQL that is deemed an impact to performance, then it will show up here.  There is no escape for this insert.

At this time, we can see that we are looking at a concurrency issue that is not coming from a user or from a specific session in any way.  So the next step is to get a clearer look at the 5+ minutes that lead up to the heavy IO to see what is really going on and eliminate assumptions.

ash_b_0421_9

I simply click on “Run ASH Report” in the SQL Details window, change the times to 1:10pm –> 1:16pm and notice that we are focused on this SQL_ID right still.

The report shows the standard header and high level info, but then once you dig in, you’ll see the top events:

ash_b_0421_10

We see that yes, it is almost 96% of the activity with an average of 21 active sessions running at a given time.

ash_b_0421_11

If you were to have traced this session, you’d see something similar to the following in the trace file to represent the data in the first three lines that we now see in the ASH report:

WAIT #3: nam='cell single block physical read' ela= 945 cellhash#=3983857215 diskhash#=3558547146 bytes=8192 
#ff0000;">obj#=12894 tim=1912764532115123
WAIT #3: nam='cell single block physical read' ela= 483 cellhash#=1017296094 diskhash#=1180032005 bytes=8192 
obj#=46129 tim=1213898462783761
WAIT #3: nam='cell single block physical read' ela= 697 cellhash#=1017296094 diskhash#=3896957901 bytes=8192 
obj#=47883 tim=1158963811267355

Note that there are THREE cell single block physical reads for the insert event.  Why would we see this?  This is the one question to the readers of this blog-  What would cause the single block physical reads on these three indexes?

 

ash_b_0421_13

It’s not the table we are having an issue with but the indexes that are on the table.  Three indexes show up very clearly in our Top DB Objects section showing our wait event, cell single block physical read.  The ASH report gained this information from the #ff0000;">obj#, just like you see in the trace file info in red up above that I displayed for you.  For each of those entries shown, a very similar percentage of the event is displayed farther up in the Top Event P1/P2/P3 Values.

So from here, I think we’ve inspected the SQL_ID pretty fully and we know why the problem is occurring.  There are three indexes that require a scan

The final answer we want is why is this heavy load occurring?  Well, ASH answers this for us, too-

ash_b_0421_answer

Yeah, someone is TRYING to put a heavy load on the database with Swingbench and the active average sessions matches our active average sessions overall.   We’ll leave it as is-  no one wants to be responsible for killing someone’s load test… :)

 



Tags:  


Del.icio.us



Facebook

TweetThis

Digg

StumbleUpon




Copyright © DBA Kevlar [ASH Analytics- Tracking Down an Issue, Part I], All Right Reserved. 2014.

Divergent

I’ve just got back from watching Divergent. It is a really good film!

Don’t believe any bullshit comparisons to that crappy Hunger Games. It is so much better than that rubbish! It’s probably a good idea not to read any summaries of the plot either, since it sounds kind-of stupid on paper. In the film it makes a lot more sense and just works.

Very pleased I went to see it. One of the better Sci Fi/action films I’ve seen is quite a while. Much more worthwhile than that spider-thing…

Cheers

Tim…


Divergent was first posted on April 22, 2014 at 12:16 am.
©2012 "The ORACLE-BASE Blog". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement.

Performance Testing with Agile Data

apple_orange

Performance testing requires full, fresh data

Many organizations don’t even attempt to test performance until very late in their development cycle because it is only in the UAT (or equivalent) environment that they have a full copy of their production data set.  Errors and inefficiencies found at this stage are expensive to fix and are often promoted to production due to pressures from the business to meet release schedules.

Delphix customers give each developer, or team of developers, a full, fresh copy of the database where they can validate the performance of their code in the UNIT TESTING phase of their projects.  Poorly written queries are identified by the developer and can be fixed immediately, before their code is submitted for integration with the rest of the application.   The test/fix iteration is much tighter and results in higher quality, better performing application releases.

How does Delphix enable this?

VDBs created by Delphix have many advantages over a physical database, and therefore can be used in unique ways.  Consider the following:

  • Self service.  Delphix automates all the complexity required to make changes to a database, allowing developers and testers to get what they need without waiting on associated support organizations.
  • Fast provisioning.  VDBs require no data movement at the time they are created, so even large databases can be created in a few minutes.
  • Easy data refresh.  Refreshing a VDB with the latest data from production can be done with 3 mouse clicks.  Never test against synthetic data.
  • Data rewind/reset.  Delphix tracks all changes made to a VDB and can rewind the state of the database to any point in time at the request of the user.  Run a test, rewind, change parameters, run the test again.
  • Efficient use of infrastructure.  VDBs run in a tiny storage footprint, allowing teams to run many more database environments in parallel.
  • Efficient use of licenses.  Turning VDBs on and off is trivial.  Test environments can be spun up as needed and suspended when testing is finished.  Suspended VDBs use no resources of the DBMS.
  • Database relocation.  VDBs are easily moved between database hosts, even across datacenters.

Following are examples of performance changes that can easily be tested in VDBs:

Database Configuration

  • changes to initialization parameters (eg. optimizer_index_cost_adj, optimizer_index_caching, etc)
  • changes to redo size, parameters
  • DBMS version and patch set
  • SGA size
  • CPU type, speed (move VDB between database hosts)
  • Different DB statistics, statistics gathering methods

Data Modeling

  • Index changes
  • SQL Profiles – Like the old stored outlines, you can set up a complex system of profiles on a VDB and test different explain plans
  • Run complex and potentially debilitating queries on a VDB to minimize impact, use TKPROF and heavy tracing you can’t do elsewhere

Application  Configuration

  • Testing application server connection pool sizes/limits
  • network bandwidth testing for multi-hop/firewall configuration
  • theoretical maximums for concurrent batch jobs (not just at the DB, but the app tier as well)
  • testing database monitoring solutions/thresholds/configuration impact
  • Oracle trace event impact when turned on (deviation from a baseline)

Enabling a physical UAT environment with Delphix

As mentioned above, many Delphix customers will still maintain a final testing environment that matches the production setup exactly.  They will have fibre channel (or equivalent) connections to the SAN directly from their DBMS host.  Even in this environment, which bypasses the Delphix Engine, our software can provide great benefit to the testing process.

The V2P feature can be used to migrate any data set contained within Delphix to a physical storage environment.  That means any data set captured from production, or any data set modified by a VDB can be pushed to UAT in an automated fashion by Delphix.  Running a V2P operation is not as fast as creating/refreshing a VDB because it requires data movement, but it is faster than restoring a traditional database backup and automates all the instance creation and configuration tasks.

Bringing it all together

The high level life cycle of performance testing on the Delphix Agile Data Platform looks something like the following:

  1. Create and/or refresh development environments with the latest full data set from production.
  2. Use VDBs to iterate quickly on unit tests of new code, data modeling changes, DBMS configuration changes.
  3. Integrate and test all changes in a highly parallelized QA environment, using VDBs to minimize the setup time between test runs.
  4. Run V2P to migrate release candidates to UAT for final performance verification.
  5. Promote changes to production.

 

A

The Poetry of Science

So easter was spent with the kids at a family oriented vacation spot. When everyone else was sleeping, I spent some time watching my list of videos "to watch" that I compile during my working days, so I dont forget to wathc all those wonderfull videos out there on the net. One of the videos I watched this holiday, was The Poetry of Science, with Richard Dawkins and Neil deGrasse Tyson. If I could only choose one video that my kids could watch during their education, this would be the one. The discussion between these two men, is really inspiring and if I was ever asked to define the meaning of life, this videos content would be a big part of my answer.

Centering Squarespace Buttons

Centering just one call to action button is easily done in Squarespace. But what if you have multiple buttons, and you want them in a row and centered as a group. That's a harder task, and I present in this post a fun hack to help you solve it. 

The Problem

Imagine writing a post about wheel sizes for mountain bikes. You aim to capture reader interest and motivate readers to dig beyond the surface of what is a contentious and fad-driven topic. You issue a call to action with a button like this one:

Dig Deeper!

Centering just one button is easy. I've created this button by dropping a Button block onto the page. Centering is as easy as choosing Center from the drop-down list of alignment choices. Job done!

Centering is a more interesting problem when two or more buttons are involved. Change your goal to that of getting readers to make a choice between two up-and-coming sizes that are pushing the traditional 26-inch wheel off the market. Now your call to action involves two buttons:

Go 29er

Choose 650b

The look here might not be what you're after. Both buttons are centered, but they are each centered in their own half of the display width. You prefer the buttons closer together and centered as a group.

A Failed Hack

One hack that almost works is to align the left-side button to the right, and the right-side button to the left. This has the effect of pushing the two buttons together in the center of the content. If you carefully write the button text to the same number of characters for each button, you can fake the effect of centering the buttons as a group. For example:

Go 29er

Go 650b

This approach falls apart fast. Just make your browser window narrower. Try it now. Narrow your window to mimic the size of your mobile phone display. You''ll see the buttons stack on top of each other and fly to opposite sides of the content area. The approach is not extensible beyond two buttons, and it's not easy to write button text to the same number of characters and width. A different solution is needed. 

A Successful Solution

A solution that works is to take Squarespace's HTML for a Button block, and to use a modified form of that HTML in a Code block to generate as many buttons as you need in a group. Here's how that approach plays out:

  1. Place one button on your page.
  2. Copy the HTML generated for that button.
  3. Paste the HTML into a Code block.
  4. Modify the HTML slightly, and replicate part of it for each button that you need.
  5. Delete the Button block placed in Step 1.

This approach is extensible beyond two buttons, and works well in desktop and mobile views. The buttons generated are indistinguishable from those created using a Button block, because the very same formatting is applied. 

Following is the HTML behind the Go 29er button shown just above. You can find the HTML by pressing CTRL-U to view this page's HTML source. Then search on the text "Go 29er". Find the second occurrance, and back up just a bit until you find the first of the enclosing div elements for the Button block.

 class="sqs-block button-block sqs-block-button" data-block-type="53" id="block-yui_3_10_1_1_1397998943922_173603">
class="sqs-block-content">
class="sqs-block-button-container--right">
href="http://twentynineinches.com/" class="sqs-block-button-element--medium sqs-block-button-element" >Go 29er>
>
>
>

Pasting this HTML into a Code block is the trick. Drop a Code block onto your page. Paste in the above HTML. Then make the following modifications:

  1. Remove sqs-block from the list of classes in the outermost div element. Your Code block will itself be an sqs-block. You don't want to nest one sqs-block inside another.
  2. Remove any id attributes that are present. Alternatively, you can replace any Squarespace-generated id values with ones that you make up yourself. 
  3. Remove the class attribute from the innermost div element. You'll be centering the buttons yourself, so it's best to avoid referencing the Squarespace-generated alignment class. 
  4. Write a style attribute into the tag and specify whatever margin you want for your buttons. I've specified margins of 1em in the example to follow.
  5. Write a style attribute into the innermost div element to center the text within that element. The effect will be to center the enclosed buttons as a group. I've specified text-align: center in the following example.
  6. Copy and paste the tag to create as many buttons as you need.
  7. Modify your copied tags to point to the correct URLs. 

Following is my result. There are two tags, one each for 29er and 650b. Each tag points to a URL that is appropriate for the choice being made. The margins of 1em provide visual separation between the buttons when they are left-and-right from each other, and also when they stack up in the mobile view. The innermost div centers the enclosed buttons as a group.

 class="button-block sqs-block-button" data-block-type="53">
class="sqs-block-content">
style="text-align: center;">
style="margin: 1em;"
href="http://twentynineinches.com/" class="sqs-block-button-element--medium sqs-block-button-element" >Go 29er
>
style="margin: 1em;"
href="http://650bpalace.blogspot.com/" class="sqs-block-button-element--medium sqs-block-button-element" >Go 650b
>
>
>
>

You can just begin with the HTML shown here. Steps 1 through 5 are done for you, and you can focus on Steps 6 and 7. Figure 1 shows the above code as it should be pasted into a Code block. 

Figure 1. The solution code as it appears when pasted into a Squarespace Code block

Figure 1. The solution code as it appears when pasted into a Squarespace Code block

Copy and paste the HTML into a Code block. Modify the button text and link targets. Copy-and-paste the tags to make as many buttons as you need.

The solution works because it places all buttons into the same div element where they can be centered as a group. Here's the final result

Go 29er
Go 650b

You can adjust the margin settings as needed to get the precise spacing that you like. The buttons are identical to those generated by the Button block. You can narrow your browser window, and these will eventually stack up vertically while remaining centered. 

Some Formatting

The buttons in this article are medium-size. You'll see the following class assigned to the elements:

sqs-block-button-element--medium
You can also create small and large buttons. Simply specify small or large in the class name. For example:
sqs-block-button-element--small
sqs-block-button-element--large

Other aspects of button formatting are controllable from the Style Editor. Click the paintbrush icon to get there, and scroll down to the Button Block settings. You'll be able to specify rounded corners, pill-shaped buttons, and probably a few other options depending upon your chosen template.

And Sew On

The fundamental problem at the beginning of this article is that each button is being centered within its own, independent space. That's the behavior you get when you drop Button blocks onto a page, and it's perfectly reasonable behavior too. Sometimes though, you do want to center a block of buttons as a single unit. That's also reasonable, and the hack in this article provides an approach that works toward that end.

Note: You can choose to write your buttons entirely from scratch. Kris Black shows how to do so in his article Create a Simple Call to Action Button. An advantage to the approach I describe is that you can still use the Style Editor to style the resulting buttons, and they will be consistent in appearance with any that you create through the Squarespace Button block. An advantage to Kris's approach is that you can style your buttons without being limited to the built-in choices.


Learn CSS for Squarespace

9.99

Learn CSS for Squarespace is a short, seven-chapter introduction to working with CSS on the Squarespace platform. The book is delivered as a mobi file that is readable from the Kindle Fire HDX or similar devices. A complimentary sample chapter is available. Try before you buy.

Add To Cart

The Amazing Spider-Man 2

I’ve just got back from watching The Amazing Spider-Man 2.

Wow, that is one seriously long film! At 2 hours and 22 minutes, it’s a good 1 hour and 22 minutes too long…

I guess there are two sides to this film:

  1. Action Scenes: During the action this films it is brilliant. Really over the top stuff. Bright, flashy and really cool.
  2. Everything Else : I don’t give a crap about character development in an action film. This re-imagining of the franchise is turning out to be even more whiny than the Toby Maguire version.

The film really could have been edited down massively and I would have come out agreeing with the film title. As it was, it’s “The Amazingly Long and Whiny Spider-Man Too!”

Cheers

Tim…


The Amazing Spider-Man 2 was first posted on April 19, 2014 at 8:26 pm.
©2012 "The ORACLE-BASE Blog". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement.

Running scripts in CDBs and PDBs in Oracle Database 12c

You’ve been sold on the whole concept of the multitenant option in Oracle 12c and you are launching full steam ahead. Your first database gets upgraded and converted to a PDB, so you start testing your shell scripts and bang! Broken! Your company uses CRON and shell scripting all over the place and the multitenant architecture has just gone and broken the lot in one fell swoop! I think this will end up being a big shock to many people.

I’ve been talking about this issue with a number of people since the release of Oracle 12c. Brynn Llewellyn did a session on “Self-Provisioning Pluggable Databases Using PL/SQL” at last year’s UKOUG, which covered some of these issues. More recently, I spent some time speaking to Hans Forbrich about this when we were on the OTN Yathra 2014 Tour.

Today, I put down some of my thoughts on the matter in this article.

Like most things to do with Oracle 12c, I’m sure my thoughts on the subject will evolve as I keep using it. As my thoughts evolve, so will the article. :)

Cheers

Tim…


Running scripts in CDBs and PDBs in Oracle Database 12c was first posted on April 19, 2014 at 4:23 pm.
©2012 "The ORACLE-BASE Blog". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement.