SQL Rollback not going back to last commit - mysql

I'm having problem with the following in SQL:
SELECT
*
FROM
department_dup
ORDER BY dept_no;
Then I ran this piece of code:
COMMIT;
UPDATE department_dup
SET
dept_no = 'd011',
dept_name = 'Quality Control'
;
ROLLBACK;
SELECT * from department_dup;
But the table is not going back to the last commit
Can anyone please tell me what's going wrong here? Thanks!

By default, MySQL starts the session for each new connection with autocommit enabled, so MySQL does a commit after each SQL statement if that statement did not return an error
Option 1: Set autocomit off
SET autocommit = 0
OPtion 2: Use transaction boundaries.
START TRANSACTION;
UPDATE department_dup
SET
dept_no = 'd011',
dept_name = 'Quality Control'
;
ROLLBACK;

Related

Using IF-THEN-ELSE statement in a mySQL transaction

I am learning MySQL and i have a simple transaction to make. Need to deduct quantity from stock, if there is sufficient stock for a specific item. Else, need to roll back the whole transaction.
I have tried the following code :
SET #item_code = 'PEN-001';
set #balance = (SELECT quantity_in_hand FROM items WHERE item_code = 'PEN-001');
-- ------------------------------------------------
DELIMITER //
START TRANSACTION;
IF (#balance) >= 0 THEN
BEGIN
UPDATE items SET quantity_in_hand = #balance - #purchaseqty WHERE item_code = 'PEN-001'
END;
ELSE
BEGIN
ROLLBACK;
SELECT 'Insufficient Stock';
END;
END IF;
COMMIT;
DELIMITER ;
When I run this query in MySQL, nothing happens, there is no action output or error displayed either. Is this the right approach? And, What is the issue with this code?
You could do:
UPDATE items
SET quantity_in_hand = quantity_in_hand - #purchaseqty
WHERE item_code = 'PEN-001' and quantity_in_hand>=#purchaseqty
and then check ROW_COUNT()
The transaction in your example does nothing as rollback has nothing to do and the update when it happens, is atomic by default.

Endless deadlock situation on mySQL innoDB

Here is an issue which I encountered recently in my MySQLdb 5.7 (with innoDB engine) hosted in a Virtual Machine in my Google Cloud Platform account.
Suddenly, my DB came to a state where every transaction (such as logins) on a specific table named 'users' failed (endless timeout).
I took this error: pymysql.err.OperationalError: (1213, 'Deadlock found when trying to get lock; try restarting transaction'
Well, basically I try to find out if there is an automated recovery from this circled situation. I read in MySQL's site that by default is performed a rollback to last transaction, but why did't happen this in my situation? After a long time remaining in this situation I had to restart the MySQL server.
I need some directions on how to investigate it or take action for not facing it up again because it's a live database with customers.
MySQL's InnoDB Engine sports row-level locking, which can lead to deadlocks even when your code is inserting or updating a single row (specially if there are several indexes on the table being updated). Your best bet is to design the code around this in order to retry a transaction if it fails due to a deadlock. Some useful info about MySQL deadlock diagnose and possible workarounds is available in MySQL Official Documentation
Below is the stored procedure for the login process in which we detect the endless deadlock.
CREATE DEFINER=`root`#`%` PROCEDURE `login`(
in email1 varchar(45),
in password1 varchar(256),
in lastlogin datetime,
out s INT(1)
)
BEGIN
DECLARE p INT(11);
DECLARE counter TINYINT;
IF EXISTS (select * from user where user.email = email1 AND user.password = password1 AND user.locked = 0 AND user.inactive = 0) THEN
SELECT id INTO p FROM user WHERE user.email = email1;
SELECT user.id, user.id_user_roles, user.id_user_settings, user.first_name, user.last_name, UserRoles.description
FROM user
LEFT JOIN UserRoles
ON user.id_user_roles = UserRoles.id_user_roles WHERE user.id = p;
UPDATE user SET last_login = lastlogin WHERE user.id = p;
INSERT INTO login_info (id_user, timestamp)
VALUES (p, lastlogin);
SET s = 1;
ELSE
SELECT login_error_times INTO counter FROM user WHERE email = email1;
IF (counter < 3) THEN
SET counter = counter + 1;
UPDATE user
SET login_error_times = counter
WHERE user.email = email1;
SET s = 0;
ELSE
UPDATE user
SET locked = 1
WHERE user.email = email1;
SET s = 2;
END IF;
END IF;
END

Update mysql Table from PL SQL error ORA-28536: error in processing Heterogeneous Services initialization parameters

UPDATE query without WHERE clause working fine. But when i use WHERE clause then it shows error
ORA-28536: error in processing Heterogeneous Services initialization parameters
ORA-28507: error in data dictionary view sys.hs$_class_init
ORA-02063: preceding 2 lines from MYSQL_ATULSSO
ORA-00604: error occurred at recursive SQL level 1
ORA-02067: transaction or savepoint rollback required
ORA-00604: error occurred at recursive SQL level 1
ORA-02067: transaction or savepoint rollback required.
My code :
DECLARE
A NUMBER(15) := 70;
B NUMBER(15) := 69;
BEGIN
UPDATE ATL1_SSO_ACCESS_REQ_DETAILS A SET A.REQ_ID = B;
DBMS_OUTPUT.PUT_LINE('done11');
UPDATE ATL1_SSO_ACCESS_REQ_DETAILS A SET A.REQ_ID = B WHERE A.REQ_ID = A;
COMMIT;
DBMS_OUTPUT.PUT_LINE('done');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('not done1');
COMMIT;
END;
Output:
done1
not done
I think using table alias A in where clause may be the issue
Try the below code
DECLARE
A NUMBER(15) := 70;
B NUMBER(15) := 69;
BEGIN
UPDATE ATL1_SSO_ACCESS_REQ_DETAILS A SET
A.REQ_ID = B;
DBMS_OUTPUT.PUT_LINE('done11');
UPDATE ATL1_SSO_ACCESS_REQ_DETAILS A SET
A.REQ_ID = B WHERE A.REQ_ID = 70;
DBMS_OUTPUT.PUT_LINE('done');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('not done1');
END;
I got answer.
You can update from Database Link. Below is syntax
UPDATE "*DB_NAME*"."*TABLE_NAME*"#"*DB_LINK*"
SET "*DB_NAME*"."*TABLE_NAME*"."*COLUMN_NAME*"#"*DB_LINK*"= 'r2'
WHERE "*DB_NAME*"."*TABLE_NAME*"."*COLUMN_NAME*"#"*DB_LINK*"='r1';
example:
UPDATE "atul_sso"."ATL_SSO_ACCESS_REQ_DETAILS"#"mysql_atulsso.atul.co.in"
SET "atul_sso"."ATL_SSO_ACCESS_REQ_DETAILS"."REQ_TYPE"#"mysql_atulsso.atul.co.in"= 'r2'
WHERE "atul_sso"."ATL_SSO_ACCESS_REQ_DETAILS"."REQ_TYPE"#"mysql_atulsso.atul.co.in"='r1';
I still have one more doubt. I can not update using Synonym. is there any syntax for it ?

how to use row_count() with transAction?

i have an stored procedure in mysql like below:
BEGIN
START TRANSACTION;
INSERT INTO tbl1 (v1,v2) VALUES (p1,p2);
UPDATE tbl2 SET s1 = 1 WHERE s2 = s3;
SELECT ROW_COUNT();
COMMIT
END
in this query even the transaction doesn't commit, the row_count will be 1.
in fact my question is that how can i use row_count that it returns 0 if rollback occurred?
I ran into a similar problem recently, but I managed to solve it by selecting the row count inside of the transaction block and then returning it after the commit:
BEGIN
START TRANSACTION;
INSERT INTO tbl1 (v1,v2) VALUES (p1,p2);
UPDATE tbl2 SET s1 = 1 WHERE s2 = s3;
SET #rowCount = (SELECT ROW_COUNT());
COMMIT
SELECT #rowCount;
END
I don't know if this is the best way to solve it, but it seems to work for me :-)

MYSQL Procedures run, but return 0 rows affected

I call a procedure, it runs, and the console says "0 rows affected". Is this normal behavior for a MySQL procedure ?
The procedures are clearly doing what they should. One procedure has 2 insert statements, another has an insert and update statement, and I've seen the results with my own eyes. There are indeed rows being affected.
I'm not sure that I would use that result later on, but it seems like I'd want to get an accurate response from my DB whether or not anything was updated, especially when its expected.
Thoughts ?
MySQL 5.5 if it matters, and the procedures use transactions over auto-committed statements.
CREATE DEFINER=`root`#`localhost` PROCEDURE `create_issue`(user_id SMALLINT, title varchar(255), body LONGTEXT)
BEGIN
DECLARE MYUSERID SMALLINT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
START TRANSACTION;
INSERT INTO tracker.issue (user_id, title, body, creation_date, last_mod_date) values (user_id, title, body, CURDATE(), CURDATE());
UPDATE user_activity SET last_new_issue = CURDATE(), post_count = post_count + 1 WHERE user_activity.user_id = user_id;
COMMIT;
END
Edited to show the actual query. Also I've been searching and as best as I can tell this is a known issue over a year and a half old. So I suppose this one can be closed.
the "0 rows affected" response is for the last statement executed in the stored procedure.
usually i track the number of rows effected by manually counting them into session variables
DELIMITER $$
CREATE PROCEDURE `create_issue`(user_id SMALLINT, title varchar(255), body LONGTEXT)
BEGIN
DECLARE MYUSERID SMALLINT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
SET #inserted_rows = 0;
SET #updated_rows = 0;
START TRANSACTION;
INSERT INTO tracker.issue (user_id, title, body, creation_date, last_mod_date) values (user_id, title, body, CURDATE(), CURDATE());
SET #inserted_rows = ROW_COUNT() + #inserted_rows;
UPDATE user_activity SET last_new_issue = CURDATE(), post_count = post_count + 1 WHERE user_activity.user_id = user_id;
SET #updated_rows = ROW_COUNT() + #updated_rows;
COMMIT;
END
$$
the session variables can then be read after the SP was executed.
i am not sure if it is possible to override the response from the ROW_COUNT() function by setting a value to a variable,
I guess this is a reported bug. May be a good question for MySQL mailing list/forum. http://bugs.mysql.com/bug.php?id=44854
Something definitely isn't right. A sproc should still return the number of rows affected if there are multiple inserts occurring. I'm using the same version of MySQL and this works fine for me.
Are you sure you're not doing something like that
...SET col1='value1' AND col2='value2'...
instead of
...SET COL1='value1', col2='value2'...
Could you post your stored procedure?