How do transactions within stored procedures affect each other? Is it possible to use this structure or will the second procedure interrupt the transaction of the first one?
CREATE PROCEDURE some_procedure() begin
...
CALL some_procedure1();
CALL some_procedure2();
...
end
CREATE PROCEDURE some_procedure1() begin
START TRANSACTION;
...
COMMIT;
end
CREATE PROCEDURE some_procedure2() begin
START TRANSACTION;
...
COMMIT;
end
There's only one thread for a given MySQL session, so the procedures run serially.
some_procedure1() commits its transaction before it returns, and that must finish before some_procedure2() is called.
Related
I have wrote this procedure which creates new A/c voucher. It runs on MySql 5.0. Now, it's time to implement this in our production. But I am not sure that it meets the requirement. Is this Lock Strategy perfect ? Please help.
It calls this way :
CALL SpAcVoucherCreate(1,'2022/03/31','2831',5000,'A001');
My procedure is as follows :
USE `FinanceDB`;
DROP PROCEDURE IF EXISTS `SpAcVoucherCreate`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `SpAcVoucherCreate`(
V_VOCHNO INT,
V_VOCHDT CHAR(10),
V_ACCODE CHAR(4),
V_AMOUNT DECIMAL(12,2),
V_USER_ID CHAR(5)
)
BEGIN
DECLARE V_ERR_OCCURED BOOLEAN;
SET V_ERR_OCCURED=FALSE;
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
SET V_ERR_OCCURED=TRUE;
SET AUTOCOMMIT=0;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
LOCK TABLES `ACTRANS` WRITE;
INSERT INTO ACTRANS
(VOCHNO,VOCHDT,ACCODE,AMOUNT,USER_ID)
VALUES
(V_VOCHNO,V_VOCHDT,V_ACCODE,V_AMOUNT,V_USER_ID);
IF V_ERR_OCCURED=TRUE THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
UNLOCK TABLES;
SET AUTOCOMMIT=1;
END;
END $$
DELIMITER ;
I find the procedure to be doing several things that are unnecessary.
SERIALIZABLE acts the same as REPEATABLE READ for what you're doing. The only effect of SERIALIZABLE in MySQL is that it makes non-locking SELECT statements into locking SELECT statements as if you had used SELECT...LOCK IN SHARE MODE. Since you only do an INSERT, this difference has no effect.
There's no need to disable autocommit and then do a transaction start and commit/rollback for a single statement. If you had left autocommit enabled, then a successful INSERT would commit, and an unsuccessful INSERT would not commit. It would have the same result as your code.
There would be no need for an SQLEXCEPTION handler to rollback the transaction, because you have only a single statement in the transaction. It either succeeds or it does not succeed.
Regardless of any of the above, you have shown no reason to use LOCK TABLES. It will only block INSERT/UPDATE/DELETE unnecessarily, if multiple clients try to add rows concurrently. If there is a special reason you need to do this, you have not described it.
Your procedure body has an unnecessary BEGIN/END block. It doesn't do anything. Also I believe that DECLARE is only allowed following the first BEGIN, not within other blocks in the body.
There is probably no reason to use a stored procedure at all, since it only accomplishes a single INSERT operation. Why not just do the INSERT directly in the client? I suppose if you want to restrict the privilege to do inserts to the procedure, if the user doesn't have that privilege, that would be a reason.
I also agree with the comment above that you are using a version of MySQL that is suspiciously out of date. MySQL 5.0 passed its end of life date in 2012, according to https://endoflife.software/applications/databases/mysql. You are missing many bug fixes, security patches, and of course modern features.
Update:
The comment from SolarFlare is correct, one is not allowed to use LOCK or UNLOCK statements in stored procedures in MySQL:
mysql> create procedure p()
-> begin
-> lock tables mytable write;
-> insert into mytable () values ();
-> unlock tables;
-> end//
ERROR 1314 (0A000): LOCK is not allowed in stored procedures
I'm trying to write a template for building my database. I want the template to wrap all commands in a transaction so it can be automatically rolled back if anything fails.
Currently, I'm using a stored procedure containing this general structure:
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;
START TRANSACTION;
-- Commands here
COMMIT;
However there are some issues with this, for example it's impossible to add other stored procedures from a stored procedure. So I would like to have a similar functionality without being wrapped in a stored procedure. Is this possible? I haven't been able to find any way to catch SQL exceptions outside a stored procedure and without that I can't automatically rollback on error.
I've also tried something like this with the hopes that on an error execution should crash out of the first section without committing and then continuing on the next section with the rollback. But that doesn't seem to work:
DELIMITER //
START TRANSACTION;
-- Commands here
COMMIT//
ROLLBACK//
DELIMITER ;
I want to call rest api in a POST method from a stored procedure or trigger in mysql server on windows.
How do I perform this solely with MySQL?
You can use a mysql-udf-http and then create a trigger like this:
delimiter $$
CREATE TRIGGER upd_check BEFORE UPDATE ON account
FOR EACH ROW
BEGIN
IF NEW.amount > 0 THEN
set #json = select json_object(account_id,amount)
select http_post('http://restservice.example.com/account/post',#json);
END IF;
END;$$
delimiter;
Basically you can't. And if you could (thru the use of a UDF library) you shouldn't.
Mysql is a high performance db engine that you ought to respect for its core competencies. Other stakeholders and waiting for your query or transaction to wrap up, and they suffer while yours doesn't. It is not a webserver with callbacks from asynchronous calls. Triggers and stored procs need to get in and get out as they are often used in a Transactional setting.
I have a stored procedure which updates a table, pretty standard insert query and the table in question has a constraint to ensure no duplicate data can go in, it error's just fine when the procedure is executed with duplicate data, however the last step of the proc executes an email stored proc. even when the insert fails the email gets sent? I thought the procedure would stop with the insert error?
Nope - it depends on the severity of the error. If the severity is less than 11 then by default SQL server will carry on.
I found this article which seems to do a decent job of explaining this: http://blog.sqlauthority.com/2012/04/26/sql-server-introduction-to-sql-error-actions-a-primer/
If I were you I'd make sure that the stored procedure is doing everything inside a transaction with a try/catch block.
EG
BEGIN TRAN
BEGIN TRY
-- Do insert
-- send email
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0 ROLLBACK TRAN
END CATCH
IF ##TRANCOUNT > 0 COMMIT TRAN
How do I do the equivalent statement in MySQL? I want it if input is a certain value, don't insert the row. In SQL SERVER, I can just say ROLLBACK. What's the equivalent command in MySQL? Thank you.
CREATE TRIGGER tr_some_trigger
ON some_table
FOR INSERT
AS
BEGIN
IF inserted.topic == 'test' THEN
ROLLBACK
ENDIF
END
From this document:
The trigger cannot use statements that explicitly or implicitly begin
or end a transaction such as START TRANSACTION, COMMIT, or ROLLBACK.
So ROLLBACK won't work inside your trigger, but if the trigger raises an exception/error, it will prevent the insertion to succeed, so what you can do is raise an exception if your condition is met (one way is to call an undefined function).
For example:
DELIMITER $$
CREATE
TRIGGER `db`.`before_insert` BEFORE INSERT
ON `db`.`dummy_table`
FOR EACH ROW BEGIN
IF new.topic = 'test' THEN
CALL func_1();
END IF;
END$$
DELIMITER ;
Assuming func_1 doesn't exist it will prevent your new record of being inserted.
It's rollback in MySQL too. Check out the documentation here.