Introduction To Sybase, Part 3
Welcome Back! In the first two parts of this series, we installed the Sybase database and configured the Perl language to work with the database. In part three, we will create a web application using our newly installed database server. Before you can manage an application using the Sybase server, some background information is in order. I will assume you have read the two previous articles in the series.
The example program is a bookstore on the Web. We will discuss all aspects of creating and maintaining a client-server application using the Sybase SQL server. You won't be an expert after reading the article, but you'll have a good idea of what needs to be done for client-server applications. The example application will not be able to compete with Amazon.com, but it will give you an idea of how to design a client-server application. We'll first take a look at some Sybase SQL server basics.
The Sybase SQL Server is a transactional database server. A transaction is a single piece of work. For example, placing an order would be considered one transaction. Moving money from one account to another is one transaction. Even if a transaction affects two tables in our database, the entire transaction should be completed or should not happen at all—it should never be half-completed. For example, if you want to transfer $100 from your savings account to your checking account, you either want the transfer to happen or not happen. You don't want the $100 to be removed from your savings account but not placed in your checking account. The SQL to accomplish this transfer would look something like this:
update accounts_t set balance = balance - 100 where account_nbr = 'mysaving' update accounts_t set balance = balance + 100 where account_nbr = 'mychecking'
The bank wouldn't want the first update to execute without the second one. If it were my account, I know I wouldn't. The Sybase SQL Server allows the developer to denote where a transaction begins and where it ends.
begin transaction update accounts_t set balance = balance - 100 where account_nbr = 'mysaving' if @@error != 0 begin rollback transaction return end update accounts_t set balance = balance + 100 where account_nbr = 'mychecking' if @@error != 0 begin rollback transaction return end commit transaction if @@error != 0 begin rollback transaction endIf you do not use the begin transaction and commit transaction commands, the database server will assume each SQL command is a single transaction. Make sure you use transaction control in your application where it is needed. For more information on transactions, see Chapter 17 in the Transact-SQL User's Guide.
The SQL Server uses a log to keep track of all transactions. Each database has its own log. The log is part of the database and is not human readable. Each change made to a database is saved in the database's transaction log. Some databases save their data and log information in the same area. Most databases have separate areas for the data and their log. Each area of a database is called a segment. By default, a database has three segments:
System: stores the database's system tables.
Log: stores the database's transaction log.
Default: stores all other database objects.
You can create a database where all three segments are on the same device. If you do this, you won't have as much control over the database as you'd like. The best way to create a database is to separate the log segment from the system and default segments. When you create the database, you specify which devices to put the database on. For more information on these segments and on creating your own custom segments, look in chapter 16 of the System Administration Guide (see Resources). For more information on creating databases, look in chapter 14. In our example program, a database called book_d is created with 20MB allocated for data and 10MB for log.
All transactions that modify a database are saved in the database's transaction log. The data in this log will keep increasing until you back up the log to tape or disk. The data in the log will remain even after all transactions are committed. It stays until the log segment is backed up. This means you need to back up your database often, or this log segment will fill up. When the log segment fills up, you cannot make changes to data in this database until you back up the log segment.
A function is available that will allow the database server to automatically call a stored procedure when a segment is filling up. So, you can write a stored procedure to automatically back up the log when the segment is close to full. A stored procedure is an object in the database containing SQL code. An example stored procedure called sp_thresholdaction that will back up the log to disk is included in the application. For more information about Threshold procedures, see chapter 21 of the System Administration Guide.
Just as any other part of a computer system, databases need to be backed up. One approach would be to shut down the database server, then back up the database device files. This could work, but Sybase says a back up made this way is not guaranteed to restore properly. Each database has to keep track of its logs and the sequence of transactions. If any of these are out of sync with the others, Sybase cannot use the database. Fortunately, Sybase has created a backup server to help you back up your databases. It will even let you run your backups while the database is still up. Your bookstore can stay up 24 hours a day, 7 days a week.
You can back up your databases and logs to either disk or tape using the Sybase backup server. To back up to tape, you'll need to configure your tape device. Read Chapter 18 of the System Administration Guide to learn how to configure your tape drive.
Depending on the size of your databases, I would recommend backing up the logs at least once during the day and the databases every night. If your databases are huge, you might not be able to do this. Back up the logs as often as you can, but think of log backups as changes made to the database. If the database gets corrupted, you'll need to restore the database, then all the logs you backed up since the database backup was made.
If you choose to save logs to a disk drive, I would highly recommend they be saved on a separate disk from the one holding your database. On one of our production database servers, we back up the logs to disk at noon each day, then FTP them to another system. This system has 20 1GB drives on it, so databases and logs are located on different drives, and the log backups are on yet another disk. For best performance, it would be best to keep everything on separate small drives. The system can read and write to multiple drives faster than to a large single drive.
Each time you boot your Linux system, the fsck program is run against all your file systems. The fsck program makes sure all the directories and data are consistent. It is possible for a file system to become out of sync, causing a loss of data.
The Sybase database server has a similar command. It is called dbcc (database consistency check). This command makes sure all data allocations are proper and accounted for. These checks should be run regularly on your databases. They can be scheduled just as you schedule your backups.
You can download the entire application from the Linux Journal FTP server at ftp://ftp.linuxjournal.com/pub/lj/listings/issue64/. To save space, the entire application isn't presented here. There are two tar files: 3250src.tgz and 3250cgi.tgz. The first one has the source code for all database objects. Log in as the sybase user and unpack the tar files. Read the README file before installing. You'll need to install the pubs2 example database shipped with the server. The second tar file has all CGI scripts and other files needed for the application. These files should be placed in the /cgi-bin directory of your web server. Again, read the README file before installing. Sybase and Sybperl must be installed to use this application. Information on this installation is in the first two parts of this article.
This isn't an article about web development, so I won't go into great detail about the web aspects of the application. It also isn't a web application beauty contest. You will see I didn't spend much time making it look nice. I'm sure you can find the time to make the application look the way you like it.
If you installed the application in the default location, you can start a web browser on your system and go to http://localhost/cgi-bin/store/store/ to run the application. If you receive a “File Not Found” error message, your CGI application cannot be found. On a default Red Hat 5.x system, the CGI perl script should be located at /home/httpd/cgi-bin/store/store.
If you received an Internal Server Error message, your Perl program probably isn't located at /usr/bin/perl. Edit the file /home/httpd/cgi-bin/store/store/ and modify the path for Perl to point to your Perl executable. One way to figure out the problem is to run the Perl script at the command line. You should receive HTML. If you receive an error message, you'll need to resolve this problem.
If you receive the store menu, click on Search for Books. If you receive an error message, your client cannot connect to the database. Look at the file /home/httpd/cgi-bin/store/store.inc/. You may need to change the name of the database server. Make sure your database server is up and running. You should be able to connect to it using the user name and password in the store.inc file. Use the isql program at the command line to test this.
Each screen of the application has a subroutine written in Perl. The subroutine is named after the last part of the URL. To search for books, the URL would be http://localhost/cgi-bin/store/store/search/. The subroutine responsible for this is called search.
In our application, we use two databases. The first is the pubs2 example database. We use the titles table as the list of books. This table is read-only. We just view it; the application does not make changes to it. The second database is called book_d and it is created on two devices. The log segment is on device02 and has 10MB allocated to it. The data segment is on device01 and has 20MB allocated to it. There are five tables in this database.
inventory_t: this table is a one-to-one relationship to the titles table in the pubs2 database. There is one row in this table for each row in the titles table. This table contains the number of books in stock and the number on order.
orders_t: this table is a list of customer orders.
order_nbr_t: this table has one row in it. It is used to guarantee that the order number is always unique.
types_t: this table is a list of the types of books. It is used to populate the drop-down box on the search screen.
user_t: this table is a list of customers.
To provide access to the data, we use stored procedures in all cases except one. Stored procedures are SQL code stored in the database. This allows us to encapsulate procedures in the database so it doesn't have to be replicated in all your applications. It also provides a performance benefit. When the stored procedure is loaded, the SQL is precompiled. When the application runs, the server doesn't have to precompile the SQL, so the application should run faster. We used SQL in the search1 procedure, because it would change dramatically depending on the parameters given.
In the scripts, we have also created a user to access the database. Each time the CGI script runs, it logs in as this user. The end users of your application do not need to know this, and in fact, shouldn't know it. Even though this user has the minimum rights necessary to run the application, you should protect this user name and password.
This is a very small application. A few more things must be done if you put this application into production.
Make it look nicer. This application would have looked fine in the early 90's, but in today's world, it would need to look much better before people would use it.
Prepare and schedule automatic backups. Use cron to back up your data at regular intervals.
Prepare and schedule database consistency checks. These should be run regularly, again using cron to schedule these checks.
Create and tune table indexes. These tables have no defined indexes. An index is extra data about the table that will allow the database server to access the data faster.
Explaining how the database server uses indexes is beyond the scope of this article—I have a complete book on the subject. Before you put an application into production, you should load example data in all the tables and test queries to be run in your application. Based on the queries, you can make good guesses as to which indexes will be needed. There is a command in SQL that can help tune indexes. It is set showplan on. Entire book chapters are devoted to explaining this command and its output.
As you can see, using a Sybase database as the basis for your client-server applications is not a trivial task. The Sybase database server is an industrial-strength database, capable of handling hundreds of users and many gigabytes of data. Many databases are available for Linux. Of the free ones, I believe the Sybase database server is the most powerful. If you don't need a powerful database, there may be better choices. If, however, you need a high-power database to manage a large amount of data or many users, a Sybase database server would be a solid foundation.
Jay Sissom (firstname.lastname@example.org) is responsible for the web-based front end to the financial decision support data at Indiana University. He has installed and supported Sybase databases on many operating systems and has written database clients for the web. When not programming, he enjoys amateur radio and playing his bass guitar and keyboards.