Archive for July, 2006

How to find out who is locking a table in MySQL

MySQL is adding more tools to monitor its internals with every new release, but one thing it still lacks is a way to find out who is locking what, and therefore which transactions block which other ones. This is such a vital feature that I’m considering writing my own patch to the source! Still, it is possible, to a limited extent, to find out who’s locking resources. In this article I’ll explain how you can do that.

This article is the second in a series on how to use the innotop MySQL and InnoDB monitor.

Introduction

Here’s the situation: you are trying to update a table and every time you issue the query, it hangs until it times out and tells you the lock wait timeout was exceeded. Someone has locked the table you’re trying to update, but you have no idea who. This can be incredibly frustrating, because this could go on indefinitely. I’ve sometimes had to put work off till another day, because the table is locked all day long.

I’ve found only a very limited set of circumstances in which MySQL will say what’s happening with locks. These are all printed out in the text of SHOW ENGINE INNODB STATUS.

When there was a deadlock

The first way to see locks is when there’s been a deadlock. The status text will show transaction information on the transactions that deadlocked, which locks they held, and which they were waiting for. Here is a sample. Look at the sections titled “WAITING FOR THIS LOCK TO BE GRANTED” and “HOLDS THE LOCKS.”

------------------------
LATEST DETECTED DEADLOCK
------------------------
060731 20:19:58
*** (1) TRANSACTION:
TRANSACTION 0 93698, ACTIVE 2 sec, process no 12767, OS thread id 1141946720 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1216
MySQL thread id 3, query id 19 localhost root Updating
update test.innodb_deadlock_maker set a = 0 where a <> 0
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 131120 n bits 72 index `GEN_CLUST_INDEX` of table `test/innodb_deadlock_maker` trx id 0 93698 lock_mode X waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 6; hex 000000019000; asc       ;; 1: len 6; hex 000000016e01; asc     n ;; 2: len 7; hex 80000000320110; asc     2  ;; 3: len 4; hex 80000000; asc     ;;

*** (2) TRANSACTION:
TRANSACTION 0 93699, ACTIVE 2 sec, process no 12767, OS thread id 1142212960 starting index read, thread declared inside InnoDB 500
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1216
MySQL thread id 4, query id 20 localhost root Updating
update test.innodb_deadlock_maker set a = 1 where a <> 1
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 131120 n bits 72 index `GEN_CLUST_INDEX` of table `test/innodb_deadlock_maker` trx id 0 93699 lock mode S
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 6; hex 000000019000; asc       ;; 1: len 6; hex 000000016e01; asc     n ;; 2: len 7; hex 80000000320110; asc     2  ;; 3: len 4; hex 80000000; asc     ;;

Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 6; hex 000000019001; asc       ;; 1: len 6; hex 000000016e01; asc     n ;; 2: len 7; hex 8000000032011f; asc     2  ;; 3: len 4; hex 80000001; asc     ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 131120 n bits 72 index `GEN_CLUST_INDEX` of table `test/innodb_deadlock_maker` trx id 0 93699 lock_mode X waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 6; hex 000000019000; asc       ;; 1: len 6; hex 000000016e01; asc     n ;; 2: len 7; hex 80000000320110; asc     2  ;; 3: len 4; hex 80000000; asc     ;;

*** WE ROLL BACK TRANSACTION (2)

More importantly, the lines beginning “RECORD LOCKS space id 0″ show which index of which table was locked. That is the real meat of the matter — that’s what you need to know.

There’s just one problem: after there’s been a deadlock, it’s too late. You don’t want to know what held locks in the past, you want to know what holds them now. The deadlock information isn’t usually helpful in finding out what transaction is blocking something from happening.

When a transaction is waiting for locks

The next place you can sometimes see lock information is in the transaction section of the output. Here’s a sample:

---TRANSACTION 0 93789802, ACTIVE 19 sec, process no 9544, OS thread id 389120018
MySQL thread id 23740, query id 194861248 worker1.office 192.168.0.12 robot
---TRANSACTION 0 93789797, ACTIVE 20 sec, process no 9537, OS thread id 389005359 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 320
MySQL thread id 23733, query id 194861215 elpaso 192.168.0.31 robot Updating
update test.test set col1 = 4
------- TRX HAS BEEN WAITING 20 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 299998 n bits 200 index `PRIMARY` of table `test/test` trx id 0 93789797 lock_mode X locks rec but not gap waiting
Record lock, heap no 77 PHYSICAL RECORD: n_fields 15; compact format; info bits 0 
 0: len 4; hex 80474fd6; asc  GO ;; 1: len 6; hex 000005970680; asc       ;; 2: len 7; hex 000017c02b176c; asc     + l;; 3: len 4; hex 80000003; asc     ;; 4: len 8; hex 800000000da0c93a; asc        :;; 5: len 8; hex 800000000eb2ea7e; asc        ~;; 6: len 4; hex c771fe44; asc  q D;; 7: len 4; hex 8000003e; asc    >;; 8: len 8; hex 8000123eb9e5dfd5; asc    >    ;; 9: len 4; hex 8000003a; asc    :;; 10: len 8; hex 8000123eb9e43603; asc    >  6 ;; 11: len 4; hex 80000035; asc    5;; 12: len 8; hex 8000123eb9d6c130; asc    >   0;; 13: len 4; hex 80000033; asc    3;; 14: len 8; hex 8000123eb9c7c853; asc    >   S;;
 
---------------------
---TRANSACTION 0 93789679, ACTIVE 31082 sec, process no 9535, OS thread id 388972583 starting index read, thread declared inside InnoDB 6
mysql tables in use 4, locked 4
11614 lock struct(s), heap size 683328
MySQL thread id 23731, query id 194861117 elpaso 192.168.0.31 robot

Notice the first transaction has been waiting 20 seconds for a lock to be granted, and it tells you which table and index as above. The other transaction I included (there were many in this section, but I omitted most) says it has 4 tables open and 4 locked. What it doesn’t say is which ones.

Again, there’s some information here, but not a lot. If you issue a query and it hangs and waits for a lock, knowing what lock it’s waiting for isn’t really helpful. And knowing some other transaction holds a lock isn’t always helpful either.

It can be useful sometimes though, and that’s better than nothing. If you only see two transactions with locks, you know the one that’s not waiting for a lock is probably the one that holds them. Notice something scary in the information above? Transaction “0 93789771″, on connection 23731, has been active for… eight and a half hours! Whoa. It’s time to find out what owns that connection and possibly kill it.

The take-away here is, if you’re getting blocked on an InnoDB table, and you’re lucky enough to see only one other transaction with locks, it’s probably the one blocking you.

What about table locks?

Ah, good question. What if the table isn’t InnoDB, or what if someone locked it with LOCK TABLES, and it doesn’t show up in the output of SHOW ENGINE INNODB STATUS? As far as I know, you’re helpless. I don’t know how to get any information on who’s locking the table then. Table lock information doesn’t seem to be exposed in any fashion — only row lock information.

In fact, if you’re in a transaction, LOCK TABLES seems to “kick you out” of the transaction. Try experimenting with START TRANSACTION and LOCK TABLES on an InnoDB table, and you’ll see what I mean. If you lock a table for writing, then try to select from it in another connection, the other connection will block. If you then issue START TRANSACTION on the first connection, the second connection will immediately unblock, and the first connection’s transaction will disappear from the InnoDB status text.

Who wants to read all that mess?

Who, indeed? The text I included above is a pain to read, and it’s not even representative of what you’ll really be looking at. For one thing, you might have to scan through 40 or more transactions to find the ones you care about, and then there’s all the other information in the output, some of which can be voluminous (such as deadlocks). What a hassle!

Fortunately, there’s a tool to do that for you: innotop. This tool formats the output neatly and gives you filtering options to display only transactions with locks (or just sort them to the top of the display). Here’s how you can do that:

Start innotop and use the “T” key to enter InnoDB Transaction mode, if it’s not already in that mode. You will see a list of transactions. Next, make the “Locks,” “Tbl Used,” and “Tbl Lck” columns visible. Press the “c” key to activate the “choose columns” dialog:

innotop screenshot

Press Return and you should see something that looks like this:

innotop screenshot

Now sort transactions with locks to the top by pressing the “s” key and choosing “lock_structs” as the sort column. You may need to press the “r” key afterwards to reverse the sort order if they go to the bottom instead. Alternatively, you can use the “w” key to add a filter on the “lock_structs” column, such as “[1-9]” to match only rows where the column isn’t zero (this is a handy filter to add in general, just so you can see how many transactions have locks).

Here’s a screenshot of me changing the sort column, and adding a filter:

innotop screenshotinnotop screenshot

And here’s a screenshot of the result:

innotop screenshot

In this example you could see the locks without hiding the other rows, but when you have a very busy server it can really help to hide all the transactions without locks.

Isn’t that easier than digging through the output of SHOW ENGINE INNODB STATUS? I think so.

Is there more?

Though I’ve searched the Internet, searched the source code and the MySQL manual, I haven’t been able to find any other ways to get information on current locks in MySQL. But I’d be delighted if you prove me wrong! If you have anything to add, please comment.

Technorati Tags:No Tags

You might also like:

  1. How to monitor InnoDB lock waits
  2. How I patched InnoDB to show locks held
  3. How to debug InnoDB lock waits
  4. A little-known way to cause a database deadlock
  5. An introduction to InnoDB error handling

How to install innotop

This is the first in a series of articles I’ll write on how to use innotop, the MySQL and InnoDB monitor I’m developing. This article explains how to install innotop.

Note: this article is outdated now. Please see the innotop homepage for updated installation instructions and download options.

Technorati Tags:No Tags

You might also like:

  1. Innotop version 1.152 released
  2. New support options for innotop
  3. How to install innotop on Microsoft Windows
  4. MySQL Query Profiler, Checksum, Index Checker updated to version 1.0.1
  5. Installing innotop on FreeBSD and Gentoo

Why does InnoDB create two indexes per foreign key?

If you’ve ever created foreign keys on an InnoDB table, you’ll see it automatically creates indexes, if none exists, on the referenced columns in the parent table, and also in the foreign key columns in the child table. This article explains why both are needed.

Why index the parent table?

When a row is inserted or updated in the child table, the parent table must be searched for a row whose referenced values match the values in the foreign key columns. To make this efficient, it’s necessary to have a usable index on those columns in the parent table.

By “usable” I mean an index where the columns are either a leftmost prefix or a full cover of the foreign key columns.

Why index the child table?

Foreign key checking goes both directions. When a row in the parent table is updated or deleted, any rows in the child table that depend on it must be checked to make sure they’re not invalidated (or, in the case of a CASCADE, to find them to take the CASCADE action upon them). Again, the only efficient way to do this is to use an index.

You can see that the checking always uses indexes by examining the output of SHOW INNODB STATUS and looking at the LATEST FOREIGN KEY ERROR section. If there’s an error there, you will always see information about two indexes (though it may not always be obvious, since the code that creates this output has to handle a variety of different errors).

By the way, I seem to remember seeing some comments in the InnoDB source code that say indexes are not created automatically, but I can’t find them now. In any case, if this was true once, it is no longer true.

A useful tool

The innotop tool can format and display the LATEST FOREIGN KEY ERROR output for easy reading. I check our systems for foreign key violations regularly. Here is a sample of innotop’s output for a violation I deliberately manufactured for this article:

Reason: Foreign key constraint fails for table `test/table_2`:

User xaprb from 192.168.0.225, thread 64548 was executing:

insert into table_2(table_1) values(5)

Time            2006-07-27 16:32:10
Child DB        test
Child Table     table_2
Child Index     table_1
Parent DB       test
Parent Table    table_1
Parent Column   table_1
Parent Index    PRIMARY
Constraint      table_2_ibfk_1
Technorati Tags:No Tags

You might also like:

  1. MySQL’s ERROR 1025 explained
  2. Introducing MySQL Duplicate Key Checker
  3. Duplicate index checker version 1.8 released
  4. How to find duplicate and redundant indexes in MySQL
  5. The innotop MySQL and InnoDB monitor

How to coordinate distributed work with MySQL’s GET_LOCK

This article explains how I replaced file-based methods to ensure only one running instance of a program with MySQL’s GET_LOCK function. The result is mutual exclusivity that works in a distributed environment, and it’s dead simple to implement.

My current employer used to use a technique similar to the classic Perl ‘Highlander’ method to ensure only one instance of a certain program would run at any given time. The method was to create a file with a certain name and then get an exclusive, non-blocking lock on the file with the flock() call. If another program tried to get the same lock, it would find the file already locked and exit with a message about “another running instance found.”

This type of locking can be pretty tricky to get right. There are always lots of edge cases to consider. For example, what if the same program tries to get the lock twice and blocks itself?

Trying to roll your own locking functionality is asking for trouble, unless you really know what you’re doing. It’s not enough to just create some “sentinel” that indicates “something else is running.” It must be done atomically and in a non-blocking fashion — already tough to hand-roll — and there are lots of other requirements, such as “the lock must be released if the program dies without having a chance to release it.” This is all old news to readers who’ve worked with threading or other concurrency issues in programs, of course.

The file-based solution works well on a single machine, but it doesn’t work well if you need programs on different machines to play nicely together. Using a network filesystem such as NFS doesn’t solve that problem either. It may work on certain systems, but it’s not portable.

We had this problem at my employer. We were beginning to distribute parts of the workload out to cloned servers, each of whom would do part of the work based on which machine and what time of day, and we needed to make sure they didn’t stomp on each other if they miscalculated what work they should be doing. Several options came to mind, all of them using some functionality already provided for us. For instance, we could choose a server as the arbitrator and write a daemon on it to accept network connections. Holding a socket open to that daemon would represent a lock. If the daemon already had a connection from a certain program, it would deny the connection to other programs. If the program with the lock died, the lock server’s operating system would know, the daemon would know, and it could make the socket open to another instance.

I was just about to take this approach when I stumbled upon MySQL’s GET_LOCK function, completely by accident. I immediately realized we could use it. The syntax is GET_LOCK(str, timeout), and the behavior is to attempt for timeout time to get a “lock,” returning a value indicating whether it succeeded. The “lock” is exclusive, and setting timeout to zero makes the call non-blocking, which is perfect.

I’m putting “lock” in quotes because it’s not really a normal database lock, in the way you might be used to thinking of it. It’s not a lock on a row, or a lock on a table, or anything like that. It’s a lock on an arbitrary string value, and like flock(), it’s completely advisory; nothing forces a program to wait for the lock — it is up to the programs to play nicely together.

The actual SQL call is select COALESCE(GET_LOCK('some_string_value', 0), 0). The call returns 1 if the lock was granted, and 0 or NULL otherwise (hence the COALESCE()). The lock is released either explicitly, or when the connection closes. There are more subtleties to the function’s behavior, but for this purpose, this is all we need to worry about (you can read the manual to learn more about the subtleties).

We did raise the question “what if the DB server is down?” but quickly answered it: every program that does anything important talks to the DB server, so it’s a moot point. Besides, if it’s down, we have bigger problems than two programs processing the same data twice.

Unfortunately, as far as I know no other database vendor has provided something similar to this incredibly handy function.

Are there other ways to implement this easily? I can’t imagine an easier way — even the flock() solution was harder to get right than this — but if you have other ideas, let me know. I’m especially interested in how you’d do this without a DB server.

Technorati Tags:No Tags

You might also like:

  1. How to notify event listeners in MySQL
  2. How to create a VB6 console program
  3. How I patched InnoDB to show locks held
  4. How to auto-mount removable devices in GNU/Linux

Version 0.1.106 of innotop MySQL/InnoDB monitor released

I’ve just improved innotop substantially, and released version 0.1.106 (download innotop here), and I’m also preparing a series of articles on how to use it for real, practical things. I’d like to know what you think of it, what problems you have, what features you want. It would be a huge help if you’d start it, toggle through its modes, and give me your feedback.

Enhancements in version 0.1.106 include:

  1. InnoDBParser is much more complete and accurate.
  2. Tons of bug fixes.
  3. Add partitions to EXPLAIN mode.
  4. Enhance Q mode header, add T mode header.
  5. Share some configuration variables across modes.
  6. Add formatted time columns to Q, T modes.
  7. Add command-line argument parsing.
  8. Turn off echo when asking for password.
  9. Add option to specify port when connecting.
  10. Let display-optimized-query display multiple notes.
  11. Lots of small improvements, such as showing more info in statusbar.

That’s only a partial list, but those are the major things I’ve improved. I hope you enjoy it, and stay tuned for articles on how to use it.

Technorati Tags:No Tags

You might also like:

  1. The innotop MySQL and InnoDB monitor
  2. Version 1.6.0 of the innotop monitor for MySQL released
  3. innotop 1.4.2 released
  4. innotop 1.4.0 released
  5. How to monitor MySQL status and variables with innotop

How to track what owns a MySQL connection

MySQL doesn’t yet provide good tools for some troubleshooting tasks. Fortunately, there is some low-hanging fruit you can pluck. One example is a tool to record who owns a MySQL database connection, so long-running transactions can be traced back to the source. This article demonstrates an easy way to solve that problem.

Introduction

One of the reasons I wrote the innotop InnoDB and MySQL monitor was to monitor long-running transactions. Sure enough, I began to see some transactions being held open for tens of thousands of seconds (ouch!), sometimes with open locks and undo log entries. From MySQL itself I can find the connection ID, transaction number, username and hostname of the offender, but not what program opened the connection. Since our software mostly uses a single login to access the database, even the username and hostname didn’t help. It could be one of dozens of systems.

How I solved it

Everything has the same username because all our software connects through one database abstraction layer, which creates a single point of access. I changed it to identify the caller to the database. This is fast and painless, and provides a reverse lookup.

Here’s the trick: create a table like this,

create table connection_info (
   connection_id int not null,
   unix_proc_id int not null,
   prog_name varchar(50) not null,
   ts timestamp not null,
   primary key(connection_id),
   key(unix_proc_id)
) engine = MyISAM;

This is obviously designed for UNIX systems. Our client software is written in Perl, so any program that connects can be recorded simply by changing the DB access layer to issue the following query right after connecting:

replace into connection_info
   (connection_id, unix_proc_id, prog_name, ts)
   select connection_id(), $PID, '$PROGRAM_NAME', current_timestamp

$PID and $PROGRAM_NAME are Perl variables for the current process’s ID and the name of the program currently executing. Every programming language and operating system I know has some way to get this information.

The query is fast, so there’s very little added overhead when making a connection, especially given that our systems tend to connect and hold the connection open for a long time while doing a lot of work. The initial extra cost becomes vanishingly small.

Results

After I made this change, we were able to start looking up who held an open transaction for a long time. The culprit turned out to be processes owned by an Apache web server, which were running instances of mod_perl that didn’t really get unloaded after the HTTP request was serviced. The real trouble was poor coding practice, of course; explicitly closing the database connection is the solution.

Although this system works well for us, I’m curious if there are better ways to do it. What do you think? Leave a comment!

Technorati Tags:No Tags

You might also like:

  1. innotop 1.5.0 released
  2. How to coordinate distributed work with MySQL’s GET_LOCK
  3. How to monitor InnoDB lock waits
  4. How to deliberately cause a deadlock in MySQL
  5. How to find out who is locking a table in MySQL

3 ways to maintain rollup tables in SQL

At both my current and previous employer I’ve been involved in designing and maintaining aggregate, or “rollup” tables for advertising traffic data. I have learned several methods of propagating changes from the atomic data through to its aggregations. This article discusses these methods, how to implement them, and their pros and cons.

As an example of data that gets rolled up to aggregate tables, I’ll use my current employer’s data structures (more or less). The main table looks something like this:

create table ad_day (
   ad int not null,
   day date not null,
   impressions int not null,
   clicks int not null,
   cost_cents int not null,
   avg_pos decimal(3, 1) not null,
   primary key (day, ad)
) engine = InnoDB;

As an aside, notice the table is called ad_day, which is the way people generally want to say it — “rolled up by ad by day” — but the primary key is (day, ad) — the reverse of the way people say it. When I joined the company, it was indexed (ad, day), which generally doesn’t help most queries, which want to look at data in a date range. Actually, it had a surrogate key, so there wasn’t even a good clustered index! I’ve written a lot about this in the past, and the woes it caused us. You might find those articles interesting if you’re considering designing some large tables.

The challenge

The ad_day table is rolled up along two dimensions: by time (ad_week, ad_month, ad_year) and by coarser levels of our schema hierarchy. For example, an ad belongs to an account, which is the intersection of a search_engine and a client, so we have tables rolling the data up along those lines (account_day, client_day, search_engine_day).

Fortunately, that’s as far as it goes — we either roll up by one dimension or the other, but not both, though I’ve never seen a case where someone didn’t want more and more. It’s the old multiple-hierarchy problem — as soon as you “slice” things one way, you want to slice it another way too. I’ll have a lot more to say in future articles about the evils of “slicing” and “rolling up.”

The challenge with this set of tables is to make sure the rollup tables are always accurate with respect to the atomic ad_day table. As soon as any data changes in that table, the rollup tables need to be changed to agree with it. There are three types of changes to deal with: inserts, deletes, and updates. Each of them can have very different requirements, depending on the schema of the rollup tables. For instance, an insert into ad_day may require an insert into client_day, or may only require an update. And, depending on the data requirements, this may all need to be transactional to prevent inconsistent data. Ideally, it would be transactional if for no other reason than to ensure an aborted change doesn’t leave things out of sync, but in large tables that may be very costly.

Orphan rows

One thing to keep in mind when rolling up tables like this is orphan rows. Deletes in the atomic table may leave rows dangling in the rollups unless you’re careful to delete them. For example, if I delete all ads for a client in the ad_day table, then run a naive rollup query like so:

insert/update into client_day (client, day, ...)
   select client, day, sum(clicks)...
   from ad_day...

That query will correctly sum the rows in the ad_day table, but it won’t touch the rows left over in the client_day table. These rows are orphans. This is important to keep in mind when desiging a rollup system.

Method one: triggers

This is one place where I’d actually be in favor of using triggers to automatically propagate the changes through to the rollup tables. The ad_day table will need a trigger for each event (INSERT, UPDATE, DELETE), and if there are intermediate-level rollups, they will too. As an example, if the client_day table is rolled up from account_day rather than ad_day directly, account_day will need triggers too. Orphans can be handled without too much trouble with this scheme.

An alternative to triggers is a stored procedure that does the same thing. At my previous employer we inserted or updated only one row at a time in the ad_day table, using a stored procedure.

Whether it’s via triggers or stored procedures, the logic can get a bit hairy. Correctly updating a rollup table may require a lot of math. For example, keeping the avg_pos column straight during an update is tedious. avg_pos is the average position of the ad over all its “impressions” (every time the ad is displayed is an “impression”), so updating it requires calculating deltas from current values, then applying those deltas to the correct row in the rollup, which probably contains the weighted average of a bunch of ads or over a bunch of days, so the delta has to be given the correct weight in the rollup. I won’t reproduce the math here. It’s not hard, but it is tedious and easy to get wrong.

Another problem with triggers, if they handle one row at a time as they do with MySQL, is that one change may indicate a row in the rollup is no longer needed and should be deleted, then the next change may indicate that row should be brought back. To avoid this delete-insert-delete-insert vicious cycle, all-zero rows should probably just be left for later cleanup. Of course, if your platform supports setwise operations on the affected data, as in Microsoft SQL Server, you should handle it as a set, not a row at a time, and this isn’t an issue. Thus, depending on how triggers are implemented on your platform, you will need to handle orphan rows differently.

The benefit to the trigger approach is that the changes flow through the system with no further ado. As long as nothing else changes the rollup tables, they should stay in perfect lockstep with the atomic table.

Method two: empty and re-fill

Another approach, if it makes sense for the data, is to delete a range of the data and re-calculate it from scratch. In the example I’ve given, this does make sense. We typically keep up-to-date on traffic data, unless something breaks, so we’re generally fetching yesterday’s traffic data and inserting it into the table. This means we’re working at the end of the table, and each time we do a batch, we can remember the earliest date affected, then empty and re-fill from that date forward.

Benefits of this approach are that the math is a lot simpler. There is no math to handle updates and deletes, just inserts. There’s also no hidden black magic going on behind the scenes (I’m referring to triggers, which scare some people because they do things invisibly). And finally, orphan rows are taken care of; the table is emptied before it’s filled, so there’s no chance orphan rows will hang around.

There’s a cost, though: a lot of inserting and deleting. That’s kind of hard on the database, depending on the platform. For example, we’re using MySQL and the InnoDB storage engine. It would probably be cheaper to use MyISAM, which keeps deleted rows in a linked list for later re-use, but that has its drawbacks too. In any case, this isn’t the method we use, because of all the deletes and inserts.

Method three: zero and re-calculate

An alternative to the second method, which we use at my current employer, is to zero out the atomic table from the start date forward, and then REPLACE with new data and use REPLACE to roll it up to the aggregate tables. On other systems, you can use an equivalent method — MERGE in Oracle, UPDATE/INSERT in Microsoft Sql Server. See my article on flexible inserts and updates for more details.

This method has two main advantages. One, it’s not that costly to UPDATE a row in place. It’s much cheaper to flip some bits to zero than to delete an entire row. Two, the changes will automatically propagate to rollup tables — even those not zeroed out — as you run the rollup, taking care of orphan rows. They will still be in the table, but they’ll just a bunch of zeroes if they truly are orphaned. If they’re not truly orphaned, they’ll have the right values — and all-zero rows won’t contribute anything to any further dependent rollups, if your rollup system uses rollup tables as the source for other rollup tables.

The major drawback to this system is all-zero rows.

How to clean up all-zero rows

If your chosen method leaves all-zero rows lying around, you’ll want to take care of that. Rows filled with zeroes just make the table larger. Fortunately, this isn’t a terrible problem. It should be easy to write a nibbler to purge the junk rows, which ought to be very low-impact on the server.

Summary

I’ve discussed three methods to keep rollup tables in sync with the authoritative data, from which they’re rolled up. I’ve used several methods, and each has advantages and disadvantages. What do you think? Are there other options?

If you found this article useful, subscribe via feeds or e-mail to be notified when my upcoming articles are published.

Technorati Tags:No Tags

You might also like:

  1. How to reverse a sequence in SQL
  2. How to implement a queue in SQL
  3. How to find duplicate rows with SQL
  4. SQL Server 2000 date and time puzzler
  5. How to use foreign key cascades in MySQL

How we enabled threading in MySQL

MySQL on GNU/Linux appears to be able to either run multiple processes, or one process and multiple threads. We’ve noticed a significant CPU penalty for multiple processes, probably from the context switching overhead. The trouble was, one of our servers wouldn’t use threads; it wanted to use multiple processes. This article explains how we got it to use threads instead.

First, we noticed the master server’s CPU utilization was higher than the slave’s, even though we expected the type of queries running on the slave should have caused it to have around the same CPU utilization as the master. We checked the configuration, but couldn’t find anything that should have caused this. Then we noticed the slave only had a single process in top, but the master had dozens. My co-worker speculated that the single process on the slave might have been running many threads, which have so much less context-switching overhead that it could have caused the difference. Indeed, I was able to toggle the display of threads in top with the H key, and could see each connection being handled by a thread.

Another clue was running vmstat and looking at the number of context switches in the cs column. The master’s number was much higher than the slave’s. We examined a number of other performance metrics (see my article about monitoring server load in GNU/Linux), but those ended up being the the most obvious signs of difference between the two servers.

The key ended up being NPTL. As I discussed in my article on Gentoo and NPTL, apparently certain software won’t multi-thread, even when it has linuxthreads available. I’m not pretending to know a lot about compiling MySQL, but we did try multiple ways to get it to use threads, and it wasn’t until we figured out NPTL wasn’t built into glibc that we made any progress. After re-building glibc and restarting the the mysql daemon, it came back up with just one process, but multiple threads. Success! Now our master server uses less CPU, leaving more available for queries.

Technorati Tags:No Tags

You might also like:

  1. How to switch from linuxthreads to NPTL on Gentoo
  2. Why MySQL says the server is not configured as a slave
  3. MySQL Toolkit version 896 released
  4. How to measure MySQL slave lag accurately
  5. How to sync tables in master-master MySQL replication

How to switch from linuxthreads to NPTL on Gentoo

This article explains how to enable the Native Posix Threading Library (NPTL) on Gentoo GNU/Linux, and how to disable the now-obsolete linuxthreads library so you don’t have both on your system.

Linuxthreads and NPTL are part of glibc, the GNU C Library. The recommended threading library for GNU/Linux is now NPTL, not linuxthreads, even though the linuxthreads web page’s excerpt in Google says it’s “The recommended threads package for Linux, also included in glibc 2.0.” Development on linuxthreads stopped a while ago, and NPTL is now mature and should be used instead, as it has many advantages.

How to enable NPTL on Gentoo

Just as with many other things, Gentoo has a USE flag to turn NPTL on. The use flag is, appropriately, nptl. There’s a twist, though. As the message during the emerge process notes,

Warning! Gentoo’s GLIBC with NPTL enabled now behaves like the glibc from almost every other distribution out there. This means that glibc is compiled -twice-, once with linuxthreads and once with nptl. The NPTL version is installed to lib/tls and is still used by default. If you do not need nor want the linuxthreads fallback, you can disable this behavior by adding nptlonly to USE to save yourself some compile time.

So, unless you want both libraries, you should add both nptl and nptlonly to your /etc/make.conf. Next you should run revdep-rebuild (from the gentoolkit package) to make sure everything is built to use it.

By the way, “tls” stands for “thread-local storage.” Wikipedia has a good article on TLS.

How to tell if it’s enabled

Even if it’s set in your USE flags, your system might not be using NPTL for threading. It has to be enabled in your kernel, glibc has to be compiled with support for it, and there may even be other factors at play. Here are several ways to know if your system is set up to use it.

First, check whether software you compile can be configured with support for NPTL:

$ getconf GNU_LIBPTHREAD_VERSION
linuxthreads-0.10

If you see that output, this system is still using linuxthreads. Just to be sure, you can also execute the library (yep, the library itself can be executed):

$ /lib/libc.so.6
GNU C Library stable release version 2.3.6, by Roland McGrath et al.
... snip ...
Compiled on a Linux 2.6.11 system on 2006-06-18.
Available extensions:
        GNU libio by Per Bothner
        crypt add-on version 2.1 by Michael Glad and others
        linuxthreads-0.10 by Xavier Leroy
        The C stubs add-on version 2.1.2.
... snip ...

You want to look at the “Available extensions” section of the output. Again, in this example you can see linuxthreads is included, but not NPTL.

On the other hand, maybe if you execute /lib/tls/... you’d find an NPTL version there. In any case, once you rebuild with the nptlonly USE flag, you should see the following from executing /lib/lib.so.6:

$ /lib/libc.so.6 
GNU C Library stable release version 2.3.6, by Roland McGrath et al.
... snip ...
Available extensions:
        GNU libio by Per Bothner
        crypt add-on version 2.1 by Michael Glad and others
        Native POSIX Threads Library by Ulrich Drepper et al
... snip ...

The getconf call should also return NPTL now.

Certain software will not use threads, even if it has linuxthreads available, unless it can use NPTL. Instead it will use multi-processing, which causes a lot more overhead. I have not found anything that complains about the lack of linuxthreads, so I believe it is safe to use ntplonly.

Technorati Tags:No Tags

You might also like:

  1. How we enabled threading in MySQL
  2. How to update a GCC profile on Gentoo
  3. Why I (still) like Gentoo
  4. Installing innotop on FreeBSD and Gentoo

So you think your code is in version control?

“My code is all in version control,” Joe said proudly. “Everything is versioned. I’ll never lose any work.” But then he lost some “other” code he didn’t realize was critical. This article is about how to find and safeguard all the hidden code you don’t know your business relies on.

Introduction

Everyone knows version control is indespensable. I put everything into version control — even my GnuCash file is in version control. So is my poetry (you’re in luck: this is a technical blog, so I won’t post any of it). And definitely all my code, right?

Well, no. Like many people, some little snippets of code escape my notice. I don’t think of it as something that has to be in version control. This is really dangerous. The most recent time I noticed some code eluding my version control fanaticism was in the comments on my post on re-licensing my JavaScript snippets. I realized that I’d developed these scripts at odd times, over SSH connections to servers I didn’t own, e-mailing myself the latest versions to save it… but never putting it in version control. I felt dumb.

Feeling dumb is one thing, but suddenly discovering that you’ve overlooked some critical code and you can’t recover it from backups in the middle of the night is another. Software engineers I’ve known, myself included, have a habit of thinking about certain work products as code, and others as less important and not deserving of version control. For example, maybe certain things go through a defined release process, and others don’t, and you think of the release-able things as code that needs to be in version control.

You need to become conscious of those hidden distinctions, and put everything into version control, because it will bite you if you don’t. This article isn’t about the benefits of version control, or how to use it. It’s about helping you realize the things you’ve forgotten, so you can stop overlooking them.

Here’s a list of things I version. It’s not necessarily an exhaustive list; the point is to get your creative juices flowing, and come up with your own list.

User-related information

If you’re not versioning users, passwords, public keys, groups, and privileges, you’re not versioning the full state of your software system. Your system depends on the right users having the right privileges to do the things that have to happen. It can get very complex in a system of any size. If you install a system, then spend weeks tweaking it to have the right users and privileges, but then lose those, you may have lost weeks of work. Likewise, if you install on a test system and then have to deploy to production systems, you should not have to go through it all again if you’ve versioned it.

Database schema

Something went wrong during the release. It’s midnight, and a stored procedure is trying to insert into a table, but there’s a database error: it’s trying to insert too many columns. One of your developers made the mistake of doing a blind insert. And you don’t know what the database used to look like, because you don’t have your database schema under version control.

It’s really easy to fix this. Just create a nightly scheduled task that scripts out the entire database schema and commits any changes. I did this at my new employer and it has proven very helpful even when there are no problems; it gives everyone visibility into what is changing, and it even helps us find what refers to a given database entity, because the schema is all in searchable text files.

Initialization scripts

Imagine this: you built a great database schema for a system that integrates with an e-commerce or business-to-business system. It serves as the persistence layer for a set of services that talk remotely to web services on the other end. Your code is all in version control, and so is the schema. But you populated those tables with definitions of the partner’s constants, and someone deleted them. Now you don’t have the constants, and you don’t have the script to populate the tables with the initial set of data.

Such initialization scripts should always go into version control. Anything that has to do with getting the system into a defined state so it’ll function definitely needs to be versioned. You should be able to start with an empty database, run your schema script, run your initialization script, and be ready to roll. Even if there’s no data loss, this is essential for smooth integration and deployment.

Other database code

Stored procedures, user-defined functions, and triggers should also be in version control. In the Microsoft world, stored procedures can be put into Visual SourceSafe fairly easily, but triggers and functions can’t, at least not when I quit working in the Microsoft world about six months ago. They can still be scripted to file, and put into version control that way, as opposed to integration with SourceSafe through an IDE, though.

In the non-Microsoft world, of course I script these things out to files and put them into version control.

Scheduled tasks

Crontabs and other OS-specific scheduled tasks are also code. I don’t know about Windows Scheduled Tasks, but crontabs are very easy to put into version control, along with a script to install them from version control, with the ability to detect if they’ve been changed outside version control and complain.

One great benefit to this is knowing what programs are used. You can search for any references to programs if your scheduled tasks are in version control.

Configuration files

In UNIX systems, the entire /etc directory is a good candidate for version control. Sometimes operating systems even have built-in versioning methods, which is great. For example, on Gentoo GNU/Linux, using dispatch-conf with the option to integrate RCS is a good idea (as opposed to using etc-update, which doesn’t keep deltas between past versions).

In the non-UNIX world, you can find all configuration files and add them to version control with a really minimal amount of extra work, considering how much work it could save you. In Windows, I think it’s a great idea to script out either the entire registry, or selected parts of it.

Your backups

That’s right, all your data in your regular backups can be versioned! Look into rdiff-backup for a great example of a tool that does this. A side benefit of storing deltas is the much smaller disk space requirement. Storing all backups like this might be a bit extreme of course, but sometimes it’s a viable option. One place I actually do this is on my home systems. I use rdiff-backup to back up my entire /etc and /home directories. Boy, has that saved my neck a few times!

Other things

Here are some other things that might need to be in version control:

  1. one-off shell scripts and environmental settings (supposing they’re in /usr/local/bin, you can put them somewhere else that’s under version control, and make symbolic links to them)
  2. your documentation and specifications (including your wiki)
  3. your template and scratchpad files
  4. lists of software and versions installed from other sources, such as CPAN

Summary

You may think I’m a fanatic to insist on versioning everything, and you’d be right — but my fanaticism has saved me, and sometimes my employers, a lot of trouble. I think everything ought to be under version control, but it’s so easy to overlook something. I hope this article has helped you make a list of critical code you’re not putting into source control.

Technorati Tags:No Tags

You might also like:

  1. Announcement: Xaprb scripts are re-licensed
  2. High Performance MySQL, Second Edition: Backup and Recovery
  3. More GnuCash to MySQL tools and queries