Thursday, December 29, 2005

Funky redo behaviour in 10g

I'll admit it, I don't have that much exposure to 10g just yet. I'm excited about it, I just don't have much experience on it.

We put up a development database on 10.2 a couple months back just so we could start getting experience on 10g. As we add more and more development schemas to this database, we're getting a taste for the new features.

We've been getting a disproportionate number of "Checkpoint not complete" messages lately. Sure, there's pretty heavy write activity going on at the time, but not enough to fill all my redo logs. I have six groups of 128M logfiles with two members each. During the heavy write activity, my logs get switched a few times in a minute. However, I know my log_archive_dest can keep up with the write activity, so there should be no problem archiving them that fast. From the alert.log:
Thu Dec 29 19:05:37 2005
Thread 1 cannot allocate new log, sequence 9945
Private strand flush not complete
Current log# 4 seq# 9944 mem# 0: /u01/oradata/demo1/redo04_01.log
Current log# 4 seq# 9944 mem# 1: /u02/oradata/demo1/redo04_02.log
Thread 1 advanced to log sequence 9945
Current log# 5 seq# 9945 mem# 0: /u01/oradata/demo1/redo05_01.log
Current log# 5 seq# 9945 mem# 1: /u02/oradata/demo1/redo05_02.log
Thu Dec 29 19:06:28 2005
Thread 1 advanced to log sequence 9946
Current log# 1 seq# 9946 mem# 0: /u01/oradata/demo1/redo01_01.log
Current log# 1 seq# 9946 mem# 1: /u02/oradata/demo1/redo01_02.log
Thu Dec 29 19:06:42 2005
Thread 1 advanced to log sequence 9947
Current log# 2 seq# 9947 mem# 0: /u01/oradata/demo1/redo02_01.log
Current log# 2 seq# 9947 mem# 1: /u02/oradata/demo1/redo02_02.log
Thu Dec 29 19:07:00 2005
Thread 1 cannot allocate new log, sequence 9948
Checkpoint not complete
Current log# 2 seq# 9947 mem# 0: /u01/oradata/demo1/redo02_01.log
Current log# 2 seq# 9947 mem# 1: /u02/oradata/demo1/redo02_02.log
Thread 1 advanced to log sequence 9948

After the write activity is over, I look at v$logfile and v$log and see that several groups are still ACTIVE.

I then doubled the size of the logfiles and reran the big job that caused the "Checkpoint not complete" error. While the job didn't cause a "Checkpoint not complete" error, it did make three of the log groups ACTIVE, which I kind of expected. However, 20-30 minutes later, I looked at v$logfile and v$log to see almost all my log groups were either ACTIVE or CURRENT.

system@demo1.us> l
1 select l.group#, lf.member, l.bytes/1024/1024 mb, l.status, l.archived
2 from v$logfile lf, v$log l
3* where l.group# = lf.group#

GROUP# MEMBER MB STATUS ARC
------ ------------------------------- ----- ---------- ---
1 /u01/oradata/demo1/redo01_01.log 256 CURRENT NO
3 /u01/oradata/demo1/redo03_01.log 256 ACTIVE YES
3 /u02/oradata/demo1/redo03_02.log 256 ACTIVE YES
4 /u01/oradata/demo1/redo04_01.log 256 ACTIVE YES
4 /u02/oradata/demo1/redo04_02.log 256 ACTIVE YES
5 /u01/oradata/demo1/redo05_01.log 256 ACTIVE YES
5 /u02/oradata/demo1/redo05_02.log 256 ACTIVE YES
2 /u01/oradata/demo1/redo02_01.log 256 INACTIVE YES
2 /u02/oradata/demo1/redo02_02.log 256 INACTIVE YES
1 /u02/oradata/demo1/redo01_02.log 256 CURRENT NO
6 /u01/oradata/demo1/redo06_01.log 256 ACTIVE YES
6 /u02/oradata/demo1/redo06_02.log 256 ACTIVE YES
-----
Total 3072

12 rows selected.

Elapsed: 00:00:00.05

During light load, I would expect one group CURRENT and maybe one group ACTIVE. The other funny thing is the logs show they are archived, which if I look at the log_archive_dest, they are. I have to do some more research, but I suspect there's an init.ora parameter or something that isn't set correctly...

Tuesday, December 27, 2005

Router and WAP in one

Santa brought me a new NetGear router for Christmas. This particular router has an 802.11g WAP built-in so I don't have to give up an ethernet port for it. The basic setup was really easy and when I customized things like the LAN IP and DHCP addresses it was somewhat easy. The only thing that was somewhat difficult was setting up the WEP. I tried to choose my former Passphrase so I wouldn't have to change the wireless devices, but the router just wouldn't take it because it was the wrong length. The WAP has the ability to run WPA, so I set that up instead. Unfortunately, using WPA precludes me from using my Palm, but browsing on the Palm never really worked well anyway.

The old Linksys WAP is on it's way to the local landfill where it belongs. I'm hanging on to the old Linksys router for a backup.

Thursday, December 22, 2005

Interesting take on RTFM

I got a kick out of Andrew Gilfster's blog about RTFM. Maybe I'm a little more cynical, cause I think it's perfectly appropriate in certain aggrevated circumstances to give somebody "RTFM" as an answer.

Monday, December 19, 2005

The "New & Improved" Metalink

I jumped on the new metalink last night and was zipping along pretty good. It's definitely different, but I'm not sure different is bad. Today, however, 6 minutes to login. Three minutes to bring up the TAR query screen (or should I say Service Request). Another 4 minutes to get my TAR back. If they're going to make Metalink the primary interface to customer service, can we at least make sure it is somewhat responsive?

Saturday, December 17, 2005

Yummy yum

One of the things that pushed me to upgrade to Fedora Core 4 was suspense of the automatic updates from the Red Hat Network a while ago. It seemed as though every time I wanted to install something I needed to search out the correct RPMs and install them before I could intstall the software I originally wanted to install.

FC4 opened my eyes to a totally new updating method; yum. I did a quick search and found The Unoffical Fedora FAQ which walked me through setting up yum and installing software for it. I installed the updated gcc compiler using yum and it only took a couple minutes to download gcc and any dependencies. "Wow, this is easy", I thought to myself, so I used yum to update OpenOffice.org to 2.0. This is definitely a nice tool to keep some of your general software up to date.

I don't think I'll use yum to keep my main database software updated. For example, I'm going to be doing research on having multiple versions of MySQL on the same system. During this research, I'm going to put MySQL 4.1 in one directory and 5.0 in another. I don't want my 4.1 software automatically updated until I want it updated.

I wonder if Oracle has a yum repository for Oracle Applications? (If you deal with Oracle Apps, you know what I'm talking about).

I think this will be a big time-saver.

Thursday, December 15, 2005

FC4 installed

I have the base Fedora Core 4 installed with only a couple issues. When I decided to install the new OS and update my software, I figured I might as well upgrade my Hard Drive. I got an Ultra ATA/133 200G drive and replaced my 20G drive. Of course, I didn't read the package and didn't notice I needed a different I/O card. Back to CompUSA to get the new card.

The second little glitch was I downloaded the ISO images and burned them to CD. Except I didn't realized I had to burn them in a specific way. The second time I figured it out and was able to install right off CD.

The particular distribution I used had Firefox 1.0.4 and OpenOffice 1.9 (2.0 beta) so I'm no further ahead in that respect. Since I was planning on re-installing these packages anyway, it's not a big deal. My first task, however, is to get the MySQL 5.0 source and get Apache configured. More updates to come...

Wednesday, December 14, 2005

Out with the old, in with the new

I'll have a couple free hours over the next few weeks, so I have decided to upgrade my Linux box at home to RedHat Fedora Core 4. The software on it was really out of date (Firefox 1.0.4, Thunderbird 0.9, MySQL 4.0, OpenOffice 1.0, etc.), so instead of updating everything I figured I'd go the extra step and do everything. Tonight I am spending a couple hours downloading ISO images and burning them to CD. Stay tuned for the progress...

Tuesday, December 13, 2005

MySQL and icc solved

Thanks to Lenz Grimmer on the MySQL forums. His solution was to use the following variables:

CC=icc \
CFLAGS="-O3 -unroll2 -ip -mp -restrict" \
CXX=icpc \
CXXFLAGS="-O3 -unroll2 -ip -mp -restrict" \
LDFLAGS="-static-libcxa -i-static"

Monday, December 12, 2005

Installing just the MySQL Client using icc

I started out today doing what I thought was a simple task; Install the MySQL client using Intel's compiler. In my environment, we like to install the client software so it is generally available to everyone and the server software on the actual physical box. We feel this gives us the flexibility to upgrade the servers indendently from all the programs.

I've compiled the 5.0.16 software using gcc about a dozen times already and other than a few simple tweaks here and there, it was a no-brainer. When I installed the client, I used gcc instead of the preferred (in my environment) icc.

I started by issuing a "make clean" to remove any builds I did before. I then changed my CC and CXX environment variables to point to the icc compiler and did:

$ configure --without-server --prefix=/usr/local/mysql_client

On my first try I encountered errors that were looking for "__cxa_pure_virtual". I googled and found this which gave me some additional things to do. Sure enough, this solved my "__cxa_pure_virtual" problem, but now I have more errors:

$ export CC=icc
$ export CXX=icc
$ export CFLAGS="-O3 -unroll2 -ip -mp -no-gcc -restrict"
$ export CXXFLAGS="-O3 -unroll2 -ip -mp -no-gcc -restrict"


and then I configure with the following options:

$ ./configure --without-server --prefix=/usr/local/mysql_client --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared --with-client-ldflags=-all-static


I then run "make clean" to clean out any failed compiles and it runs fine.

I then run just "make" and it chugs along for a while, but then exits with errors like:

mkdir .libs
icc -O3 -DDBUG_OFF -O3 -unroll2 -ip -mp -no-gcc -restrict
-o gen_lex_hash gen_lex_hash.o ../myisam/libmyisam.a
../myisammrg/libmyisammrg.a
../heap/libheap.a ../vio/libvio.a ../mysys/libmysys.a ../dbug/libdbug.a
../regex/libregex.a ../strings/libmystrings.a -lz
-lpthread -lcrypt -lnsl -lm -lpthread
gen_lex_hash.o(.eh_frame+0x12): undefined reference to
`__gxx_personality_v0'
make[2]: *** [gen_lex_hash] Error 1
make[2]: Leaving directory `/srcpath/5.0.16/mysql-5.0.16/sql'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/srcpath/5.0.16/mysql-5.0.16'
make: *** [all] Error 2


Obviously, I'm missing a reference to __gxx_personality_v0, but where do I get that from? Maybe one of my other libaries is out of date? If anybody has any hints, I'd appreciate you sharing them at http://forums.mysql.com/read.php?11,59295,59295#msg-59295.

Update: Solution

Thursday, December 08, 2005

Where MySQL and Oracle are the same...

Say you've developed software on Oracle for a while. You know that if you start a query in SQL*Plus and then kill -9 the process that your query is still running on the server. You've got enough calls from your DBA to know that if you do that, you better call and let him know it's still running. Would you think it's any different on MySQL? Nope.

Wednesday, December 07, 2005

Three wishes...

While looking at something else, I came across 3 Things I wish I'd done by Jeanne Sahadi. While Jeanne writes about money and finance related stuff, I think the third point about valuing your work is right on.

Early in my career, I worked for a very large university in their IT department. Just being out of college, I was very grateful to even have a job. But anybody who works in the public sector knows, the pay ain't that great. In order to make ends meet, I started writing code "on the side" with a friend of a friend. I wrote a system in Paradox (version 3.5 for you techno geeks out there) for $10/hr. I got paid, but found out later that the person I was working for billed the client $50/hr for my time. This person then went on to sell this system to other clients and, of course, I didn't have any rights to it.

I also wish I listened to my gut. I had been working at a regional telecom company in the late 1990's. I had been perfectly happy there for three years and the pay was more than adequate. In 1998, during the rise of the dotcom bubble, I was seduced by a consulting company by the promise of 100% bonuses and four day work weeks. I agonized about it for about a week, and although my gut told me it was too good to be true, I jumped ship. After about two weeks I knew I made a mistake, but told myself it would get better. Fortunately, I had a good management team back at the telecom company and kept in touch with them. After two months I decided I'd had enough of consulting and went back to my old job.

Tuesday, December 06, 2005

Moving an application

We moved one of our major schemas to a new database this past weekend. This schema had lived in the same database for over six years. Over that time many people worked on the system and brought their experience to the development of it. Some of the things we found during the move:

  1. Some Java programs still continue to use a connection URL of host:port:sid.
  2. People really like synonyms. There were a couple situations where a synonym pointed to a synonym which pointed to a synonym which pointed to a synonym...
  3. Recently, we have been setting up TNS aliases for each application and not each database. Sure, when we have multiple applications on one database there are multiple aliases. But when we move the application and flip the alias, everybody changes at once. Programs that used the application specific aliases moved with no problems.
  4. It's 2005 (almost 2006) and we are still fighting people hard-coding username/passwords in their programs.
  5. Got a call from a user Sunday, "I can't login with user X to the database." I replied, "User X doesn't live on that database anymore, and where did you get user X's password?"

Saturday, December 03, 2005

It may be early...

It is really early in the College Basketball season, but who would have thought the North Carolina Tarheels would give the Illini a strong fight and be 4-1 after seeing Illinois AND Kentucky? Just when everyone counted old Roy out...

Wednesday, November 30, 2005

More stupid internet stuff

Sorry folks, I'm tied up with a nasty tuning job right now. Here's some more stupid internet fun...

You Are 35 Years Old

Under 12: You are a kid at heart. You still have an optimistic life view - and you look at the world with awe.

13-19: You are a teenager at heart. You question authority and are still trying to find your place in this world.

20-29: You are a twentysomething at heart. You feel excited about what's to come... love, work, and new experiences.

30-39: You are a thirtysomething at heart. You've had a taste of success and true love, but you want more!

40+: You are a mature adult. You've been through most of the ups and downs of life already. Now you get to sit back and relax.

Sunday, November 27, 2005

8th Grade Math




You Passed 8th Grade Math



Congratulations, you got 10/10 correct!

Friday, November 25, 2005

My First MySQL "Doh"!

Getting into a support type role with some developers using MySQL. One particular developer wanted to use the "LOAD DATA INFILE..." command to load some data from a text file.

I think to myself, "No problem, just grant the FILE privilege".

He tells me "LOAD DATA INFILE" still doesn't work. After a little head-scratching, I pull out MySQL by Paul DuBois and realize it only works from the server and not from the client. Doh. (Although the "Access denied" error was pointing me to the MySQL maze known as privileges).

Thursday, November 24, 2005

First Snow


The first snow of the season always brings hope that the bad things in the year can be purified (or covered up). I'll be cursing the weather after three months of scraping the car windows and shoveling the walk, but for now, it brings hope.

The way a crow
Shook down on me
The dust of snow
From a hemlock tree
Has given my heart
A change of mood
And saved some part
Of a day I had rued.

-- Robert Frost, "Dust of Snow"

Monday, November 21, 2005

Map24.com

I find myself using maps.google.com and mapquest.com to get directions to places I don't typically frequent. If I'm going to 3 or 4 places, I find these mapping sites to be a pain because you have to get directions from point 1 to point 2, point 2 to point 3, point 3 to point 4, etc. It gets pretty tedious. I've often thought to myself, why can't I put in all my addresses and get directions?

Then I came across Map24.com. You can put up to 5 destinations and get your directions all at once.

There are a couple improvements I'd like to see to the site. First, I could only get the map to display with IE, and not every time.

Also, right now you can specify the order in which you want to visit your destinations. However, I think it would be nice to put all my addresses in and let the software calculate the order I should visit them in order to maximize my time.

Check it out, see what you think.

Wednesday, November 16, 2005

Making IT Exciting Again

I was reading through Computerworld the other day and stumbled upon Making IT Exciting Again, an OpEd piece by Bruce A. Stewart. Back in the heyday of the late 90's you could come up with just about any idea for a web-presence and your company would fund it. Bruce points out that in this age of slashed budgets and trying to more with less, you can focus your efforts on business goals to make your work exciting again. Sure, you'll still be trying to keep your head above water, but you'll have fun doing it.

Mr. Stewart takes two cases in his own business where he examined risk and return to help the C levels recognize people in IT have a little smarts and know more about the business than rebooting a couple computers and make pretty websites.

My own career is a little contradictory to the respective times. In the late 90's I was working for a private telecommunications company that was expanding like wildfire. Every penny was stretched and every request for anything over $500 had to go the COO. Ask for over five grand and you met with the President/Owner of the company. You can imagine the business case we had to present when I asked for $1.2 Million to buy a Sun E5500 and 800G of disk. I got it, but the business case took my manager, a reseller, and myself about six weeks to put together.

My first project at my new company in 2000 was to move one of the two instances off an Ultra 2 with six 9G disks to its own Ultra 2 with six 9G disks. We discussed transaction and data volumes and I said on day one the U2 wouldn't cut it. A month later, we were on a 4 CPU box with dedicated fibre attached storage. Today I have about 20 boxes running about 12TB of storage on a SAN. I've had to justify it, but never had to write more than an email to get it.

Sure, I got lucky. Every time I think things are slowing down, wham, we get hit with a new project. Every day is exciting.

Tuesday, November 15, 2005

More WAP Worries

It happened again. My WAP lets me connect for about 15 minutes and then all of a sudden goes away. I try rebooting, resetting, and everything else but still no dice. I can't believe I spent another 3 hours on this last night. Time for a new Router/WAP.

Ideally, I'd like a WAP and Router all in one. The WAP would have to support WEP or some other authentication/encryption protocol since I live in a high density area. The router would have to support DHCP, which I think most do. Does anybody have any recommendations?

Monday, November 14, 2005

Periodic Reboots

The sysadmins did maintenance on some common NFS filesystems this weekend. Before they rebooted my workstation they saw:

root@mybox> uptime
1:20am up 500 day(s), 13:23, 1 user, load average: 0.00, 0.00, 0.01

If I had a dollar for every Windows PC that didn't have to be rebooted in 500 days, I'd have...nothing.

Friday, November 11, 2005

Re-examining what you know

Tom Kyte has a very entertaining presentation on "Things You Know" which takes a humourous, yet logical poke at what we think we know and the methods we use to come up with those conclusions. It underlines his philosophy of "trust but verify".

As you may recall, I was searching for a DBA to fill an open slot. As with any new addition, it takes time to assess the individual's abilities and figure out how they will be integrated into the team. I constantly find myself wanting to say "That's the way it works, trust me" but try to take time to explain.

For example, the other day we were recovering a database in the development environment. To do this project we had to recreate the controlfile and do an incomplete recovery. While doing the recovery, Oracle asked for an archived redo log that was months old. We got into a discussion of how the controlfile works with an incomplete recovery, how that relates to each datafile and why Oracle may be asking for a real old archived redo log. I think my DBA learned a little more about Oracle and I learned that he now knows the function of the controlfile.

I want to instill into my team members the ability to question why things are setup as they are. Sometimes I just want something done a particular way because it needs to be done fast. However, I also don't want them to take my word because I don't always know...

Tuesday, November 08, 2005

Upgrading Oracle Applications

I've been working on a huge project the last few months. We're upgrading to Oracle Applications version 11.5.9 from a much-much-older version of 11.5. One thing that I've never liked about the adpatch program is that it is an interactive session expecting someone to be actively monitoring it's progress. For example, when applying the 11.5.9 monster patch, adpatch goes for about 6 hours and then asks the question "Do you want to continue?". Great. I left the office two hours ago and it will be about 8 more before I get back. Ten wasted hours. At least I'll know I have to stick around for six hours when I apply it to production...

Monday, November 07, 2005

Not Checking out

The blog has kind of taken a backseat the last week or so. Things at work have gotten exceptionally busy with year-end coming around and other business activity. I was the lucky chap (can Americans say that?) "on duty" this weekend and it was just one failure after another. Seventeen hours later and I think I've got almost everything cleaned up. Hang in there, I've got more coming...

Wednesday, November 02, 2005

Technology at the Police Department

I had to get fingerprinted the other day at my local Police Department and I encountered some interesting technology. Rest assured, it was for recreational purposes only.

I've been fingerprinted for before. My work requires a background check and as part of the investigation your fingerprints get sent to the FBI. The last time I was fingerprinted a police officer came in with his trusty ink pad and cards. He rolled each finger in the appropriate box and you were left with a mess on your hands.

Today, it was a different story. First, the officer put my information into a computer. Instead of pulling out the trusty ink pad, he placed my fingers on a glass surface and then scanned my fingerprints. You still have to go through the same process where the officer rolls each of your fingers over the glass, but it's definitely less messy.

The only thing I was disappointed with is when you're done, the officer runs a fingerprint card through a laser printer and your prints get transferred to a standard form. Once they are sent to the FBI, they get scanned again for analysis. Wouldn't it be much easier to just transfer the images to the FBI directly? Maybe it wouldn't take 6 weeks to get the results back.

Tuesday, November 01, 2005

HP, EVA's and databases

Getting the next generation disk array from HP and I'm trying to figure out the best way to configure it. The EVA has a new concept called "disk groups" that I just can't get my hands around. The lowest level of storage that the EVA uses is a Redundancy Storage Set (RSS). The EVA basically groups your disks into these RSS's based on the number of disks in your disk group.

The "disk group" basically sits on top of the RSS and is a logical collection of disks. The disk group is stiped across all disks in the disk group. Each "virtual disk" (basically LUN) is then created from a single disk group and assigned a "vRaid" level. You can create as many "vDisks" in your disk group as you need. A single vDisk can not span multiple disk groups unless you use a LVM like vxvm.

The documents I'm reading (here, and here) are conflicting at best. One says that a database server should have one disk group effectively implementing SAME (stripe and mirror everything) for you. The other document says to configure the number of disk groups for the type of I/O you will encounter. Knowing that the redo logs will be sequential access and the datafiles will be a mix of random and sequential access, I think there should be at least two disk groups.

Performance wise, every fiber of my being tells me one filesystem just isn't going to cut it no matter how many physical disks are under it. Do I really want all 48 disks spinning for a 8k write?

One of my fears is that if I lose a disk group, I lose everything. HP, of course, says you will never lose a disk group. Experience on other HP products tells me the first time we have a failure, we'll get some bad advice and wipe something out. Am I just being paranoid about losing a disk group?

Does anybody have practical experience on HP EVA's that can offer some insight?

Wednesday, October 26, 2005

Skipping a beat

I have one production database left on 8.1.7.4, although it's pretty irrelavent at this point. The plans are in the works to upgrade that particular database to 9.2, so it's time to "decommission" it's 8.1.7.4 development database.

Part of the decommissioning process is to truncate all the tables in the development database, but leave the structure in place just in case we have to do any quick compiles. Although I know it's running on my development database, my pulse still quickens when I see all those tables whirring by knowing they're being truncated. I double and triple checked that I was on development, but still I was a little nervous pressing the "Enter" key...

Monday, October 24, 2005

Giving up on dbms_metadata

My group was assigned a project to create a script that would dump the DDL of a schema to source. We figured dbms_metadata was the way to go and started writing our script. The process was to dump a particular object type, and then run that DDL on an empty schema to make sure it ran.

First thing we hit was good old bug 3832291:

ORA-31603: object "SYS_C0059941" of type CONSTRAINT not found in schema "MYSCHEMA"
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 105
ORA-06512: at "SYS.DBMS_METADATA", line 628
ORA-06512: at "SYS.DBMS_METADATA", line 1221
ORA-06512: at line 1

OK. We figured out a way around that by generating constraints as ALTER statements. As we're cooking along again, blam, bug 3721907. Sure, we found a way around that one too.

The final nail in the coffin, was the performance with the whole thing. It took 30 minutes to dump a small schema of about 200 tables and a couple dozen packages. Checked metalink and found good old bug 3653586.

Looks like most of these bugs are fixed in 10g, but I'm not upgrading a bunch of instances just so dbms_metadata works. Sigh.

Wednesday, October 19, 2005

Automating the post office

I thought I had a simple task; mail a letter, get a return receipt, and have the ability to track it. I don't do this every day, so I went to the post office and started reading. Certified mail, Delivery Confirmation, Registered Mail, Priority Mail... it was a lot to take in. I finally decided I wanted Delivery Confirmation with a Return receipt. I filled out both forms and went to wait in line. One line, with one teller.

A friendly postal worker announced "Anybody paying by debit card or credit card can use the automated postal center." Cool, I thought, and I proceeded over to the ATM like thingy.

I must have had a blank stare on my face because the same postal worker asked me, "Do you need help?"

"I just want to mail this letter, get an acknowledgement from the recipient, and be able to track it if it gets lost.", I replied.

"Those aren't the right forms. The machine will print out the right ones."

"OK, cool." I start punching away. Letter. First Class. Done.

"Um, it didn't ask me if I wanted to get a return receipt."

"You did it wrong. You have to add a service."

"O...K..." Cancel. Letter. First Class. Add Service. Return Receipt.

"How do I know my tracking number?"

"You have to add a different service."

At this point, she is getting just as frustrated as I am. There's three Moms behind me patiently waiting to send cookies off to their kids. We go through it together: Cancel. Letter. First Class. Add Service. Certified Mail. Add Return Receipt. Done.

Finally, the stamp prints out. Another form prints the Return Receipt card and another sticker I'm supposed to put on the letter. The form is about half "peel and stick" and half regular paper. I fill out the "peel and stick" part and put it on the back of my letter. I carefully place the other sticker on the front of my envelope and fold it according to the directions on the form. I drop my neatly assembled letter in the big mailbox next to the APC.

"That's for packages", she says and quickly adds on "but it will get there." I'm going to the window next time.

Monday, October 17, 2005

Wicked ORA-27054, Solved

You may recall that I've been having problems getting 10gR2 backed up to NFS mounted disk. After we got bounced around a couple groups of Oracle Support, we finally landed into the capable hands of David Marshall.

After much research on David's part and some testing on our own, we settled on using the following parameters to mount our NFS filesystems for the purpose of backup:

rw,bg,intr,hard,timeo=600,wsize=32768,rsize=32768,nfsver=3,tcp

So all is well now. Our 9.2 backups complete in the same time and our 10.2 backups complete in an acceptable time. Now if we just knew which one of those parameters did it, we'd complete the education process.

Saturday, October 15, 2005

Setting up Multiple Listeners

Somebody had a problem in one of the forums with connections timing out. I suggested the error might be due to the listener being really busy and the poster could setup multiple listeners and load balance between the two. The setup was complex enough that I wanted enough room to explain the whole thing.

Setting up two listeners on the same box is done via the listener.ora file. The listener.ora file is usually located in your $ORACLE_HOME/network/admin directory. I have setup two listeners on my test box and the listener.ora file looks like this:

LSNR1666 =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = jake)(PORT = 1666))
)
)
)

LSNR2666 =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = jake)(PORT = 2666))
)
)
)

SID_LIST_LSNR1666 =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = lx10r2.us)
(ORACLE_HOME = /u01/app/oracle/product/10.2.0.1)
(SID_NAME = lx10r2)
)
)

SID_LIST_LSNR2666 =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = lx10r2.us)
(ORACLE_HOME = /u01/app/oracle/product/10.2.0.1)
(SID_NAME = lx10r2)
)
)

This part of the listener.ora tells me my listener name is LSNR1666 and that it is listening on port 1666 of hostname "jake" and I'll be using the TCP protocol.

LSNR1666 =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = jake)(PORT = 1666))
)
)
)

This part of the listener.ora tells me that LSNR1666 will be listening for the DB named lx10r2.us whose ORACLE_HOME is /u01/app/oracle/product/10.2.0.1 and whose ORACLE_SID is lx10r2. (This could have been specified with a SERVICE_NAME also, but I chose to do it this way because it is simpler).

SID_LIST_LSNR1666 =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = lx10r2.us)
(ORACLE_HOME = /u01/app/oracle/product/10.2.0.1)
(SID_NAME = lx10r2)
)
)

That's it, now you just start the listeners by name:


[oracle@jake admin]$ lsnrctl start lsnr1666

LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 15-OCT-2005 08:52:23

Copyright (c) 1991, 2005, Oracle. All rights reserved.

Starting /u01/app/oracle/product/10.2.0.1/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 10.2.0.1.0 - Production
System parameter file is /u01/app/oracle/product/10.2.0.1/network/admin/listener.ora
Log messages written to /u01/app/oracle/product/10.2.0.1/network/log/lsnr1666.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jake)(PORT=1666)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=jake)(PORT=1666)))
STATUS of the LISTENER
------------------------
Alias lsnr1666
Version TNSLSNR for Linux: Version 10.2.0.1.0 - Production
Start Date 15-OCT-2005 08:52:23
Uptime 0 days 0 hr. 0 min. 0 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /u01/app/oracle/product/10.2.0.1/network/admin/listener.ora
Listener Log File /u01/app/oracle/product/10.2.0.1/network/log/lsnr1666.log
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jake)(PORT=1666)))
Services Summary...
Service "lx10r2.us" has 1 instance(s).
Instance "lx10r2", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully
[oracle@jake admin]$ lsnrctl start lsnr2666

LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 15-OCT-2005 08:52:30

Copyright (c) 1991, 2005, Oracle. All rights reserved.

Starting /u01/app/oracle/product/10.2.0.1/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 10.2.0.1.0 - Production
System parameter file is /u01/app/oracle/product/10.2.0.1/network/admin/listener.ora
Log messages written to /u01/app/oracle/product/10.2.0.1/network/log/lsnr2666.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jake)(PORT=2666)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=jake)(PORT=2666)))
STATUS of the LISTENER
------------------------
Alias lsnr2666
Version TNSLSNR for Linux: Version 10.2.0.1.0 - Production
Start Date 15-OCT-2005 08:52:30
Uptime 0 days 0 hr. 0 min. 0 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /u01/app/oracle/product/10.2.0.1/network/admin/listener.ora
Listener Log File /u01/app/oracle/product/10.2.0.1/network/log/lsnr2666.log
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jake)(PORT=2666)))
Services Summary...
Service "lx10r2.us" has 1 instance(s).
Instance "lx10r2", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully


We can see that the listeners are started and waiting for connections:

[oracle@jake admin]$ tail $ORACLE_HOME/network/log/lsnr1666.log
Trace information written to /u01/app/oracle/product/10.2.0.1/network/trace/lsnr1666.trc
Trace level is currently 0

Started with pid=3201
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jake)(PORT=1666)))
Listener completed notification to CRS on start

TIMESTAMP * CONNECT DATA [* PROTOCOL INFO] * EVENT [* SID] * RETURN CODE
WARNING: Subscription for node down event still pending
15-OCT-2005 08:52:23 * (CONNECT_DATA=(CID=(PROGRAM=)(HOST=jake)(USER=oracle))(COMMAND=status)(ARGUMENTS=64)(SERVICE=lsnr1666)(VERSION=169869568)) * status * 0
[oracle@jake admin]$ tail $ORACLE_HOME/network/log/lsnr2666.log
Trace information written to /u01/app/oracle/product/10.2.0.1/network/trace/lsnr2666.trc
Trace level is currently 0

Started with pid=3211
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jake)(PORT=2666)))
Listener completed notification to CRS on start

TIMESTAMP * CONNECT DATA [* PROTOCOL INFO] * EVENT [* SID] * RETURN CODE
WARNING: Subscription for node down event still pending
15-OCT-2005 08:52:30 * (CONNECT_DATA=(CID=(PROGRAM=)(HOST=jake)(USER=oracle))(COMMAND=status)(ARGUMENTS=64)(SERVICE=lsnr2666)(VERSION=169869568)) * status * 0

Next, we configure the client. The client naming is usually controlled by a file called tnsnames.ora in the $ORACLE_HOME/network/admin directory of the client. My tnsnames.ora file looks like this:

D:\oracle\product\10.2.0\NETWORK\ADMIN>type tnsnames.ora
# tnsnames.ora Network Configuration File: D:\oracle\product\10.2.0\network\admin\tnsnames.ora
# Generated by Oracle configuration tools.

LX10R2.US =
(DESCRIPTION =
(ADDRESS_LIST=
(LOAD_BALANCE=on)
(ADDRESS = (PROTOCOL = TCP)(HOST = jake)(PORT = 1666))
(ADDRESS = (PROTOCOL = TCP)(HOST = jake)(PORT = 2666))
)
(CONNECT_DATA = (SID = lx10r2))
)

Here, the database alias is "lx10r2.us". Normally, when you specify multiple address lines for an alias, Oracle will attempt the first and if that fails will attempt the second. This might actually work for the poster, but would still pound port 1666 until it couldn't handle any connections and THEN try port 2666. The key to having a somewhat even distribution over the two listeners is by using the (LOAD_BALANCE=ON) parameter.

Just to test the theory, we create a small batch file on the client machine that connects and disconnects in an infinite loop. The batch file looks like this:

C:\temp>more infinite.bat
:start
sqlplus jeffh/jeffh@lx10r2.us @disconnect
goto :start

C:\temp>more disconnect.sql
exit

Then, we open up multiple command prompt windows and start pounding away. You can see the listener.log file keeps growing and both listeners are accepting approximately the same number of connections:

[oracle@jake log]$ wc -l *.log; sleep 120; wc -l *.log
206 lsnr1666.log
199 lsnr2666.log
405 total
528 lsnr1666.log
582 lsnr2666.log
1110 total

Nice. About three hundred connections per minute. Not bad for an 802.11b connection to a 733Mhz Linux box connected to a 100Mbps router. Will this solve the poster's problem? I don't know. I do know this is how you can setup multiple listeners, though.

Friday, October 14, 2005

Using MySQL more frequently

As I use MySQL more frequently, I really get perturbed when I get back on to Oracle and can't do:

SELECT someFunctionName();

Thursday, October 13, 2005

Thanks Howard, Part II

I use statcounter to keep track of my blog's visitors. No, I don't use it for ads or anything like that, but still, I like to know who is reading the blog and how they got here.

A couple of weeks ago, Howard J. Rogers added my blog to the links section of The Dizwell Blog and I started getting a lot of referring links. Sometimes when I post an entry about MySQL, I'll get a spike from Planet MySQL and other related sites. Over the last few days, The Dizwell Blog has taken the top spot and I'm starting to get referrals from other sites I never knew about. In fact, I've found a couple blogs that are interesting that I'll be modifying my own links section in the near future to replace some of the blogs that don't get updated on a regular basis.

So, thanks to Howard and others to helping me get recognized and thanks to the readers. Keep on blogging.

This is the second time HJR has helped me out in the last couple weeks.

Tuesday, October 11, 2005

Wicked ORA-27054, Part I

We're doing some testing with RMAN and 10.2.0.1 on Linux. Our standard backup strategy is to backup to NFS mounted disk and backup to tape at a later time. With 9.2 I could mount the NFS filesystems without any particular options and RMAN would run just fine.

On 10.2.0.1, we setup the backup and immediately got an error (ORA-27054: NFS file system where the file is created or resides is not mounted with correct options). So we submit a TAR and find out that 10.2 requires NFS filesystems to be mounted with the following options:

rsize=32768,wsize=32768,hard,noac

The backup works now, except it takes 1 hour 9 minutes to backup a 2G database. We indicate this in the TAR and the analyst basically says "new problem, new tar". So we create a new TAR for the performance issues, but I post a followup on the existing TAR:


Me: Is there any flag or something that we can change to turn off the checking that results in the ORA-27054?
OCS: I have seen the following being used on different problems (not related to RMAN), sometimes it works, sometimes it doesn't, I would not be able to explain why since it is not on my skills, also this parameter is not documented so I would not know what other effects could cause.

Set init.ora parameter:
_filesystemio_options=directio

You can also try:
_filesystemio_options=none

Hope this helps.

Well, at least he's being honest about it. Of course, we all know that filesystemio_options is not hidden in 10.2.

Me: This is a production system. We'd rather not "try" something if we don't know if it will solve our problem or not. Since you say you're not qualified, how do we get to someone who can tell us the answer?

OCS: Create a new tar.


OK, I get it. You're just trying to close as many TARs as possible. Glad to see my support dollars "at work".

So we pursue our "performance" problem with the other TAR and reference the first TAR. The analyst suggests we contact the vendor of our NAS to find out what they suggest. We explain this is plain NFS and it doesn't really have a vendor. They suggest getting an strace on the rman process. Now we're getting somewhere.

While they are looking at the TAR, one of my DBAs does some more testing. He backs up my 2G database to local disk in 4 minutes. He then copies the backup pieces to the NFS mounted disk mounted with the options specified by Oracle Support. 1 hour 9 minutes. Ah ha! Poor performance even with plain old cp.

I know what Oracle Support is going to say. I'd probably say it myself. "The fact that plain old cp is slow tells me your NFS is setup wrong." And I wouldn't disagree. The conundrum is that these are the options Oracle told us to use...

to be continued...solution

Friday, October 07, 2005

Lions and zookeepers

A friend from geekster.com pointed out this article about MySQL and Oracle.

What I think about MySQL

After my series on MySQL to an Oracle DBA (here, here, here, here, and here), a lot of people have asked what I think about MySQL.

I'm not really qualified to compare the two. I think I know Oracle much better than I know MySQL, so the comparison would be jaded. Some people claim that MySQL is much easier to setup and maintain than Oracle. I'm not completely convinced of that. Each has their own set of hundreds of parameters that can be tweaked. Having installed MySQL from source a couple times, I'd actually say it's a little harder to setup in certain circumstances. Not hard, just harder.

I'm very intrigued by MySQL's backup methods. At first glance mysqldump looks more like Oracle's export program than a backup tool. An Oracle DBA would scoff this off as single point in time snapshot of the data. Of course, we Oracle DBA's know you can't import and then apply archived redo logs, but imagine a scenario where you could. Appearantly MySQL has the ablity to import and re-apply the bin log (kind of like the redo log). This concept was tossed about in the class and I'm anxious about trying it out.

I'm a little concerned about connection scalability with MySQL. The MySQL server is bound to one port. In the coming months I'll be stress testing high frequency connections to see of they scale.

I think Oracle gives you much more information about the health of the database through views than MySQL does. With Oracle, I can query v$this, x$that, and dba_whatever to tell me certain things about how the database is performing. In addition, I can write tools using these queries to automate my job and alert me to when certain conditions arise. MySQL has a lot of SHOW commands, but it's difficult to get this information in an automated fashion without some pipes, grep, and awk. Maybe I just don't know enough about it yet.

One thing I really like about MySQL is the concept of a "slow log". Here, queries that run longer than a specified threshold are logged to a "slow log" that can be investigated later. My developers will hate me. I wonder if it's to obnoxious to set my threshold at 60 seconds. Hmmm...

We'll definitely be using MySQL. It will start off with backoffice apps and progress to bigger apps. I've got half a mind to port my Oracle monitoring app to MySQL just for kicks. I'll be updating this blog as I find interesting things about MySQL.

Thursday, October 06, 2005

Sysadmin at work

For you sysadmin types out there, this is not such a big accomplishment, but for me it is. I salvaged a drive from one of my older systems that I was throwing out. I decided to add it to my Linux box because I wanted to separate my home directories from my OS files.

This particular drive was a 800M IDE drive that I slapped into the box and the machine booted right away. Now, I'm not a hardware guy, so the fact that this worked the first time was pretty amazing to me.

Next, I knew I had to partition the disk and cook a filesystem, but didn't know the Linux commands to do it. I went to the Red Hat docs and managed to partition my disk and cook an ext3 filesystem. On Solaris, I'd just put an entry in /etc/vfstab and mount the filesystem. But there's no vfstab file on Linux. I did some more reading and found I need to put my entry in /etc/fstab. Although the format of the fstab file is different then I'm used to, I put the entries in like I think they should have been and tried to mount. Still can't mount.

Finally, I realize that my new disk has to have a label. I go through the same process except put a label on the disk this time. I use the new syntax in the /etc/fstab file and finally the filesystem mounts. I reboot the box and the filesystem mounts automatically. Basically a two hour process for something my sysadmins could have done in about 5 minutes. The joy of learning.

Wednesday, October 05, 2005

New Toy

Our old VCR finally died a couple days ago. We've had that thing for about 7 years now and use it pretty extensively to tape shows and watch them later. The quality of the recordings has gotten pretty poor over the last 6 months or so. In fact, we made the decision to junk it only when the top half of the picture didn't record and we had to have to volume all the way up to hear it.

We went through the process of looking at new VCRs, but decided a DVD recorder might make more sense. We looked at Tivo, but didn't want to be saddled with the additional cost. So we asked my sister-in-law; a buyer in the consumer electronics field. She suggested we look at a DVD recorder with a hard drive. (Hard drive, I'm into that!) We could record up to 100 hours on the drive and burn to DVD when we needed to. Our particular DVD recorder has on-screen listings that get updated automatically. I am ashamed to say that my DVD recorder has more disk space than my Linux box.

It was really a snap to hook up to the TV. After 24 hours, the listings downloaded to the unit and we setup all our shows to record. I'll see tonight if American Chopper recorded sucessfully Monday. Now if I can figure out how to NFS mount that bad boy to my Linux box, I'd be all set...

Tuesday, October 04, 2005

Problem Solved

Thanks to a tip by HJR, my .pdf problems have been solved. I've downloaded Foxit Reader and installed it on all my Windoz machines to take the place of Acrobat Reader 7.0. All my .pdf files now display correctly and print correctly. Thanks Howard.

Friday, September 30, 2005

Book Bonanza







I went a little crazy at Amazon.com last weekend.

I ordered these books Saturday and they all came in today. Where to start?

Thursday, September 29, 2005

How many?

If you've ever seen...


There are now 76772 jobs remaining (current phase=A31):
12 running, 14235 ready to run and 62525 waiting.

... you know you're in for a looooong weekend.

Wednesday, September 28, 2005

My Last Straw

I've had it with Adobe Acrobat Reader 7.0. Whenever I encounter a .pdf file that has both graphics and text on it, I can't seem to print it. No matter what I try to do, I just can't print the whole thing.

I recently upgraded to Acrobat Reader 7.0 on all my machines. My wife's computer is a W2K box that has the Brother HL-1440 printer attached to it. My laptop runs XP and I can normally print to the Brother with no problems over the network. My main box is a RH9 box that also prints to the same printer via the network.

I received an invoice from MySQL AB for the training I attended last week. I viewed it fine with Acrobat Reader 7.0 and then clicked "Print". Only the logos and lines on the document came out. So I tried a couple of the different "Comments and Forms" options in the Print dialog. Same thing. I figured my printer drivers might be out of date, so I updated them and tried again. Boxes and graphics only. Then I un-installed and re-installed Reader 7.0 with the most current updates. Same thing.

Next, I brought the document up on my laptop which also has Acrobat Reader 7.0 and tried printing to the network printer. Same deal. Then I tried printing the same file from my Linux box with Reader 7.0 with exactly the same result. Just for kicks, I brought up the file in xpdf and printed it, and voila, it prints fine. That ruled out the printer.

I thought maybe it was just the document I was trying to print. So I created a document with lines, graphics and text in Open Office and saved it as a .pdf. I tried it on all three computers; Reader 7.0 couldn't print, xpdf could.

Maybe it is the printer after all. I brought the same two documents to work and tried to print on an HP 8150. Still only those damn boxes and lines. Then I figured I'll downgrade to Reader 6, but I couldn't find it on Adobe's site.

My next step is seeing if there is a xpdf version for Windows.

Friday, September 23, 2005

New York Reflections


I guess you could call me a frequent visitor to New York. I’m in the city at least once a month for a user group meeting, training, or just as a plain old tourist. This week I’ve been one of the “commuter bots” that wake up at ungodly times, rush to the train station with their Starbucks Venti Moca something or another Latte and promptly go back to sleep for 72 minutes. I don’t know how these people do it every day, I couldn’t.

The training facility for this particular course is in lower Manhattan. I’m pretty comfortable with the subway system in New York, so I had a good idea which train to catch and that walking 3 or 4 blocks wouldn’t kill me. While walking around at lunch time one day, I strolled through Battery Park and came upon “The Sphere”. The Sphere was located at the World Trade Center four years ago when evil came to my backyard. This giant, scarred orb remains in this now vibrant community as a reminder that although time marches on, those who came before us will never be forgotten.

Next to “The Sphere” were impromptu tributes to those that died on that fateful day. A boy scout troop from somewhere in the Midwest had left a plaque. Somebody left a flower. There was a picture of somebody that sacrificed their life on that day to save others. The whole experience was overwhelming, more so, in my opinion, than seeing the empty spot where the WTC stood.

Walking the streets of New York on the weekend is different than during business hours. On the weekend, people are casually walking along drinking their $6 cup of coffee chatting about the weeks events and letting their dogs sniff every hydrant along the way. Rush hour turns these same people into machines silently screaming "GET OUT OF MY WAY!!!" with their eyes and expressionless face. On the weekend you can look lost and some Golden Retreiver walker will ask you where you are going and suggest you go up 41st Street instead of 42nd Street to avoid the crowds. On the weekday you have to ask three people which way to go and you'll be lucky if you get a point in the right direction. It's not that they're rude, they just have some place to be and the 5 train was delayed and they had to change to a local train at 14th street and ...

There's a lot of great things about New York, but I'm sure it's tough living there. If I could live and work North of City Hall, I think getting around would be pretty easy. You see, the Streets go East/West and the Avenues go North/South. The street numbers go up as you go North, the avenue numbers go up as you go West. Usually within a block you can tell if you are going in the wrong direction or not. Lower Manhattan is a differnt story. It's like another political party suddenly took control of the Street Naming Division and decided to start giving streets actual names instead of numbers. And forget about any grid of North/South and East/West.

I don't know if I am cut out for living in Manhattan. Sure it would be fun. For a while. I think I'd miss cutting the grass.

Thursday, September 22, 2005

MySQL to an Oracle DBA, Part IV


Today is where the rubber meets the road in the Oracle/MySQL comparison; locking and transactions. At the end, I'll give you a little Oracle fun.

As I said yesterday, the different storage engines may or may not support transactions. MyISAM tables do not support transactions while InnoDB tables do. First, I create two tables; one as InnoDB, one as MyISAM:

system@localhost:world> create table city_myisam
engine = myisam as select * from city;
Query OK, 4063 rows affected (0.78 sec)
Records: 4063 Duplicates: 0 Warnings: 0

system@localhost:world> create table city_innodb
engine = innodb as select * from city;
Query OK, 4063 rows affected (0.53 sec)
Records: 4063 Duplicates: 0 Warnings: 0

Next, I set autocommit off.

system@localhost:world> set autocommit = 0;
Query OK, 0 rows affected (0.06 sec)


Now I'll delete some rows from the tables in a transaction and see what happens:

system@localhost:world> begin;
Query OK, 0 rows affected (0.00 sec)

system@localhost:world> delete from city_myisam
where country = 'FRA';
Query OK, 40 rows affected (0.11 sec)

system@localhost:world> delete from city_innodb
where country = 'FRA';
Query OK, 40 rows affected (0.09 sec)

system@localhost:world> rollback;
Query OK, 0 rows affected, 1 warning (0.05 sec)

system@localhost:world> show warnings;
+---------+------+---------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------+
| Warning | 1196 | Some non-transactional changed tables couldn't be rolled back |
+---------+------+---------------------------------------------------------------+
1 row in set (0.00 sec)

system@localhost:world> select count(*) from city_innodb
where country = 'FRA';
+----------+
| count(*) |
+----------+
| 40 |
+----------+
1 row in set (0.08 sec)

system@localhost:world> select count(*) from city_myisam
where country = 'FRA';
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.27 sec)

Aha, MySQL gives me a warning, but does it anyway. Note to self: no money transactions in MyISAM tables.

The next interesting thing was locking. The MyISAM storage engine only uses table level locks. When you update a row in a MyISAM table, you have to get an exclusive table level lock before you can update. These table level locks severly limit MyISAM scalability in a write intensive envrionment. The InnoDB engine, on the other hand, has row level locks, like Oracle.

The biggest Oracle misstatement today: Oracle will escalate to a table level lock when you delete more than 25% of the rows. Nope. In fact, I have a table with 5000 rows where the pk ranges from 1 to 5000:

SQL> l
1 select count(*),
2 min(x),
3 max(x)
4* from xyz
SQL> /

COUNT(*) MIN(X) MAX(X)
---------- ---------- ----------
5000 1 5000


In one session, I delete the first 4999 rows:

SQL> delete from xyz where x < 5000;

4999 rows deleted.


No problem. Now, from a different session I try to delete the row where x=4000.


SQL> delete from xyz where x=4000;


And, as expected, we are waiting on a lock from the first session:


SQL> l
1 select waiting_Session wt, holding_session ho, lock_type lt,
2 mode_held, mode_requested, lock_id1, lock_id2
3* from dba_waiters
SQL> /

WT HO LT MODE_HELD MODE_REQUE LOCK_ID1 LOCK_ID2
---- ---- ------------ ---------- ---------- -------- --------
24 25 Transaction Exclusive Exclusive 262148 163


But, if we try to delete the row that is not locked, it should go through with no issues.


SQL> delete from xyz where x=5000;

1 row deleted.

No problem, with no locks:

SQL> select waiting_Session wt, holding_session ho, lock_type lt,
2 mode_held, mode_requested, lock_id1, lock_id2
3 from dba_waiters
4 /

no rows selected

Wednesday, September 21, 2005

MySQL to an Oracle DBA, Part III

Today is where we started digging our DBA teeth into MySQL. As with any database, the first thing you must do is install the software. MySQL comes in a couple different flavors depending on the platform and how you intend to use it. For example, on Linux you can install via RPM's, precompiled binaries, or source. On Windows you can install via a Windoz Installer, precompiled binaries, or source. While the quickest way to install is via RPMs or Windows Installer, you can build your mysql software tailored specifically for your hardware and the options you want to use. I chose to install from Windows Installer on Windows XP so I could work with my own laptop.

Once installed, you have to go through the configuration process. A lot of the configuration process is similar to Oracle; data goes here, logfiles (transaction logs) go on a seperate filesystem, the message logs go another place, etc. Similar to Oracle, you setup memory parameters and other features you want installed in the instance.

One interesting feature of MySQL is that you can store your tables using different "Storage Engines". A storage engine is basically the method used to access your data. You can use any number of storage engines in your database. The main storage engines are MyISAM, InnoDB, Memory, Merge, Berkley, and NDBCluster.

Why would you want to choose your storage engine? You can assign the storage engine based on what type of activity the table will have and the features you need.








Storage EngineAdvantagesDisadvantage
MyISAMExtremely fast for QueriesCan't use transactions with, Concurrent INSERTs don't scale because the entire table is locked,Dirty Reads
InnoDBCan use transactions, multi-versioning read consistency, DML scales wellQueries slower than MyISAM
MemoryTables stored directly in memory. Access is really fast. Best for TEMP type tablesTables stored directly in memory. DB Goes down, your data is toast.
MergeCan present two identical tables as one table. Kind of like a materialized view, kind of like a partitioned tableMust be MyISAM tables
BerkleyOffers transactions.Older technology
NDBClusterSupports transactions and clusters, highly scalableNot widely used.
FederatedCan store data on a seperate serveryour I/O is limited by bandwidth


Last, but not least, we talked about security. We went through the same things you would do to secure an Oracle database; protect the root OS user, protect the mysql "root" (or SYS) user, use strong passwords, protect remote root logins, etc. One interesting concept is that MySQL users are identified not only by a username, but by the host they can login from. For example, jeffh@localhost is a totally different identity than jeffh@webserver. You grant permissions to both user depending on how you want to want them to access your data. If you want the root user to only login on the server itself, you only create root@localhost. This lets you setup access rules such as "When user jeffh is logged into the database on an internal domain, he can INSERT, UPDATE, DELETE, SELECT from my tables. When user jeffh is logged in from the VPN, he can only SELECT from my tables". That's kind of cool.

Two side notes: I leared about google sets and gvim (vi for windows).

Tuesday, September 20, 2005

MySQL to an Oracle DBA, Part II

Found out some things that you need to be aware of when converting from Oracle to MySQL. Let me create a table and show you some examples.

mysql> create table number_stuff (
-> description varchar(20) not null,
-> ti tinyint,
-> ival integer,
-> fl float,
-> dc decimal(15,5));
Query OK, 0 rows affected (0.13 sec)


This is kind of cool. You can insert multiple values in one shot.

mysql> insert into number_stuff values
-> ('123',123, 123, 123, 123),
-> ('384',384, 384, 384, 384),
-> ('12.5', 12.5, 12.5, 12.5, 12.5),
-> ('13.5', 13.5, 13.5, 13.5, 13.5),
-> ('14.5', 14.5, 14.5, 14.5, 14.5),
-> ('12345.67890',12345.67890, 12345.67890, 12345.67890, 12345.67890);
Query OK, 6 rows affected, 2 warnings (1.78 sec)
Records: 6 Duplicates: 0 Warnings: 2

mysql> show warnings
-> ;
+---------+------+------------------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------------------+
| Warning | 1264 | Out of range value adjusted for column 'ti' at row 2 |
| Warning | 1264 | Out of range value adjusted for column 'ti' at row 6 |
+---------+------+------------------------------------------------------+
2 rows in set (0.00 sec)


Fair enough. We tried to insert values outside the bounds (-127 to 127) for TINYINT, and it makes sense that they’d fail. So let’s see what we got here:

mysql> select * from number_Stuff;
+-------------+------+-------+---------+-------------+
| description | ti | ival | fl | dc |
+-------------+------+-------+---------+-------------+
| 123 | 123 | 123 | 123 | 123.00000 |
| 384 | 127 | 384 | 384 | 384.00000 |
| 12.5 | 13 | 13 | 12.5 | 12.50000 |
| 13.5 | 14 | 14 | 13.5 | 13.50000 |
| 14.5 | 15 | 15 | 14.5 | 14.50000 |
| 12345.67890 | 127 | 12346 | 12345.7 | 12345.67890 |
+-------------+------+-------+---------+-------------+
6 rows in set (0.00 sec)


Our first row looks like it went in just fine.

The second row is what makes the DBA in me a little nervous. We tried to insert the integer value 384 into a TINYINT column and MySQL correctly gave us a warning. However, it then modified our data and put a 127 (the maximum value) into the TINYINT field.

Rows 3, 4, and 5 appear to have gone in without a hitch. But wait, it looks like MySQL insert the rounded number into the columns that contained integers. Hold on, you’re being paranoid, Oracle does the same thing:

SQL> create table xyz (x integer);

Table created.

SQL> insert into xyz (x) values (12.5);

1 row created.

SQL> commit;

Commit complete.

SQL> select * from xyz;

X
----------
13


But what am I trying to show you with these numbers? Just that FLOAT and NUMBER round differently:

mysql> select description, round(fl), round(dc) from number_stuf
-> where description in ('12.5','13.5', '14.5')
-> ;
+-------------+-----------+-----------+
| description | round(fl) | round(dc) |
+-------------+-----------+-----------+
| 12.5 | 12 | 13 |
| 13.5 | 13 | 14 |
| 14.5 | 14 | 15 |
+-------------+-----------+-----------+
3 rows in set (0.00 sec)


Last, but not least, lets look at real numbers.


mysql> select description, fl, dc
-> from number_stuff
-> where description = '12345.67890';
+-------------+---------+-------------+
| description | fl | dc |
+-------------+---------+-------------+
| 12345.67890 | 12345.7 | 12345.67890 |
+-------------+---------+-------------+
1 row in set (0.00 sec)


Is that fl a display issue or a storage issue? Lets just use the TRUNCATE function to see what MySQL is really storing:

mysql> select description, fl, truncate(fl, 25) trunc_fl, dc
-> from number_stuff
-> where description = '12345.67890';
+-------------+---------+---------------------------------+-------------+
| description | fl | trunc_fl | dc |
+-------------+---------+---------------------------------+-------------+
| 12345.67890 | 12345.7 | 12345.6787109375000000000000000 | 12345.67890 |
+-------------+---------+---------------------------------+-------------+
1 row in set (0.00 sec)


Yup, that’s really what MySQL is storing, a wrong value. But does it really? Lets multiply by 10000 to see:

mysql> select description, fl, fl * 10000 big_fl, dc
-> from number_stuff
-> where description = '12345.67890';
+-------------+---------+-----------------+-------------+
| description | fl | big_fl | dc |
+-------------+---------+-----------------+-------------+
| 12345.67890 | 12345.7 | 123456787.10938 | 12345.67890 |
+-------------+---------+-----------------+-------------+
1 row in set (0.00 sec)


Sure enough, that’s the value being stored.

Note to self: Don’t use FLOAT to store money or fractional shares.

As we were going through data types, I couldn’t understand why there were all these different INTEGER subtypes. The reason is that MySQL will take the entire 4 bytes in a 4 byte INTEGER even though it might not need it. For example, you create the table below:

CREATE TABLE xyz (
id BIGINT);

BIGINT is a data type that is an 8 byte integer. You intend to fill xyz.id with sequential numbers starting at 1. When you insert the value 1 into xyz.id, you have taken 8 bytes. This is different than Oracle in that the number data types are variable length. Is this good or bad, depends. It’s just something to be aware of.

Monday, September 19, 2005

MySQL to an Oracle DBA, Part I

As you may remember, I am at MySQL training this week. The first day was introductory material which included installing MySQL and query basics. Because we didn’t breeze through the Query portion, it gave me plenty of time to experiment.


SQL> select count(*) from country;

COUNT(*)
----------
239


mysql> select count(*) from country;
+----------+
| count(*) |
+----------+
| 239 |
+----------+
1 row in set (0.00 sec)


OK, that’s cool, that’s what I expected. Let’s do a simple aggregate function:


SQL> select continent, sum(population) TotalPop
2 from country
3 group by continent
4 order by continent
5 ;

CONTINENT TOTALPOP
------------------------------ ----------
Africa 784475000
Antarctica 0
Asia 3705025700
Europe 730074600
North America 482993000
Oceania 30401150
South America 345780000

7 rows selected.


OK, that’s what we expected. Let’s try the same query in MySQL:


mysql> select continent, sum(population) TotalPop
-> from country
-> group by continent
-> order by continent
-> ;
+---------------+------------+
| continent | TotalPop |
+---------------+------------+
| Asia | 3705025700 |
| Europe | 730074600 |
| North America | 482993000 |
| Africa | 784475000 |
| Oceania | 30401150 |
| Antarctica | 0 |
| South America | 345780000 |
+---------------+------------+
7 rows in set (0.00 sec)


Hmm, that’s interesting. Maybe it has something to do with default sorting order or something. I’ll have to ask Tobias (my Instructor) about that in the morning. Let’s try sorting by a number field:


SQL> select continent, sum(population) totalpop
2 from country
3 group by continent
4 order by totalpop desc
5 ;

CONTINENT TOTALPOP
------------------------------ ----------
Asia 3705025700
Africa 784475000
Europe 730074600
North America 482993000
South America 345780000
Oceania 30401150
Antarctica 0

7 rows selected.

mysql> select continent, sum(population) totalpop
-> from country
-> group by continent
-> order by totalpop desc
-> ;
+---------------+------------+
| continent | totalpop |
+---------------+------------+
| Asia | 3705025700 |
| Africa | 784475000 |
| Europe | 730074600 |
| North America | 482993000 |
| South America | 345780000 |
| Oceania | 30401150 |
| Antarctica | 0 |
+---------------+------------+
7 rows in set (0.02 sec)


Yeah, that’s we expected. Let’s try another query:

mysql> select continent, population totalpop
-> from country
-> group by continent
-> order by totalpop desc
-> ;
+---------------+----------+
| continent | totalpop |
+---------------+----------+
| South America | 37032000 |
| Africa | 31471000 |
| Asia | 22720000 |
| Europe | 15864000 |
| North America | 217000 |
| Oceania | 68000 |
| Antarctica | 0 |
+---------------+----------+
7 rows in set (0.00 sec)


Hmm, what’s weird about this query (assuming the data is correct)? Let’s try it in Oracle:

SQL> select continent, population totalpop
2 from country
3 group by continent
4 order by totalpop desc
5 ;
select continent, population totalpop
*
ERROR at line 1:
ORA-00979: not a GROUP BY expression


That’s right, our old friend didn’t even run the query for us.

Another interesting tidbit was with the DISTINCT Operator. In Oracle, the optimizer may determine DISTINCT values by sorting, whereas MySQL can use one of two algorithms. For example:

SQL> select distinct continent from country;

CONTINENT
------------------------------
Africa
Antarctica
Asia
Europe
North America
Oceania
South America

7 rows selected.


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=6 Card=239 Bytes=7
648)

1 0 SORT (UNIQUE) (Cost=6 Card=239 Bytes=7648)
2 1 TABLE ACCESS (FULL) OF 'COUNTRY' (TABLE) (Cost=5 Card=23
9 Bytes=7648)

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
16 consistent gets
0 physical reads
0 redo size
665 bytes sent via SQL*Net to client
507 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
7 rows processed

mysql> select distinct continent from country;
+---------------+
| continent |
+---------------+
| Asia |
| Europe |
| North America |
| Africa |
| Oceania |
| South America |
| Antarctica |
+---------------+
7 rows in set (0.00 sec)


BTW, another participant in the class suggested that Oracle always sends back the results of DISTINCT in sorted order. I didn’t think so, but wasn’t able to disprove it. Maybe I learned something new about Oracle today.

Edit: 09/19/2005 23:33 -
Tom correctly points out in the comments that Oracle doesn't always use a sort to determine duplicates. If I had that looked on metalink at doc 655027.999 or 249919.999 I would have confirmed my suspicians about always using ORDER BY. Bang head on desk, Bang head on desk, ...

Saturday, September 17, 2005

We're doing MySQL

My manager called me into his office the other day and explained how we were going to put our first MySQL database up. It's a relatively simple app with 99% read activity and some batch loads in the night. This wasn't a total surprise as I did some investigation into MySQL about a year ago and determined that for the right types of application it would be adequate.

We've got some of the basics up in development already, but I feel like I'm a newbie all over again. When I can't figure something out, I say "That's how it works in Oracle" and need to step outside the box to figure it out.

This week is training in NYC. Five days of the basics will hopefully get me up to speed where I can be relatively proficient. Expect some blog entries next week about the differences between MySQL and Oracle.

Thursday, September 15, 2005

Top N

A Frequently Asked Question on many Oracle related forums is “How can I get the first/last N rows in my table?” Sometimes that’s not an easy question to answer. I always ask the poster what they mean by “first”. Some people mean the order the records were inserted, some people mean the top-N rows. I’ve found it’s always easier to get the poster to explain what they are trying to do instead of guessing.

First/Last – in an ordered set
This one is easy. You take advantage of inline views and Oracle’s pseudocolumn ROWNUM. People usually get tripped up when they use ROWNUM because while ROWNUM is relevant in all queries, in this type of query it only makes sense when coupled with an ORDER BY.

For example:

SQL> select * from xyz;

X Y Z
---------- ---------- -------------------
127 1 09/16/2005 14:46:50
148 22 09/17/2005 14:48:42
149 23 09/18/2005 14:48:42
150 24 09/19/2005 14:48:42
131 5 09/20/2005 14:46:50
151 25 09/20/2005 14:48:42
133 7 09/22/2005 14:46:50
152 26 09/21/2005 14:48:42
153 27 09/22/2005 14:48:42
154 28 09/23/2005 14:48:42
137 11 09/16/2005 14:46:50
155 29 09/24/2005 14:48:42
139 13 09/18/2005 14:46:50
156 30 09/15/2005 14:48:42
143 17 09/22/2005 14:46:50
145 19 09/24/2005 14:46:50
147 21 09/16/2005 14:48:42

17 rows selected.

SQL> select rownum, x, y, z from xyz;

ROWNUM X Y Z
---------- ---------- ---------- -------------------
1 127 1 09/16/2005 14:46:50
2 148 22 09/17/2005 14:48:42
3 149 23 09/18/2005 14:48:42
4 150 24 09/19/2005 14:48:42
5 131 5 09/20/2005 14:46:50
6 151 25 09/20/2005 14:48:42
7 133 7 09/22/2005 14:46:50
8 152 26 09/21/2005 14:48:42
9 153 27 09/22/2005 14:48:42
10 154 28 09/23/2005 14:48:42
11 137 11 09/16/2005 14:46:50
12 155 29 09/24/2005 14:48:42
13 139 13 09/18/2005 14:46:50
14 156 30 09/15/2005 14:48:42
15 143 17 09/22/2005 14:46:50
16 145 19 09/24/2005 14:46:50
17 147 21 09/16/2005 14:48:42


Here, ROWNUM does exactly what it’s supposed to do. It gives you a sequential number according to how the rows were pulled out of the table. There is obviously no logical order (to the human eye, anyway), but that’s how the rows come out. If you restrict by ROWNUM, you will certainly get a result, but probably not what you expect:

SQL> select * from xyz
2 where rownum < 6
3 /

X Y Z
---------- ---------- -------------------
127 1 09/16/2005 14:46:50
148 22 09/17/2005 14:48:42
149 23 09/18/2005 14:48:42
150 24 09/19/2005 14:48:42
131 5 09/20/2005 14:46:50


So what to do? Just put an ORDER BY in?


SQL> select * from xyz
2 where rownum < 6
3 order by y
4 /

X Y Z
---------- ---------- -------------------
127 1 09/16/2005 14:46:50
131 5 09/20/2005 14:46:50
148 22 09/17/2005 14:48:42
149 23 09/18/2005 14:48:42
150 24 09/19/2005 14:48:42


Nope. But we’re getting closer. You have to use your ordered query as a subquery and then apply the filter.

SQL> select * from (
2 select * from xyz
3 order by y
4 )
5 where rownum < 6
6 /

X Y Z
---------- ---------- -------------------
127 1 09/16/2005 14:46:50
131 5 09/20/2005 14:46:50
133 7 09/22/2005 14:46:50
137 11 09/16/2005 14:46:50
139 13 09/18/2005 14:46:50


Bingo. That’s what we wanted. Now suppose we wanted a “window” from 6 to 10:


SQL> select o.x, o.y, o.z from (
2 select rownum r, i.x, i.y, i.z from (
3 select x, y, z from xyz
4 order by y ) i
5 where rownum < 11 )o
6 where o.r > 5
7 /

X Y Z
---------- ---------- -------------------
143 17 09/22/2005 14:46:50
145 19 09/24/2005 14:46:50
147 21 09/16/2005 14:48:42
148 22 09/17/2005 14:48:42
149 23 09/18/2005 14:48:42


First/Last – in insertion order
Since there is no inherent way for you to figure out the order the rows were put into a table, this one is a little trickier. The only way you can positively indicate the order the rows were inserted into the table is if you explicitly mark each record. Sometimes this may be a “DATE_INSERTED” field or it may be some other field that indicates order. In my example, I have created a BEFORE INSERT trigger to populate the Primary Key (x) with a value from a sequence:


create trigger xyz_bi
before insert
on xyz
for each row
declare
pkval number;

begin
select xyz_id.nextval into pkval from dual;

:new.x := pkval;
end;


Therefore, I know my rows were inserted in the order according to X. I can then use my PK value to find out the last 10 rows inserted by:

SQL> select * from (
2 select * from xyz
3 order by x desc
4 )
5 where rownum < 11
6 /

X Y Z
---------- ---------- -------------------
156 30 09/15/2005 14:48:42
155 29 09/24/2005 14:48:42
154 28 09/23/2005 14:48:42
153 27 09/22/2005 14:48:42
152 26 09/21/2005 14:48:42
151 25 09/20/2005 14:48:42
150 24 09/19/2005 14:48:42
149 23 09/18/2005 14:48:42
148 22 09/17/2005 14:48:42
147 21 09/16/2005 14:48:42

10 rows selected.

Wednesday, September 14, 2005

Recruiting Jack of all Technology

I got a cold call from a recruiter this morning. I was feeling rather playful, so I persued the conversation.

Recruiter: Hi, this is MaryJo Recruiter from XYZ firm. Do you have a couple of minutes to talk to me?
Me: Um, OK.

R: I am looking for a combination Database Administrator/Database Developer/Business Analyst for a financial company.
Me: Let me stop you right there. What kind of money are we talking?

I always like to ask this question to see what the jobs out there are paying.

R: Well, they didn't specify a range. I asked if I found somebody at 80K would they want to look at them and the client said yes.
Me: Oh, so they're really looking for 65K-75K.
R: Probably.
Me: What kind of skills?
R: They want 5 years of Oracle DBA, 5 years using VB and/or MS Access, and business analyst background.
Me: That's a pretty strange combination.
R: The position is not defined very well.
Me: I see.
R: It's a really good company. Would you be interested?
Me: You'd have to triple the money.

I always like to throw out some factor like double or triple to see what they say.

R: Oh....I'll pay referral fees.
Me: I see. I know several people in the industry and know of a couple looking right now. Tell me more about the position.
R: This position would report to the CIO. They would interface with the users to define the project and then implement the project with VB and Access.
Me: OK, so where does Oracle come into the picture?
R: Well, they're thinking they might have a lot of data and they will need Oracle.
Me: Oh. I think you will have a very hard time filling this position. There's not that many BA's that know how to program in VB/Access and setup an Oracle Database.
R: Do you know of anyone that might fit this position? I pay referral fees.
Me: I have a couple people in mind, but they would be more on the technical side.
R: Great! Can I send you my contact information?

So if anybody wants to do VB/Access/Oracle DBA/Business Analyst for $70K in Connecticut, drop me a line.

Monday, September 12, 2005

Goodbye DBAs

Forrester Research has jumped on the "zero administration" database bandwagon. Looks like I'll be retiring in 2009. Woo hoo!!!

Oracle WTF

Stumbled upon a funny blog by Willam Robertson, Oracle WTF. It's modled after The Daily WTF, but with an Oracle slant. Check it out.

Friday, September 09, 2005

Keep it in your pants

You know that gap between the elevator and the floor you are on? Ever wonder what would happen if you dropped something down there? I have had that very thought on more than one occasion.

I had something to do after work today, and I was already late when I packed up and hit the elevator button. My keys were in my hand and I was fiddling with them when the elevator door opened. As I stepped into the elevator, my keys dropped from my hand; keys on the floor and keyless remote dangling over “the gap”. In what seemed like slow motion, I bent down to pick them and just then the remote won out and they slipped down the gap.

All I could muster was “Oh Shit” as they banged their way down to some unknown place.

I immediately went to the security office hoping they could do something. The security guard paged building maintenance and Darrel says “no problem”. We take the elevator to the bottom floor, send it back up, and he uses his special key to get in the elevator shaft. We look around, but there’s no keys down there. About $3 in change, countless gum and candy wrappers, but no keys. Darrel says “Are you sure you were in this elevator?” We repeat the same procedure floor by floor thinking that maybe they got hung up on somewhere in the shaft. I wasn’t worried about the keys, because the maintenance guy said the elevator people would come in Monday and do a better search. If we can’t find them, I’ll have to call my security officer and let him know I lost my keys. After hours. Then another thought hits me; how do I get home?

As we’re on our pursuit, Darrel says somebody drops something down the shaft about once a month, which surprises me. He suggests we go back down to the basement and look around again. We look in the same shaft and still no dice. He suggests we take a peek in the other elevator shaft with the possibility that the keys bounced around in the shaft. Sure enough, there they were. He smiles at me and says “You were in this one, weren’t you?”

The only problem was my keyless entry remote didn’t survive the drop. As luck has it, I keep my keys to the car inside the car and use the remote to open the door. Quickly, I realize I’m taking the train home tonight.

Moral of the story: Keep you keys in your pants until you get to your car.

Saturday, September 03, 2005

The Carolina Way

I love being at the beach. It gives me lots of time to catch up on non-technical reading. This year, I brought along The Carolina Way: Leadership Lessons from a Life in Coaching, by Dean Smith and Gerald Bell. A little disclosure here; I'm a Carolina fan and if Dean Smith said he made kids practice in bare feet, I'd think it was a good idea.

This book is more than your typical sports book. Sure, it's filled with stories about games, seasons, and individual players. Each chapter starts out with Coach Smith explaining a particular aspect of his coaching methodology. A Player's Perspective follows outlining how the particular aspect and Dr. Bell relates the aspect to the modern workplace. This book is all about building teams.

The Carolina Way can be summed up by these words: Play Hard; Play Together; Play Smart. For example, Coach Smith talks about recruiting players that will fit into his system. Dr. Bell then takes those ideas one step further and relates the recruiting to hiring workers. Another example is Dean Smith held regular one-on-one meetings with each of his players to discover their goals in life as well as basketball. Dr. Bell then outlines how you can pattern employee reviews around these same principals.

I personally got a lot out of this book and plan on implementing some of the strategies in my own team.

Thursday, September 01, 2005

Blogger for Word

I am posting this blog entry using the new Blogger for Word add-on.  I downloaded it a couple days ago and tried to get it working, but had problems connecting to blogger.com.  I fired it up today, and voila! It works.

I tried some of the other editors out there, but just found it easier to use the blogger.com editor, except in cases of posting source code.  Lets see how this comes out:

FOR i IN 1..100 LOOP
   i:= i+1;
END LOOP;

OK, that should suffice.  Heck, I already know Word, let me try this for a couple days to see how it goes.