我正在学习MySQL交易。我已经搜索了这个问题的答案,但他们似乎都使用PHP来制作我想做的工作。以下是我尝试做的例子:
我不明白如何以编程方式确定步骤3中的插入是否成功。当然,我可以查询表并查看,但我认为有一些方法可以使用返回值,但似乎只有在我使用PHP进行事务时才有效。
这是我尝试的代码块 - 它不起作用:
begin;
start transaction;
-- attempt to reduce inventory
update store_inventory set item_qty = item_qty - 2 where id = 1;
update store_inventory set item_qty = item_qty -1 where id = 5;
-- insert the order record and check whether it succeded
insert into store_orders (purchaser_name, purchase_date)
values ('test user', now());
-- if successful, do final insert and commit
if Row_Count() > 0 Then
insert into store_inventory (order_id, inventory_id, item_qty)
values (1, 1, 2),
(1, 2, 1);
commit;
else -- otherwise rollback
rollback;
end if;
end;
答案 0 :(得分:2)
答案是Itay Moav-Malimovka和Gordon的回答。
start transaction
和commit
之间的所有内容都是一个原子动作。就这样写:
start transaction;
-- attempt to reduce inventory
update store_inventory set item_qty = item_qty - 2 where id = 1;
update store_inventory set item_qty = item_qty -1 where id = 5;
-- insert the order record
insert into store_orders (purchaser_name, purchase_date)
values ('test user', now());
insert into store_inventory (order_id, inventory_id, item_qty)
values (1, 1, 2),
(1, 2, 1);
commit;
或者让我以一个更简单的例子来解释它发生了什么。
create table foo(id int primary key);
insert into foo values (1);
现在,如果你有这样的代码:
start transaction;
insert into foo values(2);
insert into foo values(1);
insert into foo values(3);
commit;
插入值1
时会引发错误,因为它违反了主键,已存在1
的条目,并且永远不会执行后面的代码。如果您现在执行select * from foo;
,您会看到表格中有2
的值。但那可能就是那些在那里看到2
的人,这取决于隔离级别(你可能想了解那些)。这是因为交易仍在等待中。现在取决于你,如果你不关心并继续插入值3
并提交或回滚。 但是这是在应用程序级别完成的。只需检查一个错误,如果有人提出回滚,如果没有,一切都很好。 无需在交易内部进行检查,因为如果出现任何问题/ 插入失败,将无法检查是否有任何失败的代码。强>
答案 1 :(得分:1)
你可能需要存储过程,但我可能错了,这是一个要求。您需要自己设置事务并进行一些测试。
DELIMITER $$
CREATE PROCEDURE `sample`(name VARCHAR(100))
BEGIN
START TRANSACTION; -- Begin a transaction
INSERT INTO `users` (`name`) VALUES name;
IF ROW_COUNT() > 0 THEN -- ROW_COUNT() returns the number of rows updated/inserted/deleted
COMMIT; -- Finalize the transaction
ELSE
ROLLBACK; -- Revert all changes made before the transaction began
END IF
END$$
DELIMITER ;
这样的事情可能有用(这是未经测试的,纯粹是从研究中拼凑而成),你必须使用 InnoDB 作为存储引擎,因为 MyISAM 不支持交易
答案 2 :(得分:0)
如果所有查询都在同一个事务中,那么它被认为是一个原子操作。 ALL 成功或 ALL 失败 无需同时检查和使用交易。
答案 3 :(得分:0)
如果您使用的是java和JPA,则可以使用注释
你用来做插入的bean中的@TransactionManagement(TransactionManagementType.CONTAINER)
。这将确保如果事务失败,容器将撤消所有更改。你可以谷歌EJB 3.0阅读有关交易管理的更多信息