Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
4445abd7
提交
4445abd7
authored
6月 13, 2007
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
--no commit message
--no commit message
上级
923f4c87
显示空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
99 行增加
和
62 行删除
+99
-62
advanced.html
h2/src/docsrc/html/advanced.html
+46
-39
features.html
h2/src/docsrc/html/features.html
+22
-0
history.html
h2/src/docsrc/html/history.html
+7
-5
mainWeb_text_.html
h2/src/docsrc/html/mainWeb_text_.html
+12
-10
DatabaseEventListener.java
h2/src/main/org/h2/api/DatabaseEventListener.java
+5
-1
Parser.java
h2/src/main/org/h2/command/Parser.java
+2
-2
BackupCommand.java
h2/src/main/org/h2/command/dml/BackupCommand.java
+1
-1
RunScriptCommand.java
h2/src/main/org/h2/command/dml/RunScriptCommand.java
+1
-1
ScriptBase.java
h2/src/main/org/h2/command/dml/ScriptBase.java
+2
-2
ScriptCommand.java
h2/src/main/org/h2/command/dml/ScriptCommand.java
+1
-1
没有找到文件。
h2/src/docsrc/html/advanced.html
浏览文件 @
4445abd7
...
...
@@ -31,8 +31,8 @@ Advanced Topics
ODBC Driver
</a><br
/>
<a
href=
"#acid"
>
ACID
</a><br
/>
<a
href=
"#durability"
>
Durability
</a><br
/>
<a
href=
"#durability
_problems
"
>
Durability
Problems
</a><br
/>
<a
href=
"#using_recover_tool"
>
Using the Recover Tool
</a><br
/>
<a
href=
"#file_locking_protocols"
>
...
...
@@ -326,11 +326,11 @@ To uninstall the ODBC driver, double click on h2odbcUninstall.exe. This will uni
<br
/><a
name=
"acid"
></a>
<h2>
ACID
</h2>
In the
DBMS world, ACID stands for Atomicity, Consistency, Isolation, and Durability.
In the
database world, ACID stands for:
<ul>
<li>
Atomicity: Transactions must be atomic,
that means either all tasks of a transaction 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>
Isolation: Transactions must be
completely
isolated from each other.
</li><li>
Isolation: Transactions must be isolated from each other.
</li><li>
Durability: Committed transaction will not be lost.
</li></ul>
...
...
@@ -349,67 +349,75 @@ H2 supports the transaction isolation levels 'serializable', 'read committed', a
<h3>
Durability
</h3>
This database does not guarantee that all committed transactions survive a power failure.
Other databases (such as Derby) claim they can guarantee it, in reality they can't.
Testing shows that all databases sometimes lose transactions on power failure (for details, see Durability 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.
If durability is required for all possible cases of hardware failure, clustering should be used,
such as the H2 clustering mode.
<br
/><a
name=
"durability"
></a>
<h2>
Durability
</h2>
<br
/><a
name=
"durability
_problems
"
></a>
<h2>
Durability
Problems
</h2>
<p>
Complete durability means all committed transaction survive a power failure.
Some databases claim they can guarantee
complete
durability, but such claims are wrong.
Some databases claim they can guarantee durability, but such claims are wrong.
A durability test was run against H2, HSQLDB, PostgreSQL, and Derby.
All of those databases sometimes los
t
committed transactions.
The
durability
test is included in the H2 download, see org.h2.test.poweroff.Test.
All of those databases sometimes los
e
committed transactions.
The test is included in the H2 download, see org.h2.test.poweroff.Test.
</p>
<h3>
Ways to (Not) Achive Durability
</h3>
<h3>
Ways to (Not) Achieve Durability
</h3>
<p>
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, databases use different methods. One
is to use the 'synchronous write'
option when opening a fil
e. In Java, RandomAccessFile
supports the
opening
modes "rws" and "rwd":
is to use the 'synchronous write'
file access mod
e. In Java, RandomAccessFile
supports the modes "rws" and "rwd":
</p>
<ul>
<li>
rws: Every update to the file's content or metadata is written synchronously to the underlying storage device.
</li><li>
rwd: Every update to the file's content is written synchronously to the underlying storage device.
</li>
<li>
rwd: Every update to the file's content is written synchronously to the underlying storage device.
</li><li>
rws: In addition to rwd, every update to the metadata is written synchronously.
</li>
</ul>
<p>
This feature is used by Derby
and PostgreSQL
.
When running a test with one of those modes (see org.h2.test.poweroff.TestWrite), around 50 thousand write operations per second are made
.
This feature is used by Derby.
A test (org.h2.test.poweroff.TestWrite) with one of those modes achieves around 50 thousand write operations per second
.
Even when the operating system write buffer is disabled, the write rate is around 50 thousand operations per second.
However, this feature does not force changes to disk, because it does not flush hard drive buffers.
The test updates the same byte in the file again and again. If the hard drive was able to write at a rate of 50 thousand
operations per second, then the disk would need to make at least 50 thousand revolutions per second, or 3 million RPM
(revolutions per minute). There are no such hard drives. The hard drive used for the test is slower than 7000 RPM,
or about 116 revolutions per second. And because there is an overhead,
the maximum write rate must be lower than 116 operations per second.
This feature does not force changes to disk because it does not flush all buffers.
The test updates the same byte in the file again and again. If the hard drive was able to write at this rate,
then the disk would need to make at least 50 thousand revolutions per second, or 3 million RPM
(revolutions per minute). There are no such hard drives. The hard drive used for the test is about 7200 RPM,
or about 120 revolutions per second. There is an overhead, so the maximum write rate must be lower than that.
</p>
<p>
There is a way to flush hard disk buffers, and therefore force data to disk: calling fsync() in the operating system.
In Java, there are two ways to call fsync:
Buffers can be flushed by calling the function fsync. There are two ways to do that in Java:
</p>
<ul>
<li>
FileDescriptor.sync(). The documentation says that this
will force
all system buffers to synchronize with the underlying device.
<li>
FileDescriptor.sync(). The documentation says that this
forces
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.
</li><li>
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.
</li></ul>
<p>
By default,
the MySQL database uses this feature
. When using one of those methods, only around 60 write operations
By default,
MySQL calls fsync for each commit
. When using one of those methods, only around 60 write operations
per second can be achieved, which is consistent with the RPM rate of the hard drive used.
Unfortunately, even when calling FileDescriptor.sync() or FileChannel.force(),
data is not always persisted to the hard drive, because most hard drives do not obey
fsync(): see 'Your Hard Drive Lies to You' http://hardware.slashdot.org/article.pl?sid=05/05/13/0529252
&
tid=198
&
tid=128.
fsync(): see 'Your Hard Drive Lies to You' at http://hardware.slashdot.org/article.pl?sid=05/05/13/0529252.
In Mac OS X fsync does not flush hard drive buffers:
http://lists.apple.com/archives/darwin-dev/2005/Feb/msg00072.html.
So the situation is confusing, and tests prove there is a problem.
</p>
<p>
Trying to flush hard drive buffers hard, and if you do the performance is very bad.
First you need to make sure that the hard drive actually flushes all buffers.
Tests show that this can not be done in a reliable way.
Then the maximum number of transactions is around 60 per second.
Because of those reasons, the default behavior of H2 is to delay writing committed transactions.
</p>
<p>
Currently, the only way to achieve complete durability is disabling the write cache of the operating system,
using a hard drive that actually obeys the fsync() method, and using the methods FileDescriptor.sync()
or FileChannel.force(). The maximum number of transactions is then around 60 per second.
In H2, after a power failure, a bit more than one second of committed transactions may be lost.
To change the behavior, use SET WRITE_DELAY and CHECKPOINT SYNC.
Most other databases support commit delay as well.
In the performance comparison, commit delay was used for all databases that support it.
</p>
<h3>
Running the Durability Test
</h3>
...
...
@@ -420,11 +428,10 @@ The computer with the listener application opens a TCP/IP port and listens for a
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 running. 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 consult the source code of the
listener and test application.
The listener computer displays the last inserted record number every 10 seconds. Now, switch off the power
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
consult the source code of the listener and test application.
<br
/><a
name=
"using_recover_tool"
></a>
<h2>
Using the Recover Tool
</h2>
...
...
h2/src/docsrc/html/features.html
浏览文件 @
4445abd7
...
...
@@ -34,6 +34,8 @@ Features
Closing the Database
</a><br
/>
<a
href=
"#log_index_changes"
>
Log Index Changes
</a><br
/>
<a
href=
"#custom_access_mode"
>
Custom File Access Mode
</a><br
/>
<a
href=
"#multiple_connections"
>
Multiple Connections
</a><br
/>
<a
href=
"#database_file_layout"
>
...
...
@@ -435,6 +437,12 @@ This is achieved using different database URLs. The settings in the URLs are not
jdbc:h2:
<
url
>
;IGNORE_UNKNOWN_SETTINGS=TRUE
<br
/>
</td>
</tr>
<tr>
<td>
Custom File Access Mode
</td>
<td>
jdbc:h2:
<
url
>
;ACCESS_MODE_LOG=rws;ACCESS_MODE_DATA=rws
<br
/>
</td>
</tr>
<tr>
<td>
Changing Other Settings
</td>
<td>
...
...
@@ -597,6 +605,20 @@ 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
SQL grammar documentation.
<br
/><a
name=
"custom_access_mode"
></a>
<h2>
Custom File Access Mode
</h2>
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).
Also supported are 'rws' and 'rwd'.
The access mode used for log files is set via ACCESS_MODE_LOG; for
data and index files use ACCESS_MODE_DATA.
These settings must be specified in the database URL:
<pre>
String url = "jdbc:h2:test;ACCESS_MODE_LOG=rws;ACCESS_MODE_DATA=rws";
</pre>
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.
<br
/><a
name=
"multiple_connections"
></a>
<h2>
Multiple Connections
</h2>
...
...
h2/src/docsrc/html/history.html
浏览文件 @
4445abd7
...
...
@@ -37,7 +37,9 @@ Hypersonic SQL or HSQLDB. H2 is built from scratch.
<h3>
Version 1.0 (Current)
</h3>
<h3>
Version 1.0 / 2007-TODO
</h3><ul>
<li>
After calling SHUTDOWN and closing the connection and a superfluous error message appeared in the trace file. Fixed.
<li>
For most IOExceptions now the file name is included in the error message.
</li><li>
A java.util.Date object is now converted to a TIMESTAMP in the JDBC API. Previously it was converted to a DATE.
</li><li>
After calling SHUTDOWN and closing the connection and a superfluous error message appeared in the trace file. Fixed.
</li><li>
In many situations, views did not use an index if they could have. Fixed. Also the explain plan for views works now.
</li><li>
The table id (important for LOB files) is now included in INFORMATION_SCHEMA.TABLES.
</li><li>
When using DISTINCT, ORDER BY a function works now as long as it is in the column list.
...
...
h2/src/docsrc/html/mainWeb_text_.html
浏览文件 @
4445abd7
...
...
@@ -106,19 +106,21 @@ Welcome to H2, the free SQL database. The main feature of H2 are:
<tr><td
style=
"border: 0px; background-color: #eee;"
>
<h3>
News
</h3>
<p>
<b>
Email Subscription
</b>
: If you like to get informed by email about new releases,
<br
/>
subscribe here. The email addresses of members are only used in this context.
<br
/
>
Usually, only one mail every few weeks will be sent
.
<b>
Newsfeeds:
</b>
Two are available:
<a
href=
"http://www.h2database.com/html/newsfeed-atom.xml"
target=
"_blank"
>
Full text (Atom)
</a
>
and
<a
href=
"http://www.h2database.com/html/newsfeed-rss.xml"
target=
"_blank"
>
Header only (RSS)
</a>
.
</p>
<form
name=
"newsletter"
method=
"post"
action=
"php/newsletter.php"
>
<b>
Email Newsletter
</b>
: Subscribe to
<a
href=
"http://groups.google.com/group/h2database-news/subscribe"
>
H2 Database News (Google account required)
</a><br
/>
to get informed about new releases.
Your email address is only used in this context.
<br
/>
If you don't want a Google account, there is a manually maintained list as well:
<br
/>
Email:
<input
type=
"email"
name=
"email"
size=
"30"
onKeyDown=
"newsletter.spam.value='false';"
/>
<input
type=
"hidden"
name=
"spam"
value=
"true"
size=
"30"
/>
<input
type=
"hidden"
name=
"text"
value=
"subscribe"
/>
<input
type=
"submit"
value=
"Submit"
/>
<br
/><br
/>
<b>
Newsfeeds:
</b>
Two are available:
<a
href=
"http://www.h2database.com/html/newsfeed-atom.xml"
target=
"_blank"
>
Full text (Atom)
</a>
and
<a
href=
"http://www.h2database.com/html/newsfeed-rss.xml"
target=
"_blank"
>
Header only (RSS)
</a>
.
</form>
</td></tr>
</table>
...
...
h2/src/main/org/h2/api/DatabaseEventListener.java
浏览文件 @
4445abd7
...
...
@@ -28,6 +28,10 @@ public interface DatabaseEventListener extends EventListener {
/**
* This method is called if the disk space is very low.
* One strategy is to inform the user and wait for it to clean up disk space.
* Another strategy is to send an email to the administrator in this method and
* then throw a SQLException. The database should not be accessed from
* within this method (even to close it).
*
* @param stillAvailable the estimated space that is still available, in bytes
* @throws SQLException if the operation should be cancelled
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
4445abd7
...
...
@@ -3443,10 +3443,10 @@ public class Parser {
}
else
if
(
readIf
(
"DB_CLOSE_ON_EXIT"
))
{
read
();
return
new
NoOperation
(
session
);
}
else
if
(
readIf
(
"
WRITE
_MODE_LOG"
))
{
}
else
if
(
readIf
(
"
ACCESS
_MODE_LOG"
))
{
read
();
return
new
NoOperation
(
session
);
}
else
if
(
readIf
(
"
WRITE
_MODE_DATA"
))
{
}
else
if
(
readIf
(
"
ACCESS
_MODE_DATA"
))
{
read
();
return
new
NoOperation
(
session
);
}
else
if
(
readIf
(
"RECOVER"
))
{
...
...
h2/src/main/org/h2/command/dml/BackupCommand.java
浏览文件 @
4445abd7
...
...
@@ -88,7 +88,7 @@ public class BackupCommand extends Prepared {
log
.
updateKeepFiles
(-
1
);
}
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
throw
Message
.
convert
IOException
(
e
,
fileNam
e
);
}
}
...
...
h2/src/main/org/h2/command/dml/RunScriptCommand.java
浏览文件 @
4445abd7
...
...
@@ -40,7 +40,7 @@ public class RunScriptCommand extends ScriptBase {
}
reader
.
close
();
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
throw
Message
.
convert
IOException
(
e
,
null
);
}
finally
{
closeIO
();
}
...
...
h2/src/main/org/h2/command/dml/ScriptBase.java
浏览文件 @
4445abd7
...
...
@@ -97,7 +97,7 @@ public class ScriptBase extends Prepared implements DataHandler {
try
{
outStream
=
FileUtils
.
openFileOutputStream
(
new
File
(
fileName
));
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
throw
Message
.
convert
IOException
(
e
,
fileNam
e
);
}
out
=
new
BufferedOutputStream
(
outStream
,
Constants
.
IO_BUFFER_SIZE
);
out
=
CompressTool
.
wrapOutputStream
(
out
,
compressionAlgorithm
,
Constants
.
SCRIPT_SQL
);
...
...
@@ -115,7 +115,7 @@ public class ScriptBase extends Prepared implements DataHandler {
try
{
inStream
=
new
FileInputStream
(
fileName
);
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
throw
Message
.
convert
IOException
(
e
,
fileNam
e
);
}
in
=
new
BufferedInputStream
(
inStream
,
Constants
.
IO_BUFFER_SIZE
);
in
=
CompressTool
.
wrapInputStream
(
in
,
compressionAlgorithm
,
Constants
.
SCRIPT_SQL
);
...
...
h2/src/main/org/h2/command/dml/ScriptCommand.java
浏览文件 @
4445abd7
...
...
@@ -282,7 +282,7 @@ public class ScriptCommand extends ScriptBase {
}
closeIO
();
}
catch
(
IOException
e
)
{
throw
Message
.
convert
(
e
);
throw
Message
.
convert
IOException
(
e
,
fileNam
e
);
}
finally
{
closeIO
();
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论