提交 81c34acc authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 9030e8e7
...@@ -54,22 +54,27 @@ Advanced Topics ...@@ -54,22 +54,27 @@ Advanced Topics
<h2>Result Sets</h2> <h2>Result Sets</h2>
<h3>Limiting the Number of Rows</h3> <h3>Limiting the Number of Rows</h3>
<p>
Before the result is returned to the application, all rows are read by the database. Before the result is returned to the application, all rows are read by the database.
Server side cursors are not supported currently. Server side cursors are not supported currently.
If only the first few rows are interesting for the application, then the If only the first few rows are interesting for the application, then the
result set size should be limited to improve the performance. result set size should be limited to improve the performance.
This can be done using LIMIT in a query (example: SELECT * FROM TEST LIMIT 100), This can be done using LIMIT in a query (example: SELECT * FROM TEST LIMIT 100),
or by using Statement.setMaxRows(max). or by using Statement.setMaxRows(max).
</p>
<h3>Large Result Sets and External Sorting</h3> <h3>Large Result Sets and External Sorting</h3>
<p>
For result set larger than 1000 rows, the result is buffered to disk. If ORDER BY is used, For result set larger than 1000 rows, the result is buffered to disk. If ORDER BY is used,
the sorting is done using an external sort algorithm. In this case, each block of rows is sorted using the sorting is done using an external sort algorithm. In this case, each block of rows is sorted using
quick sort, then written to disk; when reading the data, the blocks are merged together. quick sort, then written to disk; when reading the data, the blocks are merged together.
</p>
<br /><a name="large_objects"></a> <br /><a name="large_objects"></a>
<h2>Large Objects</h2> <h2>Large Objects</h2>
<h3>Storing and Reading Large Objects</h3> <h3>Storing and Reading Large Objects</h3>
<p>
If it is possible that the objects don't fit into memory, then the data type If it is possible that the objects don't fit into memory, then the data type
CLOB (for textual data) or BLOB (for binary data) should be used. CLOB (for textual data) or BLOB (for binary data) should be used.
For these data types, the objects are not fully read into memory, by using streams. For these data types, the objects are not fully read into memory, by using streams.
...@@ -78,26 +83,29 @@ PreparedStatement.setCharacterStream. To read a BLOB, use ResultSet.getBinaryStr ...@@ -78,26 +83,29 @@ PreparedStatement.setCharacterStream. To read a BLOB, use ResultSet.getBinaryStr
and to read a CLOB, use ResultSet.getCharacterStream. and to read a CLOB, use ResultSet.getCharacterStream.
If the client/server mode is used, the BLOB and CLOB data is fully read into memory when If the client/server mode is used, the BLOB and CLOB data is fully read into memory when
accessed. In this case, the size of a BLOB or CLOB is limited by the memory. accessed. In this case, the size of a BLOB or CLOB is limited by the memory.
</p>
<br /><a name="linked_tables"></a> <br /><a name="linked_tables"></a>
<h2>Linked Tables</h2> <h2>Linked Tables</h2>
<p>
This database supports linked tables, which means tables that don't exist in the current database but This database supports linked tables, which means tables that don't exist in the current database but
are just links to another database. To create such a link, use the CREATE LINKED TABLE statement: are just links to another database. To create such a link, use the CREATE LINKED TABLE statement:
</p>
<pre> <pre>
CREATE LINKED TABLE LINK('org.postgresql.Driver', 'jdbc:postgresql:test', 'sa', 'sa', 'TEST'); CREATE LINKED TABLE LINK('org.postgresql.Driver', 'jdbc:postgresql:test', 'sa', 'sa', 'TEST');
</pre> </pre>
<p>
It is then possible to access the table in the usual way. It is then possible to access the table in the usual way.
There is a restriction when inserting data to this table: When inserting or updating rows into the table, There is a restriction when inserting data to this table: When inserting or updating rows into the table,
NULL and values that are not set in the insert statement are both inserted as NULL. NULL and values that are not set in the insert statement are both inserted as NULL.
This may not have the desired effect if a default value in the target table is other than NULL. This may not have the desired effect if a default value in the target table is other than NULL.
</p>
<br /><a name="transaction_isolation"></a> <br /><a name="transaction_isolation"></a>
<h2>Transaction Isolation</h2> <h2>Transaction Isolation</h2>
<p> <p>
This database supports the following transaction isolation levels: This database supports the following transaction isolation levels:
</p> </p>
<ul> <ul>
<li><b>Serializable</b><br /> <li><b>Serializable</b><br />
This is the default level.<br /> This is the default level.<br />
...@@ -115,11 +123,9 @@ This database supports the following transaction isolation levels: ...@@ -115,11 +123,9 @@ This database supports the following transaction isolation levels:
or append ;LOCK_MODE=0 to the database URL: jdbc:h2:~/test;LOCK_MODE=0 or append ;LOCK_MODE=0 to the database URL: jdbc:h2:~/test;LOCK_MODE=0
</li> </li>
</ul> </ul>
<p> <p>
When using the isolation level 'serializable', dirty reads, non-repeatable reads, and phantom reads are prohibited. When using the isolation level 'serializable', dirty reads, non-repeatable reads, and phantom reads are prohibited.
</p> </p>
<ul> <ul>
<li><b>Dirty Reads</b><br /> <li><b>Dirty Reads</b><br />
Means a connection can read uncommitted changes made by another connection.<br /> Means a connection can read uncommitted changes made by another connection.<br />
...@@ -137,6 +143,7 @@ When using the isolation level 'serializable', dirty reads, non-repeatable reads ...@@ -137,6 +143,7 @@ When using the isolation level 'serializable', dirty reads, non-repeatable reads
</ul> </ul>
<h3>Table Level Locking</h3> <h3>Table Level Locking</h3>
<p>
The database allows multiple concurrent connections to the same database. The database allows multiple concurrent connections to the same database.
To make sure all connections only see consistent data, table level locking is used. To make sure all connections only see consistent data, table level locking is used.
This mechanism does not allow high concurrency, but is very fast. This mechanism does not allow high concurrency, but is very fast.
...@@ -149,14 +156,17 @@ to write to a table (update or delete a row), an exclusive lock is required. To ...@@ -149,14 +156,17 @@ to write to a table (update or delete a row), an exclusive lock is required. To
exclusive lock, other connection must not have any locks on the object. After the exclusive lock, other connection must not have any locks on the object. After the
connection commits, all locks are released. connection commits, all locks are released.
This database keeps all locks in memory. This database keeps all locks in memory.
</p>
<h3>Lock Timeout</h3> <h3>Lock Timeout</h3>
<p>
If a connection cannot get a lock on an object, the connection waits for some amount If a connection cannot get a lock on an object, the connection waits for some amount
of time (the lock timeout). During this time, hopefully the connection holding the of time (the lock timeout). During this time, hopefully the connection holding the
lock commits and it is then possible to get the lock. If this is not possible because lock commits and it is then possible to get the lock. If this is not possible because
the other connection does not release the lock for some time, the unsuccessful the other connection does not release the lock for some time, the unsuccessful
connection will get a lock timeout exception. The lock timeout can be set individually connection will get a lock timeout exception. The lock timeout can be set individually
for each connection. for each connection.
</p>
<br /><a name="clustering"></a> <br /><a name="clustering"></a>
<h2>Clustering / High Availability</h2> <h2>Clustering / High Availability</h2>
...@@ -167,6 +177,7 @@ same database. If both servers run, each database operation is executed on both ...@@ -167,6 +177,7 @@ same database. If both servers run, each database operation is executed on both
If one server fails (power, hardware or network failure), the other server can still continue to work. If one server fails (power, hardware or network failure), the other server can still continue to work.
From this point on, the operations will be executed only on one server until the other server From this point on, the operations will be executed only on one server until the other server
is back up. is back up.
</p><p>
Clustering can only be used in the server mode (the embedded mode does not support clustering). Clustering can only be used in the server mode (the embedded mode does not support clustering).
It is possible to restore the cluster without stopping the server, however it is critical that no other It is possible to restore the cluster without stopping the server, however it is critical that no other
application is changing the data in the first database while the second database is restored, so application is changing the data in the first database while the second database is restored, so
...@@ -183,9 +194,11 @@ To initialize the cluster, use the following steps: ...@@ -183,9 +194,11 @@ To initialize the cluster, use the following steps:
</li></ul> </li></ul>
<h3>Using the CreateCluster Tool</h3> <h3>Using the CreateCluster Tool</h3>
<p>
To understand how clustering works, please try out the following example. To understand how clustering works, please try out the following example.
In this example, the two databases reside on the same computer, but usually, the In this example, the two databases reside on the same computer, but usually, the
databases will be on different servers. databases will be on different servers.
</p>
<ul> <ul>
<li>Create two directories: server1 and server2. <li>Create two directories: server1 and server2.
Each directory will simulate a directory on a computer. Each directory will simulate a directory on a computer.
...@@ -226,6 +239,7 @@ and re-run the CreateCluster tool. ...@@ -226,6 +239,7 @@ and re-run the CreateCluster tool.
</li></ul> </li></ul>
<h3>Clustering Algorithm and Limitations</h3> <h3>Clustering Algorithm and Limitations</h3>
<p>
Read-only queries are only executed against the first cluster node, but all other statements are Read-only queries are only executed against the first cluster node, but all other statements are
executed against all nodes. There is currently no load balancing made to avoid problems with executed against all nodes. There is currently no load balancing made to avoid problems with
transactions. The following functions may yield different results on different cluster nodes and must be transactions. The following functions may yield different results on different cluster nodes and must be
...@@ -233,10 +247,13 @@ executed with care: RANDOM_UUID(), SECURE_RAND(), SESSION_ID(), MEMORY_FREE(), M ...@@ -233,10 +247,13 @@ executed with care: RANDOM_UUID(), SECURE_RAND(), SESSION_ID(), MEMORY_FREE(), M
CSVREAD(), CSVWRITE(), RAND() [when not using a seed]. Those functions should not be used CSVREAD(), CSVWRITE(), RAND() [when not using a seed]. Those functions should not be used
directly in modifying statements (for example INSERT, UPDATE, or MERGE). However, they can be used directly in modifying statements (for example INSERT, UPDATE, or MERGE). However, they can be used
in read-only statements and the result can then be used for modifying statements. in read-only statements and the result can then be used for modifying statements.
</p>
<br /><a name="two_phase_commit"></a> <br /><a name="two_phase_commit"></a>
<h2>Two Phase Commit</h2> <h2>Two Phase Commit</h2>
<p>
The two phase commit protocol is supported. 2-phase-commit works as follows: The two phase commit protocol is supported. 2-phase-commit works as follows:
</p>
<ul> <ul>
<li>Autocommit needs to be switched off <li>Autocommit needs to be switched off
</li><li>A transaction is started, for example by inserting a row </li><li>A transaction is started, for example by inserting a row
...@@ -255,14 +272,17 @@ The two phase commit protocol is supported. 2-phase-commit works as follows: ...@@ -255,14 +272,17 @@ The two phase commit protocol is supported. 2-phase-commit works as follows:
<br /><a name="compatibility"></a> <br /><a name="compatibility"></a>
<h2>Compatibility</h2> <h2>Compatibility</h2>
<p>
This database is (up to a certain point) compatible to other databases such as HSQLDB, MySQL and PostgreSQL. This database is (up to a certain point) compatible to other databases such as HSQLDB, MySQL and PostgreSQL.
There are certain areas where H2 is incompatible. There are certain areas where H2 is incompatible.
</p>
<h3>Transaction Commit when Autocommit is On</h3> <h3>Transaction Commit when Autocommit is On</h3>
<p>
At this time, this database engine commits a transaction (if autocommit is switched on) just before returning the result. At this time, this database engine commits a transaction (if autocommit is switched on) just before returning the result.
For a query, this means the transaction is committed even before the application scans through the result set, and before the result set is closed. For a query, this means the transaction is committed even before the application scans through the result set, and before the result set is closed.
Other database engines may commit the transaction in this case when the result set is closed. Other database engines may commit the transaction in this case when the result set is closed.
</p>
<h3>Keywords / Reserved Words</h3> <h3>Keywords / Reserved Words</h3>
<p> <p>
...@@ -279,43 +299,57 @@ for example CURRENT_TIMESTAMP. ...@@ -279,43 +299,57 @@ for example CURRENT_TIMESTAMP.
<br /><a name="windows_service"></a> <br /><a name="windows_service"></a>
<h2>Run as Windows Service</h2> <h2>Run as Windows Service</h2>
<p>
Using a native wrapper / adapter, Java applications can be run as a Windows Service. Using a native wrapper / adapter, Java applications can be run as a Windows Service.
There are various tools available to do that. The Java Service Wrapper from Tanuki Software, Inc. There are various tools available to do that. The Java Service Wrapper from Tanuki Software, Inc.
(<a href="http://wrapper.tanukisoftware.org">http://wrapper.tanukisoftware.org</a>) (<a href="http://wrapper.tanukisoftware.org">http://wrapper.tanukisoftware.org</a>)
is included in the installation. Batch files are provided to install, start, stop and uninstall the H2 Database Engine Service. is included in the installation. Batch files are provided to install, start, stop and uninstall the H2 Database Engine Service.
This service contains the TCP Server and the H2 Console web application. This service contains the TCP Server and the H2 Console web application.
The batch files are located in the directory H2/service. The batch files are located in the directory H2/service.
</p>
<h3>Install the Service</h3> <h3>Install the Service</h3>
<p>
The service needs to be registered as a Windows Service first. The service needs to be registered as a Windows Service first.
To do that, double click on 1_install_service.bat. To do that, double click on 1_install_service.bat.
If successful, a command prompt window will pop up and disappear immediately. If not, a message will appear. If successful, a command prompt window will pop up and disappear immediately. If not, a message will appear.
</p>
<h3>Start the Service</h3> <h3>Start the Service</h3>
<p>
You can start the H2 Database Engine Service using the service manager of Windows, You can start the H2 Database Engine Service using the service manager of Windows,
or by double clicking on 2_start_service.bat. or by double clicking on 2_start_service.bat.
Please note that the batch file does not print an error message if the service is not installed. Please note that the batch file does not print an error message if the service is not installed.
</p>
<h3>Connect to the H2 Console</h3> <h3>Connect to the H2 Console</h3>
<p>
After installing and starting the service, you can connect to the H2 Console application using a browser. After installing and starting the service, you can connect to the H2 Console application using a browser.
Double clicking on 3_start_browser.bat to do that. The Double clicking on 3_start_browser.bat to do that. The
default port (8082) is hard coded in the batch file. default port (8082) is hard coded in the batch file.
</p>
<h3>Stop the Service</h3> <h3>Stop the Service</h3>
<p>
To stop the service, double click on 4_stop_service.bat. To stop the service, double click on 4_stop_service.bat.
Please note that the batch file does not print an error message if the service is not installed or started. Please note that the batch file does not print an error message if the service is not installed or started.
</p>
<h3>Uninstall the Service</h3> <h3>Uninstall the Service</h3>
<p>
To uninstall the service, double click on 5_uninstall_service.bat. To uninstall the service, double click on 5_uninstall_service.bat.
If successful, a command prompt window will pop up and disappear immediately. If not, a message will appear. If successful, a command prompt window will pop up and disappear immediately. If not, a message will appear.
</p>
<br /><a name="odbc_driver"></a> <br /><a name="odbc_driver"></a>
<h2>ODBC Driver</h2> <h2>ODBC Driver</h2>
<p>
This database does not come with its own ODBC driver at this time, This database does not come with its own ODBC driver at this time,
but it supports the PostgreSQL network protocol. but it supports the PostgreSQL network protocol.
Therefore, the PostgreSQL ODBC driver can be used. Therefore, the PostgreSQL ODBC driver can be used.
Support for the PostgreSQL network protocol is quite new and should be viewed Support for the PostgreSQL network protocol is quite new and should be viewed
as experimental. It should not be used for production applications. as experimental. It should not be used for production applications.
</p>
<h3>ODBC Installation</h3> <h3>ODBC Installation</h3>
<p> <p>
...@@ -385,15 +419,19 @@ Currently, statements can not be cancelled when using the PG protocol. ...@@ -385,15 +419,19 @@ Currently, statements can not be cancelled when using the PG protocol.
</p> </p>
<h3>Security Considerations</h3> <h3>Security Considerations</h3>
<p>
Currently, the PG Server does not support challenge response or encrypt passwords. Currently, the PG Server does not support challenge response or encrypt passwords.
This may be a problem if an attacker can listen to the data transferred between the ODBC driver This may be a problem if an attacker can listen to the data transferred between the ODBC driver
and the server, because the password is readable to the attacker. and the server, because the password is readable to the attacker.
Also, it is currently not possible to use encrypted SSL connections. Also, it is currently not possible to use encrypted SSL connections.
Therefore the ODBC driver should not be used where security is important. Therefore the ODBC driver should not be used where security is important.
</p>
<br /><a name="acid"></a> <br /><a name="acid"></a>
<h2>ACID</h2> <h2>ACID</h2>
<p>
In the database world, ACID stands for: In the database world, ACID stands for:
</p>
<ul> <ul>
<li>Atomicity: Transactions must be atomic, meaning either all tasks are performed or none. <li>Atomicity: Transactions must be atomic, meaning either all tasks are performed or none.
</li><li>Consistency: All operations must comply with the defined constraints. </li><li>Consistency: All operations must comply with the defined constraints.
...@@ -402,24 +440,32 @@ In the database world, ACID stands for: ...@@ -402,24 +440,32 @@ In the database world, ACID stands for:
</li></ul> </li></ul>
<h3>Atomicity</h3> <h3>Atomicity</h3>
<p>
Transactions in this database are always atomic. Transactions in this database are always atomic.
</p>
<h3>Consistency</h3> <h3>Consistency</h3>
<p>
This database is always in a consistent state. This database is always in a consistent state.
Referential integrity rules are always enforced. Referential integrity rules are always enforced.
</p>
<h3>Isolation</h3> <h3>Isolation</h3>
<p>
For H2, the default isolation level is 'serializable', which means complete isolation. For H2, the default isolation level is 'serializable', which means complete isolation.
The default transaction isolation level for many other databases is 'read committed'. The default transaction isolation level for many other databases is 'read committed'.
This provides better performance, but also means that transactions are not completely isolated. This provides better performance, but also means that transactions are not completely isolated.
H2 supports the transaction isolation levels 'serializable', 'read committed', and 'read uncommitted'. H2 supports the transaction isolation levels 'serializable', 'read committed', and 'read uncommitted'.
</p>
<h3>Durability</h3> <h3>Durability</h3>
<p>
This database does not guarantee that all committed transactions survive a power failure. This database does not guarantee that all committed transactions survive a power failure.
Tests show that all databases sometimes lose transactions on power failure (for details, see below). Tests show that all databases sometimes lose transactions on power failure (for details, see below).
Where losing transactions is not acceptable, a laptop or UPS (uninterruptible power supply) should be used. Where losing transactions is not acceptable, a laptop or UPS (uninterruptible power supply) should be used.
If durability is required for all possible cases of hardware failure, clustering should be used, If durability is required for all possible cases of hardware failure, clustering should be used,
such as the H2 clustering mode. such as the H2 clustering mode.
</p>
<br /><a name="durability_problems"></a> <br /><a name="durability_problems"></a>
<h2>Durability Problems</h2> <h2>Durability Problems</h2>
...@@ -488,6 +534,7 @@ In the performance comparison, commit delay was used for all databases that supp ...@@ -488,6 +534,7 @@ In the performance comparison, commit delay was used for all databases that supp
</p> </p>
<h3>Running the Durability Test</h3> <h3>Running the Durability Test</h3>
<p>
To test the durability / non-durability of this and other databases, you can use the test application To test the durability / non-durability of this and other databases, you can use the test application
in the package org.h2.test.poweroff. Two computers with network connection are required to run this test. in the package org.h2.test.poweroff. Two computers with network connection are required to run this test.
One computer just listens, while the test application is run (and power is cut) on the other computer. One computer just listens, while the test application is run (and power is cut) on the other computer.
...@@ -499,9 +546,11 @@ The listener computer displays the last inserted record number every 10 seconds. ...@@ -499,9 +546,11 @@ The listener computer displays the last inserted record number every 10 seconds.
manually, then restart the computer, and run the application again. You will find out that in most cases, manually, then restart the computer, and run the application again. You will find out that in most cases,
none of the databases contains all the records that the listener computer knows about. For details, please none of the databases contains all the records that the listener computer knows about. For details, please
consult the source code of the listener and test application. consult the source code of the listener and test application.
</p>
<br /><a name="using_recover_tool"></a> <br /><a name="using_recover_tool"></a>
<h2>Using the Recover Tool</h2> <h2>Using the Recover Tool</h2>
<p>
The recover tool can be used to extract the contents of a data file, even if the database is corrupted. The recover tool can be used to extract the contents of a data file, even if the database is corrupted.
At this time, it does not extract the content of the log file or large objects (CLOB or BLOB). At this time, it does not extract the content of the log file or large objects (CLOB or BLOB).
To run the tool, type on the command line: To run the tool, type on the command line:
...@@ -512,6 +561,7 @@ For each database in the current directory, a text file will be created. ...@@ -512,6 +561,7 @@ For each database in the current directory, a text file will be created.
This file contains raw insert statement (for the data) and data definition (DDL) statement to recreate This file contains raw insert statement (for the data) and data definition (DDL) statement to recreate
the schema of the database. This file cannot be executed directly, as the raw insert statements the schema of the database. This file cannot be executed directly, as the raw insert statements
don't have the correct table names, so the file needs to be pre-processed manually before executing. don't have the correct table names, so the file needs to be pre-processed manually before executing.
</p>
<br /><a name="file_locking_protocols"></a> <br /><a name="file_locking_protocols"></a>
<h2>File Locking Protocols</h2> <h2>File Locking Protocols</h2>
...@@ -531,7 +581,9 @@ The two methods are 'file method' and 'socket methods'. ...@@ -531,7 +581,9 @@ The two methods are 'file method' and 'socket methods'.
</p> </p>
<h3>File Locking Method 'File'</h3> <h3>File Locking Method 'File'</h3>
<p>
The default method for database file locking is the 'File Method'. The algorithm is: The default method for database file locking is the 'File Method'. The algorithm is:
</p>
<ul> <ul>
<li>When the lock file does not exist, it is created (using the atomic operation File.createNewFile). <li>When the lock file does not exist, it is created (using the atomic operation File.createNewFile).
Then, the process waits a little bit (20ms) and checks the file again. If the file was changed Then, the process waits a little bit (20ms) and checks the file again. If the file was changed
...@@ -568,8 +620,10 @@ to the user if it cannot open a database, and not try again in a (fast) loop. ...@@ -568,8 +620,10 @@ to the user if it cannot open a database, and not try again in a (fast) loop.
</p> </p>
<h3>File Locking Method 'Socket'</h3> <h3>File Locking Method 'Socket'</h3>
<p>
There is a second locking mechanism implemented, but disabled by default. There is a second locking mechanism implemented, but disabled by default.
The algorithm is: The algorithm is:
</p>
<ul> <ul>
<li>If the lock file does not exist, it is created. <li>If the lock file does not exist, it is created.
Then a server socket is opened on a defined port, and kept open. Then a server socket is opened on a defined port, and kept open.
...@@ -583,14 +637,17 @@ and this process throws an exception (database is in use). If the original proce ...@@ -583,14 +637,17 @@ and this process throws an exception (database is in use). If the original proce
died (for example due to a blackout, or abnormal termination of the virtual machine), died (for example due to a blackout, or abnormal termination of the virtual machine),
then the port was released. The new process deletes the lock file and starts again. then the port was released. The new process deletes the lock file and starts again.
</li></ul> </li></ul>
<p>
This method does not require a watchdog thread actively polling (reading) the same This method does not require a watchdog thread actively polling (reading) the same
file every second. The problem with this method is, if the file is stored on a network file every second. The problem with this method is, if the file is stored on a network
share, two processes (running on different computers) could still open the same share, two processes (running on different computers) could still open the same
database files, if they do not have a direct TCP/IP connection. database files, if they do not have a direct TCP/IP connection.
<p>
<br /><a name="sql_injection"></a> <br /><a name="sql_injection"></a>
<h2>Protection against SQL Injection</h2> <h2>Protection against SQL Injection</h2>
<h3>What is SQL Injection</h3> <h3>What is SQL Injection</h3>
<p>
This database engine provides a solution for the security vulnerability known as 'SQL Injection'. This database engine provides a solution for the security vulnerability known as 'SQL Injection'.
Here is a short description of what SQL injection means. Here is a short description of what SQL injection means.
Some applications build SQL statements with embedded user input such as: Some applications build SQL statements with embedded user input such as:
...@@ -606,8 +663,10 @@ SELECT * FROM USERS WHERE PASSWORD='' OR ''=''; ...@@ -606,8 +663,10 @@ SELECT * FROM USERS WHERE PASSWORD='' OR ''='';
</pre> </pre>
Which is always true no matter what the password stored in the database is. Which is always true no matter what the password stored in the database is.
For more information about SQL Injection, see Glossary and Links. For more information about SQL Injection, see Glossary and Links.
</p>
<h3>Disabling Literals</h3> <h3>Disabling Literals</h3>
<p>
SQL Injection is not possible if user input is not directly embedded in SQL statements. SQL Injection is not possible if user input is not directly embedded in SQL statements.
A simple solution for the problem above is to use a PreparedStatement: A simple solution for the problem above is to use a PreparedStatement:
<pre> <pre>
...@@ -630,8 +689,10 @@ do not include literals. ...@@ -630,8 +689,10 @@ do not include literals.
There is also a second mode where number literals are allowed: SET ALLOW_LITERALS NUMBERS. There is also a second mode where number literals are allowed: SET ALLOW_LITERALS NUMBERS.
To allow all literals, execute SET ALLOW_LITERALS ALL (this is the default setting). To allow all literals, execute SET ALLOW_LITERALS ALL (this is the default setting).
Literals can only be enabled or disabled by an administrator. Literals can only be enabled or disabled by an administrator.
</p>
<h3>Using Constants</h3> <h3>Using Constants</h3>
<p>
Disabling literals also means disabling hard-coded 'constant' literals. This database supports Disabling literals also means disabling hard-coded 'constant' literals. This database supports
defining constants using the CREATE CONSTANT command. Constants can be defined only defining constants using the CREATE CONSTANT command. Constants can be defined only
when literals are enabled, but used even when literals are disabled. To avoid name clashes when literals are enabled, but used even when literals are disabled. To avoid name clashes
...@@ -645,18 +706,23 @@ SELECT * FROM USERS WHERE TYPE=CONST.ACTIVE; ...@@ -645,18 +706,23 @@ SELECT * FROM USERS WHERE TYPE=CONST.ACTIVE;
Even when literals are enabled, it is better to use constants instead Even when literals are enabled, it is better to use constants instead
of hard-coded number or text literals in queries or views. With constants, typos are found at compile of hard-coded number or text literals in queries or views. With constants, typos are found at compile
time, the source code is easier to understand and change. time, the source code is easier to understand and change.
</p>
<h3>Using the ZERO() Function</h3> <h3>Using the ZERO() Function</h3>
<p>
It is not required to create a constant for the number 0 as there is already a built-in function ZERO(): It is not required to create a constant for the number 0 as there is already a built-in function ZERO():
<pre> <pre>
SELECT * FROM USERS WHERE LENGTH(PASSWORD)=ZERO(); SELECT * FROM USERS WHERE LENGTH(PASSWORD)=ZERO();
</pre> </pre>
</p>
<br /><a name="security_protocols"></a> <br /><a name="security_protocols"></a>
<h2>Security Protocols</h2> <h2>Security Protocols</h2>
<p>
The following paragraphs document the security protocols used in this database. The following paragraphs document the security protocols used in this database.
These descriptions are very technical and only intended for security experts that already know These descriptions are very technical and only intended for security experts that already know
the underlying security primitives. the underlying security primitives.
</p>
<h3>User Password Encryption</h3> <h3>User Password Encryption</h3>
<p> <p>
...@@ -736,17 +802,22 @@ database operations take about 2.2 times longer when using XTEA, and 2.5 times l ...@@ -736,17 +802,22 @@ database operations take about 2.2 times longer when using XTEA, and 2.5 times l
</p> </p>
<h3>SSL/TLS Connections</h3> <h3>SSL/TLS Connections</h3>
<p>
Remote SSL/TLS connections are supported using the Java Secure Socket Extension Remote SSL/TLS connections are supported using the Java Secure Socket Extension
(SSLServerSocket / SSLSocket). By default, anonymous SSL is enabled. (SSLServerSocket / SSLSocket). By default, anonymous SSL is enabled.
The default cipher suite is <code>SSL_DH_anon_WITH_RC4_128_MD5</code>. The default cipher suite is <code>SSL_DH_anon_WITH_RC4_128_MD5</code>.
</p>
<h3>HTTPS Connections</h3> <h3>HTTPS Connections</h3>
<p>
The web server supports HTTP and HTTPS connections using SSLServerSocket. The web server supports HTTP and HTTPS connections using SSLServerSocket.
There is a default self-certified certificate to support an easy starting point, but There is a default self-certified certificate to support an easy starting point, but
custom certificates are supported as well. custom certificates are supported as well.
</p>
<br /><a name="uuid"></a> <br /><a name="uuid"></a>
<h2>Universally Unique Identifiers (UUID)</h2> <h2>Universally Unique Identifiers (UUID)</h2>
<p>
This database supports the UUIDs. Also supported is a function to create new UUIDs using This database supports the UUIDs. Also supported is a function to create new UUIDs using
a cryptographically strong pseudo random number generator. a cryptographically strong pseudo random number generator.
With random UUIDs, the chance of two having the same value can be calculated With random UUIDs, the chance of two having the same value can be calculated
...@@ -773,6 +844,7 @@ Some values are: ...@@ -773,6 +844,7 @@ Some values are:
</pre> </pre>
One's annual risk of being hit by a meteorite is estimated to be one chance in 17 billion, One's annual risk of being hit by a meteorite is estimated to be one chance in 17 billion,
that means the probability is about 0.000'000'000'06. that means the probability is about 0.000'000'000'06.
</p>
<br /><a name="system_properties"></a> <br /><a name="system_properties"></a>
<h2>Settings Read from System Properties</h2> <h2>Settings Read from System Properties</h2>
...@@ -781,11 +853,9 @@ Some settings of the database can be set on the command line using ...@@ -781,11 +853,9 @@ Some settings of the database can be set on the command line using
-DpropertyName=value. It is usually not required to change those settings manually. -DpropertyName=value. It is usually not required to change those settings manually.
The settings are case sensitive. The settings are case sensitive.
Example: Example:
</p>
<pre> <pre>
java -Dh2.serverCachedObjects=256 org.h2.tools.Server java -Dh2.serverCachedObjects=256 org.h2.tools.Server
</pre> </pre>
<p>
The current value of the settings can be read in the table The current value of the settings can be read in the table
INFORMATION_SCHEMA.SETTINGS INFORMATION_SCHEMA.SETTINGS
</p> </p>
......
...@@ -212,22 +212,27 @@ Features ...@@ -212,22 +212,27 @@ Features
</table> </table>
<h3>Derby and HSQLDB</h3> <h3>Derby and HSQLDB</h3>
<p>
After an unexpected process termination (for example power failure), H2 can recover safely and After an unexpected process termination (for example power failure), H2 can recover safely and
automatically without any user interaction. For Derby and HSQLDB, there are some manual steps required automatically without any user interaction. For Derby and HSQLDB, there are some manual steps required
('Another instance of Derby may have already booted the database' / ('Another instance of Derby may have already booted the database' /
'The database is already in use by another process'). 'The database is already in use by another process').
</p>
<h3>DaffodilDb and One$Db</h3> <h3>DaffodilDb and One$Db</h3>
<p>
It looks like the development of this database has stopped. The last release was February 2006. It looks like the development of this database has stopped. The last release was February 2006.
</p>
<h3>McKoi</h3> <h3>McKoi</h3>
<p>
It looks like the development of this database has stopped. The last release was August 2004 It looks like the development of this database has stopped. The last release was August 2004
</p>
<br /><a name="products_work_with"></a> <br /><a name="products_work_with"></a>
<h2>Products that Work with H2</h2> <h2>Products that Work with H2</h2>
<table> <table>
<tr><th>Product</th><th>Description</th></tr> <tr><th>Product</th><th>Description</th></tr>
<tr> <tr>
<td><a href="http://jackrabbit.apache.org">Apache Jackrabbit</a></td> <td><a href="http://jackrabbit.apache.org">Apache Jackrabbit</a></td>
<td>Open source implementation of the Java Content Repository API (JCR).</td> <td>Open source implementation of the Java Content Repository API (JCR).</td>
...@@ -314,7 +319,9 @@ It looks like the development of this database has stopped. The last release was ...@@ -314,7 +319,9 @@ It looks like the development of this database has stopped. The last release was
<br /><a name="connection_modes"></a> <br /><a name="connection_modes"></a>
<h2>Connection Modes</h2> <h2>Connection Modes</h2>
<p>
The following connection modes are supported: The following connection modes are supported:
</p>
<ul> <ul>
<li>Local connections using JDBC (embedded) <li>Local connections using JDBC (embedded)
</li><li>Remote connections using JDBC over TCP/IP (client/server) </li><li>Remote connections using JDBC over TCP/IP (client/server)
...@@ -436,12 +443,14 @@ This is achieved using different database URLs. The settings in the URLs are not ...@@ -436,12 +443,14 @@ This is achieved using different database URLs. The settings in the URLs are not
</table> </table>
<h3>Connecting to an Embedded (Local) Database</h3> <h3>Connecting to an Embedded (Local) Database</h3>
<p>
The database URL for connecting to a local database is <code>jdbc:h2:[file:][&lt;path&gt;]&lt;databaseName&gt;</code>. The database URL for connecting to a local database is <code>jdbc:h2:[file:][&lt;path&gt;]&lt;databaseName&gt;</code>.
The prefix <code>file:</code> is optional. If no or only a relative path is used, then the current working The prefix <code>file:</code> is optional. If no or only a relative path is used, then the current working
directory is used as a starting point. The case sensitivity of the path and database name depend on the directory is used as a starting point. The case sensitivity of the path and database name depend on the
operating system, however it is suggested to use lowercase letters only. operating system, however it is suggested to use lowercase letters only.
The database name must be at least three characters long (a limitation of File.createTempFile). The database name must be at least three characters long (a limitation of File.createTempFile).
To point to the user home directory, use ~/, as in: jdbc:h2:~/test. To point to the user home directory, use ~/, as in: jdbc:h2:~/test.
</p>
<h3>Memory-Only Databases</h3> <h3>Memory-Only Databases</h3>
<p> <p>
...@@ -467,6 +476,7 @@ An example database URL is: <code>jdbc:h2:tcp://localhost/mem:db1</code> ...@@ -467,6 +476,7 @@ An example database URL is: <code>jdbc:h2:tcp://localhost/mem:db1</code>
<br /><a name="file_encryption"></a> <br /><a name="file_encryption"></a>
<h2>Connecting to a Database with File Encryption</h2> <h2>Connecting to a Database with File Encryption</h2>
<p>
To use file encryption, it is required to specify the encryption algorithm (the 'cipher') To use file encryption, it is required to specify the encryption algorithm (the 'cipher')
and the file password. The algorithm needs to be specified using the connection parameter. and the file password. The algorithm needs to be specified using the connection parameter.
Two algorithms are supported: XTEA and AES. The file password is specified in the password field, Two algorithms are supported: XTEA and AES. The file password is specified in the password field,
...@@ -474,6 +484,7 @@ before the user password. A single space needs to be added between the file pass ...@@ -474,6 +484,7 @@ before the user password. A single space needs to be added between the file pass
and the user password; the file password itself may not contain spaces. File passwords and the user password; the file password itself may not contain spaces. File passwords
(as well as user passwords) are case sensitive. Here is an example to connect to a password (as well as user passwords) are case sensitive. Here is an example to connect to a password
encrypted database: encrypted database:
</p>
<pre> <pre>
Class.forName("org.h2.Driver"); Class.forName("org.h2.Driver");
String url = "jdbc:h2:~/test;CIPHER=AES"; String url = "jdbc:h2:~/test;CIPHER=AES";
...@@ -501,6 +512,7 @@ if the database files are only accessed by the one (and always the same) compute ...@@ -501,6 +512,7 @@ if the database files are only accessed by the one (and always the same) compute
</li><li>It is also possible to open the database without file locking; </li><li>It is also possible to open the database without file locking;
in this case it is up to the application to protect the database files. in this case it is up to the application to protect the database files.
</li></ul> </li></ul>
<p>
To open the database with a different file locking method, use the parameter 'FILE_LOCK'. To open the database with a different file locking method, use the parameter 'FILE_LOCK'.
The following code opens the database with the 'socket' locking method: The following code opens the database with the 'socket' locking method:
<pre> <pre>
...@@ -514,9 +526,11 @@ String url = "jdbc:h2:~/test;FILE_LOCK=NO"; ...@@ -514,9 +526,11 @@ String url = "jdbc:h2:~/test;FILE_LOCK=NO";
</pre> </pre>
For more information about the algorithms please see in Advanced Topics under For more information about the algorithms please see in Advanced Topics under
File Locking Protocol. File Locking Protocol.
</p>
<br /><a name="database_only_if_exists"></a> <br /><a name="database_only_if_exists"></a>
<h2>Opening a Database Only if it Already Exists</h2> <h2>Opening a Database Only if it Already Exists</h2>
<p>
By default, when an application calls <code>DriverManager.getConnection(url,...)</code> By default, when an application calls <code>DriverManager.getConnection(url,...)</code>
and the database specified in the URL does not yet exist, a new (empty) database is created. and the database specified in the URL does not yet exist, a new (empty) database is created.
In some situations, it is better to restrict creating new database, and only open In some situations, it is better to restrict creating new database, and only open
...@@ -524,6 +538,7 @@ the database if it already exists. This can be done by adding <code>;ifexists=tr ...@@ -524,6 +538,7 @@ the database if it already exists. This can be done by adding <code>;ifexists=tr
to the URL. In this case, if the database does not already exist, an exception is thrown when to the URL. In this case, if the database does not already exist, an exception is thrown when
trying to connect. The connection only succeeds when the database already exists. trying to connect. The connection only succeeds when the database already exists.
The complete URL may look like this: The complete URL may look like this:
</p>
<pre> <pre>
String url = "jdbc:h2:/data/sample;IFEXISTS=TRUE"; String url = "jdbc:h2:/data/sample;IFEXISTS=TRUE";
</pre> </pre>
...@@ -532,6 +547,7 @@ String url = "jdbc:h2:/data/sample;IFEXISTS=TRUE"; ...@@ -532,6 +547,7 @@ String url = "jdbc:h2:/data/sample;IFEXISTS=TRUE";
<h2>Closing the Database</h2> <h2>Closing the Database</h2>
<h3>Delayed Database Closing</h3> <h3>Delayed Database Closing</h3>
<p>
Usually, the database is closed when the last connection to it is closed. In some situations Usually, the database is closed when the last connection to it is closed. In some situations
this slows down the application, for example when it is not possible leave the connection open. this slows down the application, for example when it is not possible leave the connection open.
The automatic closing of the database can be delayed or disabled with the SQL statement The automatic closing of the database can be delayed or disabled with the SQL statement
...@@ -545,8 +561,10 @@ The value -1 means the database is never closed automatically. ...@@ -545,8 +561,10 @@ The value -1 means the database is never closed automatically.
The value 0 is the default and means the database is closed when the last connection is closed. The value 0 is the default and means the database is closed when the last connection is closed.
This setting is persistent and can be set by an administrator only. This setting is persistent and can be set by an administrator only.
It is possible to set the value in the database URL: <code>jdbc:h2:~/test;DB_CLOSE_DELAY=10</code>. It is possible to set the value in the database URL: <code>jdbc:h2:~/test;DB_CLOSE_DELAY=10</code>.
</p>
<h3>Don't Close the Database when the VM Exits</h3> <h3>Don't Close the Database when the VM Exits</h3>
<p>
By default, a database is closed when the last connection is closed. However, if it is never closed, By default, a database is closed when the last connection is closed. However, if it is never closed,
the database is closed when the virtual machine exits normally. This is done using a shutdown hook. the database is closed when the virtual machine exits normally. This is done using a shutdown hook.
In some situations, the database should not be closed in this case, for example because the In some situations, the database should not be closed in this case, for example because the
...@@ -555,12 +573,14 @@ For those cases, the automatic closing of the database can be disabled in the da ...@@ -555,12 +573,14 @@ For those cases, the automatic closing of the database can be disabled in the da
The first connection (the one that is opening the database) needs to The first connection (the one that is opening the database) needs to
set the option in the database URL (it is not possible to change the setting afterwards). set the option in the database URL (it is not possible to change the setting afterwards).
The database URL to disable database closing on exit is: The database URL to disable database closing on exit is:
</p>
<pre> <pre>
String url = "jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE"; String url = "jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE";
</pre> </pre>
<br /><a name="log_index_changes"></a> <br /><a name="log_index_changes"></a>
<h2>Log Index Changes</h2> <h2>Log Index Changes</h2>
<p>
Usually, changes to the index file are not logged for performance. Usually, changes to the index file are not logged for performance.
If the index file is corrupt or missing when opening a database, it is re-created from the data. If the index file is corrupt or missing when opening a database, it is re-created from the data.
The index file can get corrupt when the database is not shut down correctly, The index file can get corrupt when the database is not shut down correctly,
...@@ -572,8 +592,10 @@ so that recovery from a corrupted index file is fast. ...@@ -572,8 +592,10 @@ so that recovery from a corrupted index file is fast.
To enable log index changes, add LOG=2 to the URL, as in jdbc:h2:~/test;LOG=2 To enable log index changes, add LOG=2 to the URL, as in jdbc:h2:~/test;LOG=2
This setting should be specified when connecting. This setting should be specified when connecting.
The update performance of the database will be reduced when using this option. The update performance of the database will be reduced when using this option.
</p>
<h3>Ignore Unknown Settings</h3> <h3>Ignore Unknown Settings</h3>
<p>
Some applications (for example OpenOffice.org Base) pass some additional parameters Some applications (for example OpenOffice.org Base) pass some additional parameters
when connecting to the database. Why those parameters are passed is unknown. when connecting to the database. Why those parameters are passed is unknown.
The parameters PREFERDOSLIKELINEENDS and IGNOREDRIVERPRIVILEGES are such examples, The parameters PREFERDOSLIKELINEENDS and IGNOREDRIVERPRIVILEGES are such examples,
...@@ -581,17 +603,21 @@ they are simply ignored to improve the compatibility with OpenOffice.org. If an ...@@ -581,17 +603,21 @@ they are simply ignored to improve the compatibility with OpenOffice.org. If an
passes other parameters when connecting to the database, usually the database throws an exception passes other parameters when connecting to the database, usually the database throws an exception
saying the parameter is not supported. It is possible to ignored such parameters by adding saying the parameter is not supported. It is possible to ignored such parameters by adding
;IGNORE_UNKNOWN_SETTINGS=TRUE to the database URL. ;IGNORE_UNKNOWN_SETTINGS=TRUE to the database URL.
</p>
<h3>Changing Other Settings when Opening a Connection</h3> <h3>Changing Other Settings when Opening a Connection</h3>
<p>
In addition to the settings already described (cipher, file_lock, ifexists, user, password), In addition to the settings already described (cipher, file_lock, ifexists, user, password),
other database settings can be passed in the database URL. other database settings can be passed in the database URL.
Adding <code>setting=value</code> at the end of an URL is the Adding <code>setting=value</code> at the end of an URL is the
same as executing the statement <code>SET setting value</code> just after same as executing the statement <code>SET setting value</code> just after
connecting. For a list of settings supported by this database please see the connecting. For a list of settings supported by this database please see the
SQL grammar documentation. SQL grammar documentation.
</p>
<br /><a name="custom_access_mode"></a> <br /><a name="custom_access_mode"></a>
<h2>Custom File Access Mode</h2> <h2>Custom File Access Mode</h2>
<p>
Usually, the database opens log, data and index files with the access mode 'rw', meaning Usually, the database opens log, data and index files with the access mode 'rw', meaning
read-write (except for read only databases, where the mode 'r' is used). read-write (except for read only databases, where the mode 'r' is used).
Also supported are 'rws' and 'rwd'. Also supported are 'rws' and 'rwd'.
...@@ -603,26 +629,33 @@ String url = "jdbc:h2:~/test;ACCESS_MODE_LOG=rws;ACCESS_MODE_DATA=rws"; ...@@ -603,26 +629,33 @@ String url = "jdbc:h2:~/test;ACCESS_MODE_LOG=rws;ACCESS_MODE_DATA=rws";
</pre> </pre>
For more information see <a href="advanced.html#durability_problems">Durability Problems</a>. For more information see <a href="advanced.html#durability_problems">Durability Problems</a>.
On many operating systems the access mode 'rws' does not guarantee that the data is written to the disk. On many operating systems the access mode 'rws' does not guarantee that the data is written to the disk.
</p>
<br /><a name="multiple_connections"></a> <br /><a name="multiple_connections"></a>
<h2>Multiple Connections</h2> <h2>Multiple Connections</h2>
<h3>Opening Multiple Databases at the Same Time</h3> <h3>Opening Multiple Databases at the Same Time</h3>
<p>
An application can open multiple databases at the same time, including multiple An application can open multiple databases at the same time, including multiple
connections to the same database. The number of open database is only limited by the memory available. connections to the same database. The number of open database is only limited by the memory available.
</p>
<h3>Multiple Connections to the Same Database: Client/Server</h3> <h3>Multiple Connections to the Same Database: Client/Server</h3>
If you want to access the same database at the same time from different processes or computers, <p>
you need to use the client / server mode. In this case, one process acts as the server, and the If you want to access the same database at the same time from different processes or computers,
other processes (that could reside on other computers as well) connect to the server via TCP/IP you need to use the client / server mode. In this case, one process acts as the server, and the
(or SSL/TLS over TCP/IP for improved security). other processes (that could reside on other computers as well) connect to the server via TCP/IP
(or SSL/TLS over TCP/IP for improved security).
</p>
<h3>Multithreading Support</h3> <h3>Multithreading Support</h3>
This database is multithreading-safe. That means, if an application is multi-threaded, it does not need <p>
to worry about synchronizing the access to the database. Internally, most requests to the same database This database is multithreading-safe. That means, if an application is multi-threaded, it does not need
are synchronized. That means an application can use multiple threads all accessing the same database o worry about synchronizing the access to the database. Internally, most requests to the same database
at the same time, however if one thread executes a long running query, the other threads are synchronized. That means an application can use multiple threads all accessing the same database
need to wait. at the same time, however if one thread executes a long running query, the other threads
need to wait.
</p>
<h3>Locking, Lock-Timeout, Deadlocks</h3> <h3>Locking, Lock-Timeout, Deadlocks</h3>
<p> <p>
...@@ -860,8 +893,10 @@ Here is the list of currently supported modes and the difference to the regular ...@@ -860,8 +893,10 @@ Here is the list of currently supported modes and the difference to the regular
<br /><a name="trace_options"></a> <br /><a name="trace_options"></a>
<h2>Using the Trace Options</h2> <h2>Using the Trace Options</h2>
<p>
To find problems in an application, it is sometimes good to see what database operations To find problems in an application, it is sometimes good to see what database operations
where executed. This database offers the following trace features: where executed. This database offers the following trace features:
</p>
<ul> <ul>
<li>Trace to System.out and/or a file <li>Trace to System.out and/or a file
</li><li>Support for trace levels OFF, ERROR, INFO, and DEBUG </li><li>Support for trace levels OFF, ERROR, INFO, and DEBUG
...@@ -871,6 +906,7 @@ where executed. This database offers the following trace features: ...@@ -871,6 +906,7 @@ where executed. This database offers the following trace features:
</li></ul> </li></ul>
<h3>Trace Options</h3> <h3>Trace Options</h3>
<p>
The simplest way to enable the trace option is setting it in the database URL. The simplest way to enable the trace option is setting it in the database URL.
There are two settings, one for System.out (TRACE_LEVEL_SYSTEM_OUT) tracing, There are two settings, one for System.out (TRACE_LEVEL_SYSTEM_OUT) tracing,
and one for file tracing (TRACE_LEVEL_FILE). and one for file tracing (TRACE_LEVEL_FILE).
...@@ -886,22 +922,25 @@ Example: ...@@ -886,22 +922,25 @@ Example:
<pre> <pre>
SET TRACE_LEVEL_SYSTEM_OUT 3 SET TRACE_LEVEL_SYSTEM_OUT 3
</pre> </pre>
</p>
<h3>Setting the Maximum Size of the Trace File</h3> <h3>Setting the Maximum Size of the Trace File</h3>
<p>
When using a high trace level, the trace file can get very big quickly. When using a high trace level, the trace file can get very big quickly.
The size of the file can be limited by executing the SQL statement The size of the file can be limited by executing the SQL statement
<code>SET TRACE_MAX_FILE_SIZE maximumFileSizeInMB</code>. <code>SET TRACE_MAX_FILE_SIZE maximumFileSizeInMB</code>.
If the log file exceeds the limit, the file is renamed to .old and a new file is created. If the log file exceeds the limit, the file is renamed to .old and a new file is created.
If another .old file exists, it is deleted. If another .old file exists, it is deleted.
The default setting is 16 MB. Example: The default setting is 16 MB. Example:
</p>
<pre> <pre>
SET TRACE_MAX_FILE_SIZE 1 SET TRACE_MAX_FILE_SIZE 1
</pre> </pre>
<h3>Java Code Generation</h3> <h3>Java Code Generation</h3>
<p>
When setting the trace level to INFO or DEBUG, Java source code is generated as well, so that When setting the trace level to INFO or DEBUG, Java source code is generated as well, so that
problem can be reproduced more easily. The trace file looks like this: problem can be reproduced more easily. The trace file looks like this:
<pre> <pre>
... ...
12-20 20:58:09 jdbc[0]: 12-20 20:58:09 jdbc[0]:
...@@ -910,7 +949,6 @@ problem can be reproduced more easily. The trace file looks like this: ...@@ -910,7 +949,6 @@ problem can be reproduced more easily. The trace file looks like this:
/**/dbMeta3.getTables(null, "", null, new String[]{"TABLE", "VIEW"}); /**/dbMeta3.getTables(null, "", null, new String[]{"TABLE", "VIEW"});
... ...
</pre> </pre>
You need to filter out the lines without /**/ to get the Java source code. You need to filter out the lines without /**/ to get the Java source code.
In Windows, a simple way to do that is: In Windows, a simple way to do that is:
<pre> <pre>
...@@ -925,6 +963,7 @@ Class.forName("org.h2.Driver"); ...@@ -925,6 +963,7 @@ Class.forName("org.h2.Driver");
}} }}
</pre> </pre>
Also, the user name and password needs to be set, because they are not listed in the trace file. Also, the user name and password needs to be set, because they are not listed in the trace file.
</p>
<h3>Enabling the Trace Option at Runtime by Manually Creating a File</h3> <h3>Enabling the Trace Option at Runtime by Manually Creating a File</h3>
<p> <p>
...@@ -946,6 +985,7 @@ will always enable the trace mode when connecting. ...@@ -946,6 +985,7 @@ will always enable the trace mode when connecting.
<br /><a name="read_only"></a> <br /><a name="read_only"></a>
<h2>Read Only Databases</h2> <h2>Read Only Databases</h2>
<p>
If the database files are read-only, then the database is read-only as well. If the database files are read-only, then the database is read-only as well.
It is not possible to create new tables, add or modify data in this database. It is not possible to create new tables, add or modify data in this database.
Only SELECT statements are allowed. Only SELECT statements are allowed.
...@@ -954,9 +994,11 @@ Then, make the database files read-only using the operating system. ...@@ -954,9 +994,11 @@ Then, make the database files read-only using the operating system.
When you open the database now, it is read-only. When you open the database now, it is read-only.
There are two ways an application can find out a database is read-only: There are two ways an application can find out a database is read-only:
By calling Connection.isReadOnly() or by executing the SQL statement CALL READONLY(). By calling Connection.isReadOnly() or by executing the SQL statement CALL READONLY().
</p>
<br /><a name="storage_formats"></a> <br /><a name="storage_formats"></a>
<h2>Binary and Text Storage Formats</h2> <h2>Binary and Text Storage Formats</h2>
<p>
This database engine supports both binary and text storage formats. This database engine supports both binary and text storage formats.
The binary format is faster, but the text storage format can be useful as well, The binary format is faster, but the text storage format can be useful as well,
for example to debug the database engine. for example to debug the database engine.
...@@ -964,6 +1006,7 @@ If a database already exists, the storage format is recognized automatically. ...@@ -964,6 +1006,7 @@ If a database already exists, the storage format is recognized automatically.
New databases are created in the binary storage format by default. New databases are created in the binary storage format by default.
To create a new database in the text storage format, the database URL must contain To create a new database in the text storage format, the database URL must contain
the parameter STORAGE=TEXT. Example URL: jdbc:h2:~/test;STORAGE=TEXT the parameter STORAGE=TEXT. Example URL: jdbc:h2:~/test;STORAGE=TEXT
</p>
<br /><a name="low_disk_space"></a> <br /><a name="low_disk_space"></a>
<h2>Graceful Handling of Low Disk Space Situations</h2> <h2>Graceful Handling of Low Disk Space Situations</h2>
...@@ -987,12 +1030,15 @@ See also the DatabaseEventListener API. ...@@ -987,12 +1030,15 @@ See also the DatabaseEventListener API.
</p> </p>
<h3>Opening a Corrupted Database</h3> <h3>Opening a Corrupted Database</h3>
<p>
If a database can not be opened because the boot info (the SQL script that is run at startup) If a database can not be opened because the boot info (the SQL script that is run at startup)
is corrupted, then the database can be opened by specifying a database event listener. is corrupted, then the database can be opened by specifying a database event listener.
The exceptions are logged, but opening the database will continue. The exceptions are logged, but opening the database will continue.
</p>
<br /><a name="computed_columns"></a> <br /><a name="computed_columns"></a>
<h2>Computed Columns / Function Based Index</h2> <h2>Computed Columns / Function Based Index</h2>
<p>
Function indexes are not directly supported by this database, but they can be easily emulated Function indexes are not directly supported by this database, but they can be easily emulated
by using computed columns. For example, if an index on the upper-case version of by using computed columns. For example, if an index on the upper-case version of
a column is required, just create a computed column with the upper-case version of the original column, a column is required, just create a computed column with the upper-case version of the original column,
...@@ -1012,6 +1058,7 @@ column when querying the table: ...@@ -1012,6 +1058,7 @@ column when querying the table:
INSERT INTO ADDRESS(ID, NAME) VALUES(1, 'Miller'); INSERT INTO ADDRESS(ID, NAME) VALUES(1, 'Miller');
SELECT * FROM ADDRESS WHERE UPPER_NAME='MILLER'; SELECT * FROM ADDRESS WHERE UPPER_NAME='MILLER';
</pre> </pre>
</p>
<br /><a name="multi_dimensional"></a> <br /><a name="multi_dimensional"></a>
<h2>Multi-Dimensional Indexes</h2> <h2>Multi-Dimensional Indexes</h2>
...@@ -1066,7 +1113,6 @@ password will not be stored in the swap file. ...@@ -1066,7 +1113,6 @@ password will not be stored in the swap file.
</p><p> </p><p>
This database supports using char arrays instead of String to pass user and file passwords. This database supports using char arrays instead of String to pass user and file passwords.
The following code can be used to do that: The following code can be used to do that:
</p>
<pre> <pre>
Class.forName("org.h2.Driver"); Class.forName("org.h2.Driver");
String url = "jdbc:h2:simple"; String url = "jdbc:h2:simple";
...@@ -1086,8 +1132,10 @@ try { ...@@ -1086,8 +1132,10 @@ try {
</pre> </pre>
In this example, the password is hard code in the application, which is not secure of course. In this example, the password is hard code in the application, which is not secure of course.
However, Java Swing supports a way to get passwords using a char array (JPasswordField). However, Java Swing supports a way to get passwords using a char array (JPasswordField).
</p>
<h3>Passing the User Name and/or Password in the URL</h3> <h3>Passing the User Name and/or Password in the URL</h3>
<p>
Instead of passing the user name as a separate parameter as in Instead of passing the user name as a separate parameter as in
<code> <code>
Connection conn = DriverManager. Connection conn = DriverManager.
...@@ -1099,10 +1147,11 @@ Connection conn = DriverManager. ...@@ -1099,10 +1147,11 @@ Connection conn = DriverManager.
getConnection("jdbc:h2:~/test;USER=sa;PASSWORD=123"); getConnection("jdbc:h2:~/test;USER=sa;PASSWORD=123");
</code> </code>
The settings in the URL override the settings passed as a separate parameter. The settings in the URL override the settings passed as a separate parameter.
</p>
<br /><a name="user_defined_functions"></a> <br /><a name="user_defined_functions"></a>
<h2>User Defined Functions and Stored Procedures</h2> <h2>User Defined Functions and Stored Procedures</h2>
<p>
In addition to the built-in functions, this database supports user defined Java functions. In addition to the built-in functions, this database supports user defined Java functions.
In this database, Java functions can be used as stored procedures as well. In this database, Java functions can be used as stored procedures as well.
A function must be declared (registered) before it can be used. A function must be declared (registered) before it can be used.
...@@ -1122,21 +1171,29 @@ The Java function must be registered in the database by calling CREATE ALIAS: ...@@ -1122,21 +1171,29 @@ The Java function must be registered in the database by calling CREATE ALIAS:
CREATE ALIAS IS_PRIME FOR "org.h2.samples.Function.isPrime" CREATE ALIAS IS_PRIME FOR "org.h2.samples.Function.isPrime"
</pre> </pre>
For a complete sample application, see src/test/org/h2/samples/Function.java. For a complete sample application, see src/test/org/h2/samples/Function.java.
</p>
<h3>Function Data Type Mapping</h3> <h3>Function Data Type Mapping</h3>
<p>
Functions that accept non-nullable parameters such as 'int' will not be called if one of those parameters is NULL. Functions that accept non-nullable parameters such as 'int' will not be called if one of those parameters is NULL.
In this case, the value NULL is used as the result. If the function should be called in this case, you need In this case, the value NULL is used as the result. If the function should be called in this case, you need
to use 'java.lang.Integer' instead of 'int'. to use 'java.lang.Integer' instead of 'int'.
</p>
<h3>Functions that require a Connection</h3> <h3>Functions that require a Connection</h3>
<p>
If the first parameter in a Java function is a java.sql.Connection, then the connection If the first parameter in a Java function is a java.sql.Connection, then the connection
to database is provided. This connection does not need to be closed before returning. to database is provided. This connection does not need to be closed before returning.
</p>
<h3>Functions throwing an Exception</h3> <h3>Functions throwing an Exception</h3>
<p>
If a function throws an Exception, then the current statement is rolled back If a function throws an Exception, then the current statement is rolled back
and the exception is thrown to the application. and the exception is thrown to the application.
</p>
<h3>Functions returning a Result Set</h3> <h3>Functions returning a Result Set</h3>
<p>
Functions may returns a result set. Such a function can be called with the CALL statement: Functions may returns a result set. Such a function can be called with the CALL statement:
<pre> <pre>
public static ResultSet query(Connection conn, String sql) throws SQLException { public static ResultSet query(Connection conn, String sql) throws SQLException {
...@@ -1146,8 +1203,10 @@ public static ResultSet query(Connection conn, String sql) throws SQLException { ...@@ -1146,8 +1203,10 @@ public static ResultSet query(Connection conn, String sql) throws SQLException {
CREATE ALIAS QUERY FOR "org.h2.samples.Function.query"; CREATE ALIAS QUERY FOR "org.h2.samples.Function.query";
CALL QUERY('SELECT * FROM TEST'); CALL QUERY('SELECT * FROM TEST');
</pre> </pre>
</p>
<h3>Using SimpleResultSet</h3> <h3>Using SimpleResultSet</h3>
<p>
A function that returns a result set can create this result set from scratch using the SimpleResultSet tool: A function that returns a result set can create this result set from scratch using the SimpleResultSet tool:
<pre> <pre>
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
...@@ -1164,8 +1223,10 @@ public static ResultSet simpleResultSet() throws SQLException { ...@@ -1164,8 +1223,10 @@ public static ResultSet simpleResultSet() throws SQLException {
CREATE ALIAS SIMPLE FOR "org.h2.samples.Function.simpleResultSet"; CREATE ALIAS SIMPLE FOR "org.h2.samples.Function.simpleResultSet";
CALL SIMPLE(); CALL SIMPLE();
</pre> </pre>
</p>
<h3>Using a Function as a Table</h3> <h3>Using a Function as a Table</h3>
<p>
A function returning a result set can be like a table. A function returning a result set can be like a table.
However, in this case the function is called at least twice: However, in this case the function is called at least twice:
First while parsing the statement to collect the column names First while parsing the statement to collect the column names
...@@ -1192,9 +1253,11 @@ public static ResultSet getMatrix(Integer id) throws SQLException { ...@@ -1192,9 +1253,11 @@ public static ResultSet getMatrix(Integer id) throws SQLException {
CREATE ALIAS MATRIX FOR "org.h2.samples.Function.getMatrix"; CREATE ALIAS MATRIX FOR "org.h2.samples.Function.getMatrix";
SELECT * FROM MATRIX(3) WHERE X>0; SELECT * FROM MATRIX(3) WHERE X>0;
</pre> </pre>
</p>
<br /><a name="triggers"></a> <br /><a name="triggers"></a>
<h2>Triggers</h2> <h2>Triggers</h2>
<p>
This database supports Java triggers that are called before or after a row is updated, inserted or deleted. This database supports Java triggers that are called before or after a row is updated, inserted or deleted.
Triggers can be used for complex consistency checks, or to update related data in the database. Triggers can be used for complex consistency checks, or to update related data in the database.
It is also possible to use triggers to simulate materialized views. It is also possible to use triggers to simulate materialized views.
...@@ -1219,9 +1282,11 @@ CREATE TRIGGER INV_INS AFTER INSERT ON INVOICE ...@@ -1219,9 +1282,11 @@ CREATE TRIGGER INV_INS AFTER INSERT ON INVOICE
FOR EACH ROW CALL "org.h2.samples.TriggerSample" FOR EACH ROW CALL "org.h2.samples.TriggerSample"
</pre> </pre>
The trigger can be used to veto a change, by throwing a SQL Exception. The trigger can be used to veto a change, by throwing a SQL Exception.
</p>
<br /><a name="compacting"></a> <br /><a name="compacting"></a>
<h2>Compacting a Database</h2> <h2>Compacting a Database</h2>
<p>
Empty space in the database file is re-used automatically. Empty space in the database file is re-used automatically.
To re-build the indexes, the most simple way is to delete the .index.db file To re-build the indexes, the most simple way is to delete the .index.db file
while the database is closed. However in some situations (for example after deleting while the database is closed. However in some situations (for example after deleting
...@@ -1240,6 +1305,7 @@ public static void compact(String dir, String dbName, ...@@ -1240,6 +1305,7 @@ public static void compact(String dir, String dbName,
See also the sample application org.h2.samples.Compact. See also the sample application org.h2.samples.Compact.
The commands SCRIPT / RUNSCRIPT can be used as well to create the a backup The commands SCRIPT / RUNSCRIPT can be used as well to create the a backup
of a database and re-build the database from the script. of a database and re-build the database from the script.
</p>
<br /><a name="cache_settings"></a> <br /><a name="cache_settings"></a>
<h2>Cache Settings</h2> <h2>Cache Settings</h2>
...@@ -1265,7 +1331,9 @@ is listed for the data and index file. ...@@ -1265,7 +1331,9 @@ is listed for the data and index file.
<br /><a name="why_java"></a> <br /><a name="why_java"></a>
<h2>Why Java</h2> <h2>Why Java</h2>
<p>
A few reasons using a Java database are: A few reasons using a Java database are:
</p>
<ul> <ul>
<li>Very simple to integrate in Java applications <li>Very simple to integrate in Java applications
</li><li>Support for many different platforms </li><li>Support for many different platforms
......
...@@ -18,12 +18,14 @@ Initial Developer: H2 Group ...@@ -18,12 +18,14 @@ Initial Developer: H2 Group
</frameset> </frameset>
<noframes> <noframes>
<body> <body>
<p>
H2 (for 'Hypersonic 2') is free a Java SQL DBMS. H2 (for 'Hypersonic 2') is free a Java SQL DBMS.
Clustering, embedded and server mode, transactions, referential integrity, Clustering, embedded and server mode, transactions, referential integrity,
views, subqueries, triggers, encryption, and disk based or in-memory operation views, subqueries, triggers, encryption, and disk based or in-memory operation
are supported. A browser based console application is included. are supported. A browser based console application is included.
If you see this page your browser does not support frames. If you see this page your browser does not support frames.
Please click here to view the <a href="search.html">index</a>. Please click here to view the <a href="search.html">index</a>.
</p>
</body> </body>
</noframes> </noframes>
</html> </html>
...@@ -18,12 +18,14 @@ Initial Developer: H2 Group ...@@ -18,12 +18,14 @@ Initial Developer: H2 Group
</frameset> </frameset>
<noframes> <noframes>
<body> <body>
<p>
H2 (for 'Hypersonic 2') is free a Java SQL DBMS. H2 (for 'Hypersonic 2') is free a Java SQL DBMS.
Clustering, embedded and server mode, transactions, referential integrity, Clustering, embedded and server mode, transactions, referential integrity,
views, subqueries, triggers, encryption, and disk based or in-memory operation views, subqueries, triggers, encryption, and disk based or in-memory operation
are supported. A browser based console application is included. are supported. A browser based console application is included.
If you see this page your browser does not support frames. If you see this page your browser does not support frames.
Please click here to view the <a href="search_ja.html">index</a>. Please click here to view the <a href="search_ja.html">index</a>.
</p>
</body> </body>
</noframes> </noframes>
</html> </html>
...@@ -1092,6 +1092,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch. ...@@ -1092,6 +1092,7 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
</li><li>Automatic mode: jdbc:h2:auto: (embedded mode if possible, if not use server mode). </li><li>Automatic mode: jdbc:h2:auto: (embedded mode if possible, if not use server mode).
Problem: what to do when server stops while others are connected to it. Problem: what to do when server stops while others are connected to it.
</li><li>Access rights: remember the owner of an object. COMMENT: allow owner of object to change it. </li><li>Access rights: remember the owner of an object. COMMENT: allow owner of object to change it.
</li><li>Implement INSTEAD OF trigger.
</li></ul> </li></ul>
<h3>Not Planned</h3> <h3>Not Planned</h3>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html). Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group Initial Developer: H2 Group
--> -->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title> <head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
H2 Database Engine H2 Database Engine
</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /> </title><link rel="stylesheet" type="text/css" href="stylesheet.css" />
......
...@@ -22,10 +22,11 @@ Performance ...@@ -22,10 +22,11 @@ Performance
<br /><a name="performance_comparison"></a> <br /><a name="performance_comparison"></a>
<h2>Performance Comparison</h2> <h2>Performance Comparison</h2>
<p>
In most cases H2 is a lot faster than all other In most cases H2 is a lot faster than all other
(open source and not open source) database engines. (open source and not open source) database engines.
Please note this is mostly a single connection benchmark run on one computer. Please note this is mostly a single connection benchmark run on one computer.
</p>
<h3>Embedded</h3> <h3>Embedded</h3>
<table border="1" class="bar"> <table border="1" class="bar">
...@@ -76,6 +77,7 @@ Please note this is mostly a single connection benchmark run on one computer. ...@@ -76,6 +77,7 @@ Please note this is mostly a single connection benchmark run on one computer.
<h3>Benchmark Results and Comments</h3> <h3>Benchmark Results and Comments</h3>
<h4>H2</h4> <h4>H2</h4>
<p>
Version 1.0 (2007-06-17) was used for the test. Version 1.0 (2007-06-17) was used for the test.
For simpler operations, the performance of H2 is about the same as for HSQLDB. For simpler operations, the performance of H2 is about the same as for HSQLDB.
For more complex queries, the query optimizer is very important. For more complex queries, the query optimizer is very important.
...@@ -85,8 +87,10 @@ disk if more than a certain number of records are returned. ...@@ -85,8 +87,10 @@ disk if more than a certain number of records are returned.
The advantage of buffering is, there is no limit on the result set size. The advantage of buffering is, there is no limit on the result set size.
The open/close time is almost fixed, because of the file locking protocol: The engine waits The open/close time is almost fixed, because of the file locking protocol: The engine waits
20 ms after opening a database to ensure the database files are not opened by another process. 20 ms after opening a database to ensure the database files are not opened by another process.
</p>
<h4>HSQLDB</h4> <h4>HSQLDB</h4>
<p>
Version 1.8.0.5 was used for the test. Version 1.8.0.5 was used for the test.
Cached tables are used in this test (hsqldb.default_table_type=cached), Cached tables are used in this test (hsqldb.default_table_type=cached),
and the write delay is 1 second (SET WRITE_DELAY 1). and the write delay is 1 second (SET WRITE_DELAY 1).
...@@ -101,21 +105,27 @@ AND S_W_ID=? AND S_I_ID=OL_I_ID AND S_QUANTITY&lt;? ...@@ -101,21 +105,27 @@ AND S_W_ID=? AND S_I_ID=OL_I_ID AND S_QUANTITY&lt;?
The PolePosition benchmark also shows that the query optimizer does not do a very good job for some queries. The PolePosition benchmark also shows that the query optimizer does not do a very good job for some queries.
A disadvantage in HSQLDB is the slow startup / shutdown time (currently not listed) when using bigger databases. A disadvantage in HSQLDB is the slow startup / shutdown time (currently not listed) when using bigger databases.
The reason is, a backup of the database is created whenever the database is opened or closed. The reason is, a backup of the database is created whenever the database is opened or closed.
</p>
<h4>Derby</h4> <h4>Derby</h4>
<p>
Version 10.2.1.6 was used for the test. Derby is clearly the slowest embedded database in this test. Version 10.2.1.6 was used for the test. Derby is clearly the slowest embedded database in this test.
This seems to be a structural problem, because all operations are really slow. This seems to be a structural problem, because all operations are really slow.
It will not be easy for the developers of Derby to improve the performance to a reasonable level. It will not be easy for the developers of Derby to improve the performance to a reasonable level.
</p>
<h4>PostgreSQL</h4> <h4>PostgreSQL</h4>
<p>
Version 8.1.4 was used for the test. Version 8.1.4 was used for the test.
The following options where changed in postgresql.conf: The following options where changed in postgresql.conf:
fsync = off, commit_delay = 1000. fsync = off, commit_delay = 1000.
PostgreSQL is run in server mode. It looks like the base performance is slower than PostgreSQL is run in server mode. It looks like the base performance is slower than
MySQL, the reason could be the network layer. MySQL, the reason could be the network layer.
The memory usage number is incorrect, because only the memory usage of the JDBC driver is measured. The memory usage number is incorrect, because only the memory usage of the JDBC driver is measured.
</p>
<h4>MySQL</h4> <h4>MySQL</h4>
<p>
Version 5.0.22 was used for the test. Version 5.0.22 was used for the test.
MySQL was run with the InnoDB backend. MySQL was run with the InnoDB backend.
The setting innodb_flush_log_at_trx_commit The setting innodb_flush_log_at_trx_commit
...@@ -127,48 +137,64 @@ Too bad this setting is not listed in the configuration wizard, ...@@ -127,48 +137,64 @@ Too bad this setting is not listed in the configuration wizard,
and it always overwritten when using the wizard. and it always overwritten when using the wizard.
You need to change this setting manually in the file my.ini, and then restart the service. You need to change this setting manually in the file my.ini, and then restart the service.
The memory usage number is incorrect, because only the memory usage of the JDBC driver is measured. The memory usage number is incorrect, because only the memory usage of the JDBC driver is measured.
</p>
<h4>Firebird</h4> <h4>Firebird</h4>
<p>
Firebird 1.5 (default installation) was tested, but the results are not published currently. Firebird 1.5 (default installation) was tested, but the results are not published currently.
It is possible to run the performance test with the Firebird database, It is possible to run the performance test with the Firebird database,
and any information on how to configure Firebird for higher performance are welcome. and any information on how to configure Firebird for higher performance are welcome.
</p>
<h4>Why Oracle / MS SQL Server / DB2 are Not Listed</h4> <h4>Why Oracle / MS SQL Server / DB2 are Not Listed</h4>
<p>
The license of these databases does not allow to publish benchmark results. The license of these databases does not allow to publish benchmark results.
This doesn't mean that they are fast. They are in fact quite slow, This doesn't mean that they are fast. They are in fact quite slow,
and need a lot of memory. But you will need to test this yourself. and need a lot of memory. But you will need to test this yourself.
SQLite was not tested because the JDBC driver doesn't support transactions. SQLite was not tested because the JDBC driver doesn't support transactions.
</p>
<h3>About this Benchmark</h3> <h3>About this Benchmark</h3>
<h4>Number of Connections</h4> <h4>Number of Connections</h4>
<p>
This is mostly a single-connection benchmark. This is mostly a single-connection benchmark.
BenchB uses multiple connections, the other tests one connection. BenchB uses multiple connections, the other tests one connection.
</p>
<h4>Real-World Tests</h4> <h4>Real-World Tests</h4>
<p>
Good benchmarks emulate real-world use cases. This benchmark includes 3 test cases: Good benchmarks emulate real-world use cases. This benchmark includes 3 test cases:
A simple test case with one table and many small updates / deletes. A simple test case with one table and many small updates / deletes.
BenchA is similar to the TPC-A test, but single connection / single threaded (see also: www.tpc.org). BenchA is similar to the TPC-A test, but single connection / single threaded (see also: www.tpc.org).
BenchB is similar to the TPC-B test, using multiple connections (one thread per connection). BenchB is similar to the TPC-B test, using multiple connections (one thread per connection).
BenchC is similar to the TPC-C test, but single connection / single threaded. BenchC is similar to the TPC-C test, but single connection / single threaded.
</p>
<h4>Comparing Embedded with Server Databases</h4> <h4>Comparing Embedded with Server Databases</h4>
<p>
This is mainly a benchmark for embedded databases (where the application runs in the same This is mainly a benchmark for embedded databases (where the application runs in the same
virtual machine than the database engine). However MySQL and PostgreSQL are not Java virtual machine than the database engine). However MySQL and PostgreSQL are not Java
databases and cannot be embedded into a Java application. databases and cannot be embedded into a Java application.
For the Java databases, both embedded and server modes are tested. For the Java databases, both embedded and server modes are tested.
</p>
<h4>Test Platform</h4> <h4>Test Platform</h4>
<p>
This test is run on Windows XP with the virus scanner switched off. This test is run on Windows XP with the virus scanner switched off.
The VM used is Sun JDK 1.5. The VM used is Sun JDK 1.5.
</p>
<h4>Multiple Runs</h4> <h4>Multiple Runs</h4>
<p>
When a Java benchmark is run first, the code is not fully compiled and When a Java benchmark is run first, the code is not fully compiled and
therefore runs slower than when running multiple times. A benchmark therefore runs slower than when running multiple times. A benchmark
should always run the same test multiple times and ignore the first run(s). should always run the same test multiple times and ignore the first run(s).
This benchmark runs three times, the last run counts. This benchmark runs three times, the last run counts.
</p>
<h4>Memory Usage</h4> <h4>Memory Usage</h4>
<p>
It is not enough to measure the time taken, the memory usage is important as well. It is not enough to measure the time taken, the memory usage is important as well.
Performance can be improved in databases by using a bigger in-memory cache, Performance can be improved in databases by using a bigger in-memory cache,
but there is only a limited amount of memory available on the system. but there is only a limited amount of memory available on the system.
...@@ -177,13 +203,17 @@ uses 'disk based' tables for all databases. ...@@ -177,13 +203,17 @@ uses 'disk based' tables for all databases.
Unfortunately, it is not so easy to calculate the memory usage of PostgreSQL Unfortunately, it is not so easy to calculate the memory usage of PostgreSQL
and MySQL, because they run in a different process than the test. This benchmark currently and MySQL, because they run in a different process than the test. This benchmark currently
does not print memory usage of those databases. does not print memory usage of those databases.
</p>
<h4>Delayed Operations</h4> <h4>Delayed Operations</h4>
<p>
Some databases delay some operations (for example flushing the buffers) Some databases delay some operations (for example flushing the buffers)
until after the benchmark is run. This benchmark waits between until after the benchmark is run. This benchmark waits between
each database tested, and each database runs in a different process (sequentially). each database tested, and each database runs in a different process (sequentially).
</p>
<h4>Transaction Commit / Durability</h4> <h4>Transaction Commit / Durability</h4>
<p>
Durability means transaction committed to the database will not be lost. Durability means transaction committed to the database will not be lost.
Some databases (for example MySQL) try to enforce this by default by calling fsync() to flush the buffers, but Some databases (for example MySQL) try to enforce this by default by calling fsync() to flush the buffers, but
most hard drives don't actually flush all data. Calling fsync() slows down transaction commit a lot, most hard drives don't actually flush all data. Calling fsync() slows down transaction commit a lot,
...@@ -194,11 +224,15 @@ inserts. However many applications need 'short' transactions at runtime (a commi ...@@ -194,11 +224,15 @@ inserts. However many applications need 'short' transactions at runtime (a commi
This benchmark commits after each update / delete in the simple benchmark, and after each This benchmark commits after each update / delete in the simple benchmark, and after each
business transaction in the other benchmarks. For databases that support delayed commits, business transaction in the other benchmarks. For databases that support delayed commits,
a delay of one second is used. a delay of one second is used.
</p>
<h4>Using Prepared Statements</h4> <h4>Using Prepared Statements</h4>
<p>
Wherever possible, the test cases use prepared statements. Wherever possible, the test cases use prepared statements.
</p>
<h4>Currently Not Tested: Startup Time</h4> <h4>Currently Not Tested: Startup Time</h4>
<p>
The startup time of a database engine is important as well for embedded use. The startup time of a database engine is important as well for embedded use.
This time is not measured currently. This time is not measured currently.
Also, not tested is the time used to create a database and open an existing database. Also, not tested is the time used to create a database and open an existing database.
...@@ -206,6 +240,7 @@ Here, one (wrapper) connection is opened at the start, ...@@ -206,6 +240,7 @@ Here, one (wrapper) connection is opened at the start,
and for each step a new connection is opened and then closed. and for each step a new connection is opened and then closed.
That means the Open/Close time listed is for opening a connection That means the Open/Close time listed is for opening a connection
if the database is already in use. if the database is already in use.
</p>
<h3>PolePosition Benchmark</h3> <h3>PolePosition Benchmark</h3>
<p> <p>
...@@ -240,6 +275,7 @@ It was developed / sponsored by db4o. ...@@ -240,6 +275,7 @@ It was developed / sponsored by db4o.
<h2>Application Profiling</h2> <h2>Application Profiling</h2>
<h3>Analyze First</h3> <h3>Analyze First</h3>
<p>
Before trying to optimize the performance, it is important to know where the time is actually spent. Before trying to optimize the performance, it is important to know where the time is actually spent.
The same is true for memory problems. The same is true for memory problems.
Premature or 'blind' optimization should be avoided, as it is not an efficient way to solve the problem. Premature or 'blind' optimization should be avoided, as it is not an efficient way to solve the problem.
...@@ -249,26 +285,32 @@ But this does not work for complex applications with many modules, and for memor ...@@ -249,26 +285,32 @@ But this does not work for complex applications with many modules, and for memor
A very good tool to measure both the memory and the CPU is the A very good tool to measure both the memory and the CPU is the
<a href="http://www.yourkit.com">YourKit Java Profiler</a>. This tool is also used <a href="http://www.yourkit.com">YourKit Java Profiler</a>. This tool is also used
to optimize the performance and memory footprint of this database engine. to optimize the performance and memory footprint of this database engine.
</p>
<br /><a name="database_performance_tuning"></a> <br /><a name="database_performance_tuning"></a>
<h2>Database Performance Tuning</h2> <h2>Database Performance Tuning</h2>
<h3>Virus Scanners</h3> <h3>Virus Scanners</h3>
<p>
Some virus scanners scan files every time they are accessed. Some virus scanners scan files every time they are accessed.
It is very important for performance that database files are not scanned for viruses. It is very important for performance that database files are not scanned for viruses.
The database engine does never interprets the data stored in the files as programs, The database engine does never interprets the data stored in the files as programs,
that means even if somebody would store a virus in a database file, this would that means even if somebody would store a virus in a database file, this would
be harmless (when the virus does not run, it cannot spread). be harmless (when the virus does not run, it cannot spread).
Some virus scanners allow excluding file endings. Make sure files ending with .db are not scanned. Some virus scanners allow excluding file endings. Make sure files ending with .db are not scanned.
</p>
<h3>Using the Trace Options</h3> <h3>Using the Trace Options</h3>
<p>
If the main performance hot spots are in the database engine, in many cases the performance If the main performance hot spots are in the database engine, in many cases the performance
can be optimized by creating additional indexes, or changing the schema. Sometimes the can be optimized by creating additional indexes, or changing the schema. Sometimes the
application does not directly generate the SQL statements, for example if an O/R mapping tool application does not directly generate the SQL statements, for example if an O/R mapping tool
is used. To view the SQL statements and JDBC API calls, you can use the trace options. is used. To view the SQL statements and JDBC API calls, you can use the trace options.
For more information, see <a href="features.html#trace_options">Using the Trace Options</a>. For more information, see <a href="features.html#trace_options">Using the Trace Options</a>.
</p>
<h3>Index Usage</h3> <h3>Index Usage</h3>
<p>
This database uses indexes to improve the performance of SELECT, UPDATE and DELETE statements. This database uses indexes to improve the performance of SELECT, UPDATE and DELETE statements.
If a column is used in the WHERE clause of a query, and if an index exists on this column, If a column is used in the WHERE clause of a query, and if an index exists on this column,
then the index can be used. Multi-column indexes are used if all or the first columns of the index are used. then the index can be used. Multi-column indexes are used if all or the first columns of the index are used.
...@@ -277,25 +319,32 @@ Indexes are not used to order result sets: The results are sorted in memory if r ...@@ -277,25 +319,32 @@ Indexes are not used to order result sets: The results are sorted in memory if r
Indexes are created automatically for primary key and unique constraints. Indexes are created automatically for primary key and unique constraints.
Indexes are also created for foreign key constraints, if required. Indexes are also created for foreign key constraints, if required.
For other columns, indexes need to be created manually using the CREATE INDEX statement. For other columns, indexes need to be created manually using the CREATE INDEX statement.
</p>
<h3>Optimizer</h3> <h3>Optimizer</h3>
<p>
This database uses a cost based optimizer. For simple and queries and queries with medium complexity This database uses a cost based optimizer. For simple and queries and queries with medium complexity
(less than 7 tables in the join), the expected cost (running time) of all possible plans is calculated, (less than 7 tables in the join), the expected cost (running time) of all possible plans is calculated,
and the plan with the lowest cost is used. For more complex queries, the algorithm first tries and the plan with the lowest cost is used. For more complex queries, the algorithm first tries
all possible combinations for the first few tables, and the remaining tables added using a greedy algorithm all possible combinations for the first few tables, and the remaining tables added using a greedy algorithm
(this works well for most joins). Afterwards a genetic algorithm is used to test at most 2000 distinct plans. (this works well for most joins). Afterwards a genetic algorithm is used to test at most 2000 distinct plans.
Only left-deep plans are evaluated. Only left-deep plans are evaluated.
</p>
<h3>Expression Optimization</h3> <h3>Expression Optimization</h3>
<p>
After the statement is parsed, all expressions are simplified automatically if possible. Operations After the statement is parsed, all expressions are simplified automatically if possible. Operations
are evaluated only once if all parameters are constant. Functions are also optimized, but only are evaluated only once if all parameters are constant. Functions are also optimized, but only
if the function is constant (always returns the same result for the same parameter values). if the function is constant (always returns the same result for the same parameter values).
If the WHERE clause is always false, then the table is not accessed at all. If the WHERE clause is always false, then the table is not accessed at all.
</p>
<h3>COUNT(*) Optimization</h3> <h3>COUNT(*) Optimization</h3>
<p>
If the query only counts all rows of a table, then the data is not accessed. If the query only counts all rows of a table, then the data is not accessed.
However, this is only possible if no WHERE clause is used, that means it only works for However, this is only possible if no WHERE clause is used, that means it only works for
queries of the form SELECT COUNT(*) FROM table. queries of the form SELECT COUNT(*) FROM table.
</p>
<h3>Updating Optimizer Statistics / Column Selectivity</h3> <h3>Updating Optimizer Statistics / Column Selectivity</h3>
<p> <p>
......
...@@ -40,6 +40,9 @@ public class JdbcSQLException extends SQLException { ...@@ -40,6 +40,9 @@ public class JdbcSQLException extends SQLException {
} }
private static String buildMessage(String message, String sql, String state) { private static String buildMessage(String message, String sql, String state) {
if(message == null) {
message = "";
}
StringBuffer buff = new StringBuffer(message); StringBuffer buff = new StringBuffer(message);
if(sql != null) { if(sql != null) {
buff.append("; SQL statement: "); buff.append("; SQL statement: ");
......
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
*/ */
package org.h2.test; package org.h2.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties; import java.util.Properties;
import org.h2.server.TcpServer; import org.h2.server.TcpServer;
...@@ -94,6 +97,23 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2 ...@@ -94,6 +97,23 @@ java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2
/* /*
search from a frame (but usually don't use frames)
Class.forName("org.h2.Driver");
DeleteDbFiles.execute("~", null, true);
Connection conn1 = DriverManager.getConnection("jdbc:h2:~/test");
Statement s1 = conn1.createStatement();
s1.execute("create table test(id int)");
conn1.setAutoCommit(false);
s1.execute("delete from test");
s1.execute("PREPARE COMMIT TX_8");
s1.execute("COMMIT TRANSACTION TX_8");
Connection conn2 = DriverManager.getConnection("jdbc:h2:~/test");
conn2.createStatement().execute("select * from test");
call N'@name';
pg_version is in public instead of pg_catalog pg_version is in public instead of pg_catalog
copyright to include 2007 copyright to include 2007
......
...@@ -17,7 +17,7 @@ public class DbStarter implements ServletContextListener { ...@@ -17,7 +17,7 @@ public class DbStarter implements ServletContextListener {
// You can also get the setting from a context-param in web.xml: // You can also get the setting from a context-param in web.xml:
ServletContext servletContext = servletContextEvent.getServletContext(); ServletContext servletContext = servletContextEvent.getServletContext();
// String url = servletContext.getInitParameter("db.url"); // String url = servletContext.getInitParameter("db.url");
conn = DriverManager.getConnection("jdbc:h2:test", "sa", ""); conn = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
servletContext.setAttribute("connection", conn); servletContext.setAttribute("connection", conn);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论