I'd be grateful for your insights into a design idea so that I don't head down a dead-end road. Alternatives appreciated!
Our requirement is for a relatively small DB with a low rate of transactions. I'd like to be able to have a db clone on each of 3 nodes. Clients would be directed to one node via a virtual IP; the cluster would apply all operations at that IP and to two copies. If either
copy (not the 'master' at the virtual IP) fails the cluster continues to operate normally; after the node is recovered CreateCluster is re-run as usual, albeit with 3 nodes. If the master (the node at the virtual IP) fails our code selects a new master from the 2 copies; that node takes over the virtual IP and the cluster begins operating as though a copy has failed.
As far as I can see this imposes only 2 requirements on H2 that are different than usual: 1) support for a client JDBC url naming a single tcp server while in cluster mode, and 2) support for 3 nodes in a CreateCluster -serverList.
Re (1): an attempt to connect to a cluster using a single node JDBC url (e.g. "jdbc:h2:tcp://
172.16.35.53:9101/msp") receives a response: "Cannot connect to <dbname>. Check your URL. Clustering error - database currently runs in cluster mode: server list <server:port>,<server>:<port>". Is the server topology exposed so that client-side code can redirect a failed operation to the alternate server? The design I am suggesting hides the topology - and requires that a single node URL be accepted by the server.
I've begun exploring this a bit (2) a bit. I have a working 2 node cluster (nodes .55 and .53). I run the server on a third node (.51):
java -cp /usr/lib/java/*:. org.h2.tools.Server -tcp -tcpPort 9101 -tcpAllowOthers -baseDir <base> &
Then on my 'first' server (.55) I successfully run CreateCluster, which creates the db files on node .51:
java -cp /usr/lib/java/*:. org.h2.tools.CreateCluster \
Expecting the cluster to only use 2 nodes, I put the new .51 node second in the serverlist. The H2 log on .51 shows an update to the CLUSTER server list and includes all three servers:
10-02 09:14:27 index: SYS_DATA remove ( /* key:77 */ 58, 0, 6, 'SET CLUSTER ''''')
10-02 09:14:27 pageStore: log - s: 1 table: 0 row: ( /* key:77 */ 58, 0, 6, 'SET CLUSTER ''''')
10-02 09:14:27 pageStore: log commit s: 1
10-02 09:14:27 lock: 1 exclusive write lock unlock SYS
10-02 09:14:27 jdbc[20]:
Code in SessionRemote loops through the serverlist applying any SQL operation, so this looks very promising.
However, at the start of handling a SQL command, H2 removes that value and replaces it with a 2 node list, and the new node is not in that list:
10-02 09:17:06 jdbc[21]:
/*SQL */SET CLUSTER TRUE;
10-02 09:17:06 lock: 1 exclusive write lock requesting for SYS
10-02 09:17:06 lock: 1 exclusive write lock added for SYS
10-02 09:17:06 index: SYS_DATA add ( /* key:79 */ 58, 0, 6, 'SET CLUSTER ''
172.16.35.55:9101,172.16.35.53:9101''')
10-02 09:17:06 pageStore: log + s: 1 table: 0 row: ( /* key:79 */ 58, 0, 6, 'SET CLUSTER ''
172.16.35.55:9101,172.16.35.53:9101''')
I'll be looking into this.
I also see this interesting comment at line 397:
// TODO cluster: support more than 2 connections
What would need to be done?
Thanks!