Wiki Spaces
Documentation
Projects
Resources
Get Help from Others
Q&A: Ask OpenMRS »
Discussion: OpenMRS Talk »
Real-Time: IRC Chat
This article is a proposal of conflict detection and resolution, which is a result of research.
Index:
Conflict scenarios:
Greyed-out scenarios do not apply to our system, because:
To detect and resolve an update conflict for a row, the propagating site must send a certain amount of data about the new and old versions of the row to the receiving site.
More info here!
The receiving site detects an update conflict if there is any difference between the old values of the replicated row (the values before the modification) and the current values of the same row at the receiving site.
Let's take an example:
If it is possible to apply, we should check out Oracle Database Advanced Replication Management API Reference.
But out of those, only Latest Timestamp is useful with multiple master sites.
Latest Timestamp = most recent update wins
(those than offer convergence with multiple master sites)
We can easily apply Oracle example to GitHub.
Let's imagine a master branch (Parent) and two branches (Child 1 and Child 2) with Parent as upstream.
Resolving Example 1 conflict:
Git will not let Child 2 push to master, but will notify:
Updates were rejected because the remote contains work that you do not have locally.
You will be asked to pull updated master and resolve conflicts manually.
Create UI interface for choosing which changes to accept?
Microsoft's note:
To avoid potential data inconsistency, make sure that you avoid conflicts in a peer-to-peer topology, even with conflict detection enabled. To ensure that write operations for a particular row are performed at only one node, applications that access and change data must partition insert, update, and delete operations. This partitioning ensures that modifications to a given row that is originating at one node are synchronized with all other nodes in the topology before the row is modified by a different node.
So we just sync change in one node with ALL the rest?
In systems such as peer-to-peer replication, conflicts are not detected when changes are committed at individual peers. Instead, they are detected when those changes are replicated and applied at other peers. In peer-to-peer replication, conflicts are detected by the stored procedures that apply changes to each node, based on a hidden column in each published table. This hidden column stores an ID that combines an originator ID that you specify for each node and the version of the row.
empty
empty
Letting users/admin choose which change to accept.
As conflicts are logged, they can be written to a queue where conflict resolution software and kick into action and attempt to resolve the conflicts automatically.
One instance writes to all child instances - rather impossible solution
Oracle's Last Timestamp
e. Write partitioning
Ensure that all writes for a single row will always happen on the same server.
- useless in our system
The most reasonable solution for conflict detection could be:
Note: Some OpenMRS classes offer voiding, that saves outdated values as voided and keep date of change - but not all classes!
However with this solution we will have problems detecting conflicts when object are synced automatically, we should figure out if there is a solution for this case.
Different approach is better because it does not need to detect conflicts, because they can be prevented. However it requires all nodes to be updated after a single change of object in one node - that for sure is hard to accomplish due to: amount of operations that would have to be executed, constant internet connection (node-node connection).
The most reasonable solution for conflict resolution could be:
After a conflict was detected:
We need a new table in a database of each instance to store hashcodes of objects pulled from this instance's Parent.
PULL:
PULL:
* REMEMBER: This is a hashcode of an object that was calculated and saved on the last pull of this object from Parent. This hashcode is stored in a seperate table than pulled object.
** See 4.3. Merging
PUSH:
PUSH:
* REMEMBER: This is a hashcode of an object that was calculated and saved on the last pull of this object from Parent. This hashcode is stored in a seperate table than pulled object.
** See 4.3. Merging
Once a conflict was detected two objects will have to be merged. To do this, a new database table "Conflicts" will have to be created.
This table will have columns: openmrs_class, first_object, second_object and more if needed.
It will be possible to insert any type of object into child_object and parent_object due to its type: it will be either JSON, (TINY)BLOB, TEXT or else.
All conflicted objects will be put into this table and queued just like AuditLog does this.
However, there should be only the most recent merge conflict for any object. The old ones should be voided.
Then either chosen strategy or UI will be used to:
When the conflict is resolved we should save parent's object as voided in child's database.
UI for merging will use openmrs_class field to determine what class are child_object and parent_object.
Fields of determined class will be displayed as textboxes or buttons for each of two objects.
User will be able to choose which value he wants to keep.
Conflict detection and resolution by Oracle: https://docs.oracle.com/cd/E11882_01/server.112/e10706/repconflicts.htm
Microsoft SQL Server Conflict Detection in Peer-to-Peer Replication: https://docs.microsoft.com/en-us/sql/relational-databases/replication/transactional/peer-to-peer-conflict-detection-in-peer-to-peer-replication?view=sql-server-2017
Brent Ozar article: https://www.brentozar.com/archive/2011/06/resolving-conflicts-database/