So I am right now developing a backend API using GraphQL and either Python with SQLAlchemy or Node.js with Sequelize to write all the data into a SQLite database.
I am still not sure what backend I will end up with. Maybe this question and the answer to my question will lead me to using one or the other.
So my app will have a function where you add dart throws (like double 20, triple 19, ...) into a table with throws. Depending on the game chosen and the conditions chosen this throw will either substract from a total count or maybe be added into a counter table or something like that.
Everytime a throw gets added there will be a check if the game is won and some other checks as well. Those might also write (commit) data to the database.
Now, if the user types in the wrong number / or the automatic darts machine will discover the wrong throw number (malfunction) there is a throw and several changed data in the database which I will have to rollback.
In darts scorer apps you will find in the app store either ios or android you always will have a undo button which will erase the throw from the database and all the "effects" caused by entering the wrong throw.
As a former mssql administrator my first idea was transactional logs and rollback function. But after searching the net for a while I understand both SQLAlchemy and Sequelize will rollback transactions only on exception.
Can I purposely rollback the last "complete" transaction (meaning all changes which for example a function will make by the end of the function) by hitting a button / calling a rest api path like '/undo' and if so are there any code snippets for either SQLAlchemy or Sequelize I am missing?
Best regards,
Patrick
edit:
collection of provided answers:
command pattern (python)
According to Can I rollback a transaction I've already committed? (data loss) and other sources, no, you cannot rollback a committed transaction. Also this is DB dependent, so doesn't have to do much with ORM or language.
I would recommend to implement the Command pattern, which is great for Undo. So basically do the revert from code, not from the database.
Related
I am using Django with Mysql as part of a product. Occasionally some table gets corrupted and when accessing the table I get the exception:
InternalError: (145, "Table 'some_table' is marked as crashed and should be repaired")
I then need to run a sql script which uses REPAIR TABLE command to fix the issue.
My questions are:
Is there a django mechanism which will detect this issue, run "REPAIR TABLE some_table", print notification and then retry the operation which has failed?
if not - is it reasonable to put a decorator to django interface functions like filter, save etc.?
of course if the operation will fail again after repair I will want to print something rather than continue to run the db operation again.
I appreciate any answer especially one with an elaborated python example.
Thanks in advance.
I appreciate that this would be an incredibly DevOps feature to have, but I dare say that if your table is randomly getting corrupted and the extent of your caring is to run REPAIR TABLE some_table; when it errors out, you should probably skip straight to
ALTER TABLE some_table ENGINE=BLACKHOLE;
That will be a lot more robust on an otherwise unstable system.
I'm new to Flask and web development in general. I have a Flask web-application that is using SQLAlchemy, is it ok to put session.rollback at the beginning of the app in order to keep it running even after a transaction fails?
I had a problem with my website when it stopped working after I was attempting to delete records of one table. The error log showed that the deletion failed due to entries in another table still referencing these records as their foreign key. The error log suggested using session.rollback to rollback this change, so I put it at the beginning of my app just after binding my database and creating the session and my website worked. This gave me the hint to leave that line there. Is my move right, safe and ok? Can anyone tell me what is the correct thing to do if this is somewhat endangering the functionality or logic of my website by any chance?
I'd say by that you are by definition cargo cult coding and should try to determine why you're finding these errors in the first place instead of just including a bit of code for a reason you don't understand.
The problem you're describing is the result of using foreign keys to ensure data integrity in your database. Typically SQLAlchemy will nullify all of the depending foreign keys, but since I don't know anything about your set up I can't explain why it wasn't. It is perhaps a difference between databases.
One massive problem with putting the rollback at the beginning of a route (or the entire global app) is that you might rollback data which you didn't want to. You haven't provided an MVCE so no one can really help you debug your problem.
Cargo cult coding in circumstances like this is understandable, but it's never a good practice. To solve this problem, investigate the cascades in SQLAlchemy. Also, fire up your actual SQL db interface and look at the data's structure, and set SQLALCHEMY_ECHO = 1 in your config file to see what's actually getting emitted.
Good luck!
You should not use the rollback at the beginning but when a database operation fails.
The error is due to an integrity condition in your database. Some rows in your table are being referenced by another table. So, you have to remove referencing rows first.
I'm using Django Python framework, and MySQL DBMS.
In the screenshot below, I'm creating the new_survey_draft object using the SurveyDraft.objects.create() as shown, assuming that it should create a new row in the surveydraft DB table, but as also shown in the screenshot, and after debugging my code, the new_survey_draft object was created with id=pk=270 , while the DB table shown in the other window to the right doesn't have the new row with the id=270.
Even when setting a break point in the publish_survey_draft() called after the object instantiation, I called the SurveyDraft.objects.get(pk=270) which returned the object, but still there is not id=270 in the DB table.
And finally, after resuming the code and returning from all definitions, the row was successfully added to the DB table with the id=270.
I'm wondering what's happening behind the seen, and is it possible that Django stores data in objects without persisting to DB on real-time, and only persists the data all together on some later execution point?
I've been stuck in this for hours and couldn't find anything helpful online, so I really appreciate any advice regarding the issue.
After digging deep into this issue, I just found that there is a concept called Atomic Requests that's enabled in my Django project by setting the ATOMIC_REQUESTS to True in the settings.py under the DATABASES dictionary as explained here
It works like this. Before calling a view function, Django starts a
transaction. If the response is produced without problems, Django
commits the transaction. If the view produces an exception, Django
rolls back the transaction.
That's why the changes were not persisting in the database while debugging my code using break points, since the changes will only be committed to the DB once the successful response is returned.
Some devices are asynchronously storing values on a common remote MySQL database server.
I would like to write a supervisor app in Python (and possibly SQLAlchemy) to recognize the external INSERT events on the database and act upon the last rows' data. This is to avoid a long manual test to see if every table is being updated regularly or a logger crashed.
Can somebody just tell me where to search online this kind of info and, even better, an example?
EDIT
I already read all tables periodically using a datetime primary key ({date_time}), loading the last row of each table, and comparing to the previous values:
SELECT * FROM table ORDER BY date_time DESC LIMIT 1
but it looks very cumbersome and doesn't guarantee that I don't lose some rows between successive database checks.
The engine is an old version of INNODB that I cannot upgrade: I cannot use the UPDATE field in schema because it simply doesn't work.
To reword my question:
How to listen any database event with a daemon-like Python application (sleeping thread) and wake up only when something happens?
I want also to avoid SQL triggers because this would be just too heavy to manage: tables are in hundreds and they are added/removed very often according to the active loggers.
I gave a look to SQLAlchemy but all reference I could find, if I don't misunderstood it, are decorators to act on INSERTs made by SQLAlchemy's itself. I didn't find anything about external changes to the database.
About the example request: I am not interested in a copy-and-paste, because first I want to understand how stuff works. I prefer (even incomplete) examples because SQLAlchemy documentation is far too deep for my knowledge and I simply cannot put the pieces together.
Is there any simple way to define critical section?
when a user during the updating some database table, I'd force to make the other user cannot update on the same tables.
django-concurrency is an optimistic lock 1 implementation for
Django.
Tested with: 1.4.x, 1.5.x, 1.6.x, 1.7.x 1.8.x.
It prevents users from doing concurrent editing in Django both from UI
and from a django command.
I never used, but i think this can solve your problem.
django-concurrency
It depends what are your queries, Your single query to the database will never face any race condition due to ACID principle impose by the database. But if there is any condition like first you are reading the data from database and after some operation on application level you are writing the updated data back to the database, then race condition may occur for that you have to implement the locks or the mutex in python.