前言:
HSQLDB作为一个纯java实现的开源数据库,对于我们在学习数据库实现原理方面有很大的帮助,这里只是对自己学习源码过程中的过程做了简单记录,还处于初步阶段。 通过这一段时间的学习 从大的思路角度,数据库本质上是多个客户端通过socket 客户端与 数据库服务器(soketServer端) 之间进行交互的,数据库服务器端实现了线程池以便更高效的处理客户端连接,这里顺便提一下应用服务器,应用服务器本质上也是客户端通过浏览器发起的连接,应用服务器端建立连接池处理客户端发起的连接这里很早以前写过一篇关于tomcate的文章当时也是初探没有深入研究。 总的来说大的方向就是客户端与服务器端通过soket进行连接通信,服务启动通过serversoket监听客户端的连接,客户端通过socket客户端发起连接请求,这个是大的流程,那么具体的细节要研究的东西就很多了,包含数据是如何存储到数据库的,数据是如何从数据库查询回来的,通过这一段的时间学习代码只解决了一部分疑问还有很多问题值得继续深入研究。
从数据库本身的角度来讲,其是一直在后台持续运行的一个程序。
从数据库存储数据的角度来讲,其数据是存储在各种类型的文件中的,当然在实际的处理过程中数据库本本身是有我们理解中的表,索引,视图等的实体的 只是数据 最终本质上是存储在文件汇总的,比如数据文件。
从数据查询的角度来讲,就是要将数据高效的从数据库中(文件中)查询出来,这里就涉及索引技术,比如hash索引,二叉树 等数据结构的知识。
从数据存储的角度讲,就是数据如何插入到数据库,最终如何存储到文件中,索引因为插入更新而导致的变化如何处理的,这里涉及二叉树的调整以及平衡等知识。
从sql语言的处理角度讲,就是数据库如何去识别sql语言,如何去解析,如何去转换。
以及 事物的处理,数据库存储过程,触发器,函数 等其它 功能的支撑,数据库的实现时一个相当复杂的,但是其中很多理论和只是都是我们 以前数据结构、数据库原理学习过的知识,现在回头去看以前学的东西觉得还是很有用的,只是当时我们没有意识到。
1数据库服务器创建(Server)
1.1功能描述
用于实现数据库服务器,包括数据库服务器相关的属性和操作,属性比如数据库的名字、端口、路径等信息,包含数据的相关操作如启动、停止。
此类有一个内部类ServerThread类
1.2数据库启动
数据库启动本质上是启动了一个serverThread线程
1.2.1 Server->start()
publicint start() {
serverThread = new ServerThread("HSQLDB Server ");
if (isDaemon) {
serverThread.setDaemon(true);
}
serverThread.start();
}
该线程被设置为守护线程,该线程的run 方法调用server类的run 方法实现数据库的启动。
1.2.2 ServerThread->Run()
(1) 创建一个服务器端口 ServerSocket,通过HsqlSocketFactory创建ServerSocket类
(2) 创建一个线程组,同时让当前的ServerThread作为线程组的父线程。
(3) 打开数据库,获取数据相关参数。
(4) DataBaseManager.getDatabase方法获取数据库信息,先通过数据库(根据路径生成的一个key值)缓存中获取数据库,如果存在则返回,否则直接通过Database类创建新的数据库实例。
(5) DataBase的创建过程中设置数据库状态为关闭、设置数据库类型、绝对路径、相对路径、创建日志对象用于存储操作日志。
(6) 调用database的open方法打开数据库:
void reopen() {
boolean isNew = false;
setState(DATABASE_OPENING);
try {
lobManager = new LobManager(this);
nameManager = new HsqlNameManager(this);
granteeManager = new GranteeManager(this);
userManager = new UserManager(this);
schemaManager = new SchemaManager(this);
persistentStoreCollection =
new PersistentStoreCollectionDatabase(this);
isReferentialIntegrity = true;
sessionManager = new SessionManager(this);
collation = collation.newDatabaseInstance();
dbInfo = DatabaseInformation.newDatabaseInformation(this);
txManager = new TransactionManager2PL(this);
lobManager.createSchema();
sessionManager.getSysLobSession().setSchema(
SqlInvariants.LOBS_SCHEMA);
schemaManager.setSchemaChangeTimestamp();
schemaManager.createSystemTables();
// completed metadata
logger.open();//关联到数据持久化流程,此步也是打开数据库文件的步骤
isNew = logger.isNewDatabase;
if (isNew) {
String username = urlProperties.getProperty("user", "SA");
String password = urlProperties.getProperty("password", "");
userManager.createFirstUser(username, password);
schemaManager.createPublicSchema();
logger.checkpoint(false);
}
lobManager.open();
dbInfo.setWithContent(true);
checkpointRunner = new CheckpointRunner();
timeoutRunner = new TimeoutRunner();
} catch (Throwable e) {
logger.close(Database.CLOSEMODE_IMMEDIATELY);
logger.releaseLock();
setState(DATABASE_SHUTDOWN);
clearStructures();
DatabaseManager.removeDatabase(this);
if (!(e instanceof HsqlException)) {
e = Error.error(ErrorCode.GENERAL_ERROR, e);
}
logger.logSevereEvent("could not reopen database", e);
throw (HsqlException) e;
}
setState(DATABASE_ONLINE);
}
1.2.1 客户端请求接收并处理
此部分的入口是在创建完serversoket后执行的,也在run方法中。
try {
/*
* This loop is necessary for UNIX w/ Sun Java 1.3 because
* in that case the socket.close() elsewhere will not
* interrupt this accept().
*/
while (socket != null) {
try {
handleConnection(socket.accept());// 接收并处理客户端发起的请求
} catch (java.io.InterruptedIOException iioe) {}
}
} catch (IOException ioe) {
if (getState() == ServerConstants.SERVER_STATE_ONLINE) {
setServerError(ioe);
printError(this + ".run()/handleConnection(): ");
printStackTrace(ioe);
}
} catch (Throwable t) {
printWithThread(t.toString());
} finally {
shutdown(false); // or maybe getServerError() != null?
}
1.2.2 客户端请求处理步骤
publicvoid handleConnection(Socket s) {
Thread t;
Runnable r;
String ctn;
printWithThread("handleConnection(" + s + ") entered");
if (!allowConnection(s)) {
try {
s.close();
} catch (Exception e) {}
printWithThread("allowConnection(): connection refused");
printWithThread("handleConnection() exited");
return;
}
// Maybe set up socket options, SSL
// Session tracing/callbacks, etc.
if (socketFactory != null) {
socketFactory.configureSocket(s);
}
if (serverProtocol == ServerConstants.SC_PROTOCOL_HSQL) {
r = new ServerConnection(s, this);
ctn = ((ServerConnection) r).getConnectionThreadName();
} else {
r = new WebServerConnection(s, (WebServer) this);
ctn = ((WebServerConnection) r).getConnectionThreadName();
}
t = new Thread(serverConnectionThreadGroup, r, ctn);
t.start();
printWithThread("handleConnection() exited");
}
(1) 初步判断如是否允许该socket建立连接
(2) 根据服务类型判断创建哪种类型的连接,比如是Server类创建ServerConnection如果是webserver则创建WebServerConnection,每一个连接是一个单独的线程、
(3) 将连接线程加入到线程组中。
1.3数据库创建
此部分是对1.2.2 database.open方法的详细说明
1.3.1 LobManager创建schema
(1) 加载自定义的初始化脚本/org/hsqldb/resources/lob-schema.sql
1.3.2 SchemaManager创建SystemTable
1.3.3 Logger打开日志并且设置为新建数据库日志
1.3.4 UsernManager创建第一个用户
1.3.5 Schemanager创建publicSchema
Schema用于存储hsqldb的所有对象信息
// SCHEMA management
publicvoid createPublicSchema() {
writeLock.lock();
try {
HsqlName name = database.nameManager.newHsqlName(null,
SqlInvariants.PUBLIC_SCHEMA, SchemaObject.SCHEMA);
Schema schema =
new Schema(name, database.getGranteeManager().getDBARole());
defaultSchemaHsqlName = schema.getName();
schemaMap.put(schema.getName().name, schema);
} finally {
writeLock.unlock();
}
}
1.3.6 Schema类包含的特性
public Schema(HsqlName name, Grantee owner) {
this.name = name;
triggerLookup = new SchemaObjectSet(SchemaObject.TRIGGER);
indexLookup = new SchemaObjectSet(SchemaObject.INDEX);
constraintLookup = new SchemaObjectSet(SchemaObject.CONSTRAINT);
tableLookup = new SchemaObjectSet(SchemaObject.TABLE);
sequenceLookup = new SchemaObjectSet(SchemaObject.SEQUENCE);
typeLookup = new SchemaObjectSet(SchemaObject.TYPE);
charsetLookup = new SchemaObjectSet(SchemaObject.CHARSET);
collationLookup = new SchemaObjectSet(SchemaObject.COLLATION);
procedureLookup = new SchemaObjectSet(SchemaObject.PROCEDURE);
functionLookup = new SchemaObjectSet(SchemaObject.FUNCTION);
specificRoutineLookup =
new SchemaObjectSet(SchemaObject.SPECIFIC_ROUTINE);
assertionLookup = new SchemaObjectSet(SchemaObject.ASSERTION);
tableList = (HashMappedList) tableLookup.map;
sequenceList = (HashMappedList) sequenceLookup.map;
name.owner = owner;
}
1.3.7 创建checkPoint生成后台线程
checkpointRunner = new CheckpointRunner();
1.3.8 创建timeOut生成后台线程
timeoutRunner = new TimeoutRunner();