This may or may not be pagination done right, but here is how I do pagination in my web app:
|< First, << Previous, Page [5] of 12, Next >>, Last >|
The outer four options are links, while the Page [5] of 12 is a form, with the [5] as an input field. For users with JavaScript enabled, I hide the submit button and submit the form on the unfocus event or enter keypress. The user has the option on how many rows they want to display, which they can select from a dropdown menu: 10, 20, 50, 100, All. I also provide sorting and filtering of the results in addition to pagination, though that may not make sense in every situation.
Edit:
Here's a snippet from a mockup of our web app to give you a better idea. In this version, the words have been omitted from buttons, but appear as a tooltip on hover after a slight delay. However, you may find that keeping the words will result in a higher level of usability.

A few other things to point out:
- The "First" and "Previous" buttons have been disabled because it's the first page.
- The blue indicates active buttons (I will have to run this particular theme through a color checker to make sure that colorblind users can tell a difference).
- The buttons always remain, even if they are disabled. This gives the interface consistency.
- I chose an input field rather than a dropdown select box because of scale. If you have 3000 pages, you don't want to scroll down to find page
- The pagination is grouped in a singular visual component to indicate similarity in purpose.