5

我正在学习 MySQL 事务。我已经搜索过这个问题的答案,但他们似乎都使用 PHP 来完成我想做的工作。这是我正在尝试做的示例:

  1. 开始交易
  2. 更新表 1
  3. 插入表2
  4. 如果插入成功,a. 然后插入 Table3 并提交。湾。否则回滚事务。

我不明白如何以编程方式确定步骤 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;
4

4 回答 4

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并提交或回滚。但这是在应用程序级别完成的。只需检查一个错误,如果一个被引发回滚,如果没有,一切都很好。无需检查事务内部,因为如果出现任何问题/插入失败,将永远无法到达检查是否有任何失败的代码。

于 2013-04-07T08:05:23.627 回答
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不支持事务。

于 2013-04-07T04:37:15.323 回答
0

如果所有查询都在同一个事务中,那么它被认为是一个原子操作。要么全部成功,要么全部失败。
无需同时检查和使用交易。

于 2013-04-07T04:20:53.547 回答
0

如果您使用的是 java 和 JPA,您可以使用 @TransactionManagement(TransactionManagementType.CONTAINER)bean 中的注释来进行插入。这将确保如果事务失败,容器将撤消所有更改。您可以谷歌 EJB 3.0 以阅读有关事务管理的更多信息

于 2013-04-07T04:39:24.230 回答