Forum > Databases

IBX : Can it handle database operation when network connection is not stable?

<< < (4/9) > >>

Zvoni:

--- Quote from: incendio on November 24, 2021, 02:29:00 pm ---Not all data needs to be replicated, only the data that are being input / edit by users.

--- End quote ---
That's the core-definition of Replication.
Only Data which has been
1) Added
2) Changed
3) Deleted
gets (its statement) replicated. No change=No Replication

And Mark described it perfectly

tonyw:

--- Quote from: incendio on November 24, 2021, 07:39:14 am ---Hi guys,

I have this situations :

* Use IBX for database operations
* Use TIBDataset with CacheUpdate Enabled
I have an TDBEdit, with value = 'abc', then edit its value to 'abcde'

To Update database, I clicked Save button, which codes something like this

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.btnSaveClick(Sender: TObject);var  Tbl : array [1..1] of TDataSet; begin  Tbl[1] := Dt;  Dba.ApplyUpdates( Tbl);  ShowMessage('saved');end; 
That code works OK when network connection is OK, database value updated to 'abcde', but when network connection is lost, Dialog box showed with error message and option to click OK or Abort.
Error reading data from connection

That error was expected, if users click Abort, app closed, if user click OK, app not closed, value of TDBEdit in the screen still 'abcde'.

Problem is, when network connection restored again while app still open/ not restarted again, clicked again button Save still got same error like above.

Is IBX able to save data to the data  when network connection is restore again without need to restart the app?

--- End quote ---

IBX depends on the Firebird Client library as does any Firebird database client. This does not have any explicit code to recover from lost connections. When a connection is lost, the Firebird server will put the current transaction into limbo which, in theory, could allow a database adminstrator to recover any "lost" data. However, that is not always an easy procedure.

In the case of an unstable connection, your strategies are:

1. In your client systems firebird.conf file set DummyPacketInterval=0. This will avoid timeouts on inactive connections when the underlying network is unstable. However, this will not help drop outs during an update. Could be problematic.

2. Don't use ApplyUpdates or cached updates in general. All this does it make it more likely that you will lose all your updates when a connection fails. Instead, set each dataset's AutoCommit property to acCommitRetaining. This will ensure that every update is written through to the database i.e. minimising the risk of data loss.

3. Add an event handler to your TIBDatabase component to automatically re-open the database after an unexpected disconnection. You will probably want to use Application.QueueAsyncCall in the event handler to queue the re-open to ensure a tidy-up before re-opening. Your re-open procedure should re-open all previously open datasets. They should then open in the state they were in after the last autocommit.

incendio:

--- Quote from: tonyw on November 24, 2021, 05:55:31 pm ---
1. In your client systems firebird.conf file set DummyPacketInterval=0. This will avoid timeouts on inactive connections when the underlying network is unstable. However, this will not help drop outs during an update. Could be problematic.

2. Don't use ApplyUpdates or cached updates in general. All this does it make it more likely that you will lose all your updates when a connection fails. Instead, set each dataset's AutoCommit property to acCommitRetaining. This will ensure that every update is written through to the database i.e. minimising the risk of data loss.

3. Add an event handler to your TIBDatabase component to automatically re-open the database after an unexpected disconnection. You will probably want to use Application.QueueAsyncCall in the event handler to queue the re-open to ensure a tidy-up before re-opening. Your re-open procedure should re-open all previously open datasets. They should then open in the state they were in after the last autocommit.

--- End quote ---

1. Usually, I don't install firebird in client, only supplied my app + fbclient.dll to client.

2. Back in C++ Builder, always use ApplyUpdates. If I use dataset's AutoCommit, in Master Detail table, wouldn't it be problems when only data in Master table saved, while data in Detail not saved due to some errors?

3. I am able re-open the database with this code

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.OpenDt();begin  Dba.Close(true);  Dba.Open;  Trs.Active:=true;  Dt.Open;   if (Dba.Connected) then ShowMessage('data opened');end;  
Dba must be closed first (which means lost all data entry/edit from users), otherwise, when tried to saved again, same error about reading connection occur again.

MarkMLl:

--- Quote from: incendio on November 25, 2021, 04:01:56 am ---1. Usually, I don't install firebird in client, only supplied my app + fbclient.dll to client.

--- End quote ---

I think he means the "client software", i.e. the libraries etc. which are installed on any computer which wants to talk to the server.

Going back to the original question, any unique or sequential columns will obviously need to be handled specially since the value to be stored won't be known until on the actual server.

MarkMLl

tonyw:

--- Quote from: incendio on November 25, 2021, 04:01:56 am ---
1. Usually, I don't install firebird in client, only supplied my app + fbclient.dll to client.

2. Back in C++ Builder, always use ApplyUpdates. If I use dataset's AutoCommit, in Master Detail table, wouldn't it be problems when only data in Master table saved, while data in Detail not saved due to some errors?

3. I am able re-open the database with this code

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.OpenDt();begin  Dba.Close(true);  Dba.Open;  Trs.Active:=true;  Dt.Open;   if (Dba.Connected) then ShowMessage('data opened');end;  
Dba must be closed first (which means lost all data entry/edit from users), otherwise, when tried to saved again, same error about reading connection occur again.

--- End quote ---

The main issue with Master/Detail is that you usually need to make sure that changes to master and detail tables are posted in the correct order to avoid foreign key constraints being violated. If you are using master/detail then yes, you do usually want to post the changes in the correct order and then commit them all at once. ApplyUpdates does not help you here any more than a standard Post. ApplyUpdates is used with cached updates and can be more problematic with Master/Detail than using non-cached updates. This is because it is very easy to get the update order wrong if you are mixing insert and delete actions on the master record and using cached updates on the detail.

I would advise using proper transaction control instead of cached updates. When you have an unstable connection, you want to commit as often as makes sense for your application as that minimises the risk of a transaction being lost or ending up in limbo. With a simple one table at a time approach, AutoCommit works. With Master/Detail then you have to be cleverer.

If you are reacting to an exception that reports the loss of a connection then yes, you should explicitly close the database "IBConnection.Active := false;" before re-opening and telling your user that the last transaction may have been lost.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version