//Wenn Die Transaction erst nach sess2.close() gestartet wird, dann funktioniert es
//Wenn Die Transaction erst nach sess2.close() gestartet wird, dann funktioniert es
...
@@ -144,82 +132,6 @@ t.commit();
...
@@ -144,82 +132,6 @@ t.commit();
sess1.close();
sess1.close();
download/trace*.log
download/trace*.log
DatDb test
Short answer:
This database does not guarantee that all committed transactions survive a power failure.
While other databases (such as Derby) claim they can guarantee it, in reality they can't.
Testing shows that all databases lose transactions on power failure sometimes.
Where this 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,
such as the H2 clustering mode.
Long answer:
Making sure that committed transaction are not lost is more complicated than it seems first.
To guarantee complete durability, a database must ensure that the log record is on the hard drive
before the commit call returns. To do that, different approaches are possible. The first option
is to use the 'synchronous write' option when opening a file. In Java, RandomAccessFile
supports the opening modes "rws" and "rwd":
Around 1000 write operations per second are possible when using one of those modes.
You can get the exact number for your system by running the test org.h2.test.poweroff.TestWrite.
This feature is used by Derby and PostgreSQL.
However, this alone does not force changes to disk, because it does not flush the operating system and hard drive buffers.
Even 7800 RPM hard drives can spin at 130 rounds per second only.
There are other ways force data to disk:
FileDescriptor.sync().
The documentation says that this will force all system buffers to synchronize with the underlying device.
Sync is supposed to return after all in-memory modified copies of buffers associated with this FileDescriptor have been written to the physical medium.
FileChannel.force() (since JDK 1.4).
This method is supposed to force any updates to this channel's file to be written to the storage device that contains it.
The test was made with this database, as well as with PostgreSQL, Derby, and HSQLDB.
None of those databases was able to guarantee complete transaction durability.
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.
One computer acts as the listener, the test application is run on the other computer.
The computer with the listener application opens a TCP/IP port and listens for an incoming connection.
The second computer first connects to the listener, and then created the databases and starts inserting records.
The connection is set to 'autocommit', which means after each inserted record a commit is performed automatically.
Afterwards, the test computer notifies the listener that this record was inserted successfully.
The listener computer displays the last inserted record number every 10 seconds.
Now, the power needs to be switched off manually while the test is still running.
Now you can 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 consult the source code of the listener and test application.
The test was made using two computers, with computer A
writing to disk and then sending the transaction id over the network to computer B. After some time,
the power is switched off on computer A. After switching on computer A again, some committed
transactions where lost.
It is not enough to just send the write request to
the operating system, because the write cache may be enabled (which is the default for Windows XP).
Unfortunetly, it is also not enough to flush the buffers (fsync), because regular hard drives do not obey
this command. The only way to guarantee durability, according to a test, is to wait about one second
before returning from a commit call. This would mean the maximum number of transactions is 1 per second.
All databases tested achive a much higher transaction rate, which means all databases take some shortcuts.
H2 does not guarantee durability, and while other databases (such as Derby) claim they guarantee it,
in reality none of the tested databases achieve complete durability
> SCRIPT PUBLIC TEST_ALL VIEW MEMORY CREATE FORCE VIEW PUBLIC.TEST_ALL(AID, A_NAME, BID, B_NAME) AS SELECT A.ID AID, A.NAME A_NAME, B.ID BID, B.NAME B_NAME FROM TEST_A A, TEST_B B WHERE A.ID = B.ID 513
> TEST_ALL CREATE FORCE VIEW PUBLIC.TEST_ALL(AID, A_NAME, BID, B_NAME) AS SELECT A.ID AID, A.NAME A_NAME, B.ID BID, B.NAME B_NAME FROM TEST_A A, TEST_B B WHERE A.ID = B.ID
> SCRIPT PUBLIC TEST_A_SUB VIEW MEMORY CREATE FORCE VIEW PUBLIC.TEST_A_SUB(ID, NAME) AS SELECT * FROM TEST_A WHERE ID < 2 515
> TEST_A_SUB CREATE FORCE VIEW PUBLIC.TEST_A_SUB(ID, NAME) AS SELECT * FROM TEST_A WHERE ID < 2