-
-
Notifications
You must be signed in to change notification settings - Fork 816
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
Transaction support #304
Comments
It seems impossible to ensure transaction properties with
If i understand properly, function tx_handler(callback, commit) {
return function() {
var args = Array.prototype.slice.call(arguments);
var err = args[0];
if(err) db.run('rollback');
else if(commit) db.run('commit');
if(callback)
callback.apply(this, args);
}
}
var db1 = new sqlite3.Database('file');
var db2 = new sqlite3.Database('file');
db1.serialize(function () {
db1.run('begin transcation');
db1.run('insert something', tx_handler( ... ) );
...
db1.run('insert something', tx_handler( ..., true ) ); // will commit upon success
});
db2.serialize(function () {
db2.run('begin transcation');
db2.run('insert something', tx_handler( ... ) );
...
db2.run('insert something', tx_handler( ..., true ) ); // will commit upon success
}); |
@yelouafi Right, separate database objects are required. So, I guess the conclusion is: If I want to do a transaction then I have to create a new sqlite3.Database object. I should not use this database object for anything else other than this transaction (alternatively i have to somehow track that there is no pending transaction). The reason for the above conclusion is because https://github.com/mapbox/node-sqlite3/wiki/Control-Flow says that
This means that the commit and rollback commands in your tx_handler are not serialized. So if something makes calls after db1.serialize using db1 then we are in trouble. This further leads me to conclude that db.serialize() itself is pointless with transactions. If I am doing a transaction, I just create a new database object and throw it away after the transaction. Do you agree? I guess a feature suggestion at this point is to implement database object pooling with the above in mind. |
Yes, this could be achieved by some pool implementation (see below)
I don't think this is a good idea; you'll have to ensure Transaction semantics yourself (specially Isolation) ; this is a burden the database should take care of (and can better handle)
This is true if there is no dependence between executed statements; otherwise (as in master-detail updates) you'll have to ensure proper order of execution
+1 for pooling. note that you can have separate needs following the operation you need
According to documentation it would be safe to start the transaction with 'begin immediate'
|
@yelouafi Thanks for your comments and analysis! Really helped me think it through. |
I have implemented exactly that some time ago. It works quite well for small amount of transactions. |
I too am trying go get my head around this issue. In particular trying to understand why @Strix-CZ thinks you need https://github.com/Strix-CZ/sqlite3-transactions I have a web application https://github.com/akc42/MBBall which I am about to rewrite the client, and am trying to understand whether to leave the server in php or convert to javascript for the server using express. .With node.js and potentially a single thread for multiple requests, I want to ensure transaction isolation between the different requests coming in from multiple clients (all running the same version of the application). The thing that I think is confusing me is the same words that @gramakri reference
If at the start of every request I do something like
Will it be isolated from all other requests. Will other simulteneous requests somehow be able to be interspersed on the same connection. In particular see my thoughts here http://stackoverflow.com/questions/3630/sqlite-vs-mysql/3933794#3933794 about using WAL mode, and having a very efficient transactions. If I have to effectively isolate each request myself - which I think @Strix-CZ sqlite3-transactions module does, I think it would be inefficient. |
Just a quick answer for now. I will have more time in the evening. In this case you don't need it. You need it only when there is an asynchronous function call between
|
One option to avoid problems with transactions is to use stored procedures On this case your code would store pre-defined procedures on the database, and later it will just call the procedure with arguments, like this: db.run("CALL add_new_sale(ARRAY( ARRAY('DJI Avata',1,1168.00), ARRAY('iPhone 14',1,799.90), ARRAY('iWatch',2,249.99) ))") Procedure calls are handled on their own transactions, so they are isolated by default. Changes from one call will not interfere in changes from another call. You will need to rebuild node-sqlite3 to use the modified sqlite3 library, though |
Transactions can be performed either using
Note that we cannot call rollback/commit in the callbacks of db.run() because they aren't part of the serialize.
Am I missing something obvious?
The text was updated successfully, but these errors were encountered: