-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DB-12303 Fix corrupted trigger after NSDS DML: DB-6516 regression #5694
base: master
Are you sure you want to change the base?
Conversation
jenkins please test branch @dbaas3.0 |
@msirek , this was a great description of the issue and the fix. Thanks for taking the time to clearly explain it! |
jenkins please test branch @dbaas3.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice fix!
jenkins please test branch @dbaas3.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
jenkins please test branch @dbaas3.0 |
jenkins please test branch @dbaas3.0 |
TEST SUCCEEDED +1 |
Short Description
A DML statement run in NSDS which fires a trigger may corrupt data dictionary dependencies. Subsequent DDL statements, such as TRUNCATE involving trigger tables corrupts the trigger, which may cause trigger rows to be written to the wrong table and/or be written incorrectly.
Long Description
Whenever a trigger needs recompilation due to some dictionary modification which the trigger may depend on, it is marked as invalid in the sys.sysstatements system table. For example, if the target table of the trigger is altered or another trigger is added to the same target table, the previous trigger is marked invalid. The next statement which fires the trigger causes recompilation of the trigger. First BasicDependencyManager.clearDependencies is called to remove the row in sys.sysdepends for the old version of the trigger SPSDecriptor. Then GenericTriggerExecutor.compile is called to build the new trigger SPSDecriptor and store a persistent representation of it in sys.sysstatements. Then BasicDependencyManager.addDependency is called to add the UUID of the new SPSDecriptor in sys.sysdepends, so that future DDLs know which stored statement to invalidate or clear.
The problem is that DB-6516 added a check in the addDependency method, called canUseDependencyManager, to skip adding the dependency if running NSDS. This causes any future DDL statements to not detect the trigger dependency and not recompile the trigger. When a truncate is done on the table, this should invalidate the trigger because the new table will have a new conglomerate number, but the old trigger statement still refers to the old conglomerate. When the trigger is later fired, it writes rows into a defunct table. This shows up as rows simply not appearing in the proper target table, as they are supposed to, or sometimes we hit a duplicate primary key violation, because the old table, invisible to the user, still exists in HBase, and still has rows in it (if Vacuum has not been run).
DB-6516 was trying to avoid memory leaks in the in-memory dependency manager because anything addDependency adds to the DependencyManager in NSDS was not getting released. However, if both the provider (TableDescriptor) and the dependent (SPSDescriptor) are persistent, then addDependency writes to the sys.sysdepends table and not the in-memory DependencyManager. We never want to skip writing persistent dependencies, so, the fix is to have canUseDependencyManager return true when the dependency is to be written to disk, no matter if we are running on NSDS or not.
How to test