Items within the BitShares database have an identifier. They are mostly hidden from the end-user. But when we do some elementary development using the BitShares platform, database ids become important. And they have a property that is not obvious at first glance.
In short, if you do an operation that assigns a database id, you should not trust that id. That sounds like a bug, but it is actually part of the distributed nature of how BitShares works. Let me explain.
The BitShares network is a large collection of nodes (a.k.a. machines) that clients connect to. Those nodes talk to each other, and constantly share information. There are many nodes in the network. But to make explanations easier, I will talk as if there are only 3 nodes. We will call them NodeA, NodeB, and NodeC.
Now we will set up the scenario.
Just 3 minutes from now, it is NodeC's turn to make a block.
One minute from now, Alice, who is connected to NodeA, creates a database object. NodeA says the next available identifier is 1.15.16.
Just a few seconds from when Alice created her database object, Bob, who is connected to NodeB, creates the same kind of database object, albeit with different values. NodeB says the next available identifier is 1.15.16.
All 3 nodes share the information. Although there is a conflict, it is allowed to exist for a time.
It is the responsibility of the block producer (NodeC) to resolve the conflict. NodeC creates a new block. The next last block identifier was 1092, so NodeC will make hers 1093. NodeC decides that both transactions should go in this block, and decides that the database id of Bob's transaction should change from 1.15.16 to 1.15.17. Such a change resolves the conflict. NodeC then sends the new block to NodeA and NodeB.
NodeA and NodeB now revert (a.k.a. Undo) their transactions that were waiting for a block to be produced. They then apply the transactions that are in the new block. Now all 3 nodes agree that Alice created 1.15.16, and Bob created 1.15.17.
If you have questions about Bitshares database ids, and why they can change, please read the above slowly until you understand it. Feel free to ask questions until it is clear. Then read the following...
The above scenario is an over simplification of what happens. But there is another scenario that you must be aware of when dealing with database ids. It has to do with forks. To explain, we will have to make the network bigger.
Imagine a network with 26 nodes. We will call them NodeA, NodeB, and so forth until NodeZ. As before, they constantly talk to each other. In addition, 21 of those nodes are elected as block-producing nodes. These are special nodes that create blocks and make sure that the network stays sane. If a node creates a block that another node disagrees with, we have a fork.
Don't worry. Forks are not as scary as some make it out to be. It is a common and solvable puzzle, as long as the rules are well defined. We will take the example of Alice and Bob above, and twist it a bit.
Imagine that NodeC creates a block (number 1093), and that block assigns Alice's transaction a database id of 1.15.16 and Bob the transaction id of 1.15.17. Nothing new there. This is just as before.
Now it is NodeR's turn to make a block. But he didn't get NodeC's block. Perhaps there was some network problem between NodeR and NodeC. When it makes the block, it assigns his block number 1093, and assigns Bob's transaction a database id of 1.15.16, and Alice 1.15.17. The opposite of what NodeC did. It also transmits that new block to all the other nodes. Now it looks like we have a big mess. But don't worry. The network can sort it out.
Now it is NodeN's turn to make a block. NodeN sees all the previous blocks, including what NodeC and NodeR created. It sees that there are two blocks numbered 1093, and it needs to choose which of these forks it should attach its block to. It decides that NodeC's block is the correct one, and makes block 1094 based on that. It again shares its new block to the entire network.
This cycle can repeat several times, and block-producing nodes can elect which fork it wants to use. Eventually one fork wins, and the other fork is "rolled back" (a.k.a "undone").
Bonus material: Who determines the winner?
BitShares uses the rule "two-thirds plus one". With 21 block producing nodes, two-thirds plus one equals 15. When 15 block producing nodes say a certain block is correct, the block is said to be irreversible. Any other blocks on other forks that are older than that approved block are deleted. That block is on the chain permanently.
Once a block is irreversible, you are finally guaranteed that the values of the database ids of Alice and Bob are permanent, and will not change in the future.
Complicated? Yes. But in a distributed network of nodes, this is the way to provide fast creation of transactions and a reliable network.
I hope this explanation helps. Feel free to comment below.
In addition, I am not claiming to be the expert here. Please let me know if you see something that may be incorrect or needs clarification. I will research it.