MySQL Rollback in node.js - mysql

I'm trying to issue the following in MySQL via node.js (using the https://github.com/mysqljs/mysql library).
I'm using the transaction API to rollback when an error happens but it doesn't appear to roll back. I next tried to simplify the problem and put it directly in PHPMyAdmin SQL box to do the following....
START TRANSACTION;
UPDATE users SET balance=balance + 1 WHERE id_user='someuserid'
ROLLBACK WORK;
I was expecting the user balance to remain at it's previous value (124) but instead it keeps adding one and shows an updated balance of 125 at the end of this.
Any idea what I'm doing wrong? Could it be the MySQL Db isn't supporting of transactions and/or is UPDATE like this allowed to be rolled back in transactions?

Ok, problem solved.
For reference for anyone else encountering this it was because of the table engine being used.
My table was using MyISASM which DOES NOT support transactions and fails silently. It autocommits on every transaction hence ROLLBACK never did anything.
The fix was to change the table engine from MyISAM to InnoDB (did via phpmyadmin but could also do it via
ALTER TABLE table_name ENGINE=InnoDB; sql command.
Now the following works perfectly.
START TRANSACTION;
UPDATE users SET balance = 8 WHERE id_user='s10';
UPDATE users SET balance = 9 WHERE id_user='s12';
ROLLBACK;

Related

Updating the database tables with a new set of records without any latency in the UI display

I have a requirement where the data displayed in the UI needs to be the latest one. So, a .bat is written to update the database with the new set of data every 30 minutes. However, during the process the old data will be made to delete completely and fill with the new set of data. But, the issue is during this process, the UI will not be able to show any data, as the old data gets deleted as the first step in the process. So, is there anyway where I can update the DB table with new set of data while UI still displays the old data till the new data gets inserted? so that the UI will always some data to be displayed rather than showing no records?
Thanks,
Keerthi Kumar
You have no other processes that write to this table during your update (which I assume takes a while)?
Then simply use a transaction.
START TRANSACTION;
DELETE FROM your_table; /* Don't do a TRUNCATE TABLE; this would implicitly commit the transaction*/
INSERT INTO your_table VALUES('whatever');
COMMIT;
or
START TRANSACTION;
UPDATE your_table SET column1 = 'new_value';
COMMIT;
Other threads will still read the old data until you COMMITed your transaction.
Please read more about transactions in the manual. Also note, that this assumes you're using InnoDB engine tables.

Msg 7391: linked server unable to begin a distributed transaction (both svrs running locally)

I setup a LinkedServer from SqlServer 2014 to MySQL 5.7.3 running on my Win 10 PC. Both select & insert queries work fine alone via openquery, but the insert query won't function in a trigger. Please don't mark this as a duplicate unless you find a 'cure' that isn't already listed below!
OLE DB provider "MSDASQL" for linked server "MYSQL" returned message "[MySQL][ODBC 5.3(w) Driver]Optional feature not supported".
*Msg 7391, Level 16, State 2, Procedure TRG_AfterEventInsert, Line 14
The operation could not be performed because OLE DB provider "MSDASQL" for linked server "MYSQL" was unable to begin a distributed transaction.
There are TONS of posts on this but I have done everything I can find and it still won't work. I found a MS utility called dtcping which failed at first until I flipped a registry setting but now it succeeds.
On the DTC Properties screen I have enabled Network DTC Admin, allowed remote, allowed input/outbound without authentication and Enabled XA Transactions. On my linked server I have rpc & rpc out = true and "enable promotion of DT" false. I added the msdtc app into the firewall exclusions.
I also tried to disable DTC for my LinkedServer but that didn't work. I still get the error.
Can anyone suggest debugging measures here? I have spent almost a full day on this without success. MySQL driver is 5.3 (32bit).
UPDATE:
dtcPing runs without errors, but when I try the trigger insert I see the following in my dtctrace.log
TRANSACTION_BEGUN RM_ENLISTED_IN_TRANSACTION "resource manager #1001 enlisted as transaction enlistment #1. RM guid = '57c2b4b4-f37a-4017-a1fc-2d95bd64693d'"
RECEIVED_ABORT_REQUEST_FROM_BEGINNER "received request to abort the transaction from beginner"
TRANSACTION_ABORTING "transaction is aborting"
When you create trigger, use the following construct to avoid transactions:
create trigger ti on t for insert, update as
begin
COMMIT -- Commit FIRST to avoid DTC...
insert into [mysql]...[mysql.customers] (a,b) -- Do you work
select i, 'Test'
from inserted
BEGIN TRAN -- Start tran again otherwise it will crash!!
end
go
Note, the "[mysql]...[mysql.customers]" syntax, request Provider MSDASQL to have Level 0 only setting enabled (go to linked servers and set it on the provider).
But as other's suggested, you probably better of by just kicking a job from the trigger.
Full test code:
---------------
-- Run on MYSQL...
---------------
CREATE TABLE customers (a INT, b CHAR (20), INDEX (a)) ENGINE=InnoDB;
---------------
-- Run on SQL Server
---------------
create table t (i int)
go
create trigger ti on t for insert, update as
begin
COMMIT -- Commit tran to avoid DTC...
insert into [mysql]...[mysql.customers] (a,b)
select i, 'Test'
from inserted
begin tran -- Start tran again otherwise it will crash!
end
go
insert into t (i) select 1
-- Verify results
select *
from [mysql]...[mysql.customers]
Do you mean MySQL 5.3 ? The current manual shows versions as low as 5.7 and points that distributed transactions are only supported for the InnoDB storage engine 14.3.7 XA Transactions.
Provided you have checked all about the MySQL part, have you checked with different kind of triggers on the SQL Server side? Are you perhaps using an unsupported data type?
"A distributed query that is wrapped in a trigger, even with no
transaction explicitly specified, is also treated as a distributed
transaction."
support.microsoft.com/en-us/kb/274348
So you need to use DTC OR use (2) from Calling linked server from trigger

SQL query times out when updating using inner join?

This query dies when I try to execute it in PHP code and in phpMyAdmin.
UPDATE Inventory
INNER JOIN InventorySuppliers
ON Inventory.LocalSKU = InventorySuppliers.LocalSKU
SET Inventory.Integer2 = '1'
WHERE InventorySuppliers.SupplierSKU = '2D4027A6'
The error is:
1205 - Lock wait timeout exceeded; try restarting transaction
How can I prevent the lock timeout and/or solve this problem?
I can run this query in Microsoft Access correctly, and phpMyAdmin db is a copy of that Access database. Increasing the execution time is not an option for me as that will take too long for one record update.
$data1 = array('Inventory.Integer2'=>$shipping);
$this->db->where('InventorySuppliers.SupplierSKU', $SupplierSKU);
$this->db->update('Inventory inner join InventorySuppliers on Inventory.LocalSKU = InventorySuppliers.LocalSKU', $data1);
$this->db->close();
return ($this->db->affected_rows() > 0);
Issue this command before running your UPDATE.
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
Okay...Interesting for me...
As I told you, My SQL db was a copy from ms access db...Dont know what happened, but mysql database tables dont have primay key or index although original db has have them...I tried asigning PK and indexes, but mysql returned me error, My final solution was
Delete thetable in mysql
Make sure PK is asigned in table structures ( In my cases, after
importing from MS-Access, I have to do it again)
Check indexed feilds ( I have one feild indexed), and make sure index exists
and this did the trick for me, Now the same query is running okay...
thanks to all for the help...Hopes These two steps might help someone in future...

Syntax exception on trigger with multiple statements with MySQL and JDBC

I am trying to create a trigger that performs multiple operations in MySQL 5.5.28 with InnoDB.
I have two tables, "test" and "test_watcher": changes to the first are recorded in the watcher table with the help of triggers. The last trigger needs to perform 2 operations on DELETE, it works in MySQL Workbench (with DELIMITER) but doesn't if I create it with JDBC.
CREATE TRIGGER `AD_test_FER` AFTER DELETE
ON `test`
FOR EACH ROW
BEGIN
-- if it's been inserted, modified and deleted but never synced,
-- the revision is NULL: no one needs to know about it
DELETE FROM test_watcher WHERE pk = OLD.id AND revision IS NULL;
-- if it has been synced already, we just update the flag
UPDATE test_watcher SET flag = -1 WHERE pk = OLD.id;
END;
I keep getting com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax.
I know it works with DELIMITER $$ in Workbench, but JDBC doesn't support it.
I've achieved it in PostgreSQL and would post the code if necessary.
This behavior might be caused by the connection property allowMultiQueries=true. My guess is this property will make MySQL break up queries on the ; as a query separator and then execute those as separate queries, essentially breaking your trigger creation code.
As you said in a - now deleted - answer that adding allowMultiQueries=true actually solved the problem (contrary to my expectiation), the problem might actually be the last ; in your query. So another thing to check is if the problem goes away by removing the last ; (in END;) in your script (and not using allowMultiQueries=true). Some database don't consider ; to be valid at the end of a statement (as it is actually a delimiter to separate statements).
(this answer is based on my comment above)
If JDBC does not support delimiters (DELIMITER is a client command), then execute these two statements separately - one by one.

trouble deleting from mysql

I am fairly new to using mysql. I have an application that performs some basic querying. I am also trying to run a simple delete statement -
delete from mydb.mytable
This table is a simple 2 column table with not keys or triggers or anything defined. For some reason, the delete is not being performed. If I run the statement from MySql Workbench in the query window, it works fine. From the code, it does nothing. I am not seeing any error messages. I created a user with select, insert, update and delete rights to the schema. I am able to do the insert fine, but the delete does not seem to be working.
Is there a setting for mysql that I am missing that will not allow me to perform the delete?
Thanks for any thoughts.
Fist of all, check if
you are connected to the right database ;
you are using transaction and forgetting 'commit' ;
the user you use have enough permissions to delete from the table .
As a side notice, if you want to delete all records, you should use truncate instead of delete
Are you using transactions? My first guess is that your code might be issuing a BEGIN TRANSACTION without a COMMIT.
We would have to see some of your code to answer the question.
My guess is that you are not calling commit from your code. You can configure MySQL to auto-commit your queries, but this is usually not what you want.