订单系统流程
1、在订单表生成订单。(status为0表示未支付,status为1表示已支付)
粘址地栏mrw.so/2LTLqB
例如:
表 bill
数据 {"id":"1","amount":"100","status":"0","time":"2017-10-23 15:00:00"}


2、点击支付,开启事务,首先查询订单
粘址地栏mrw.so/2LTLqB
例如:
begin transaction;
select * from bill where id = 1 for update;
此次使用for update锁定这条记录,并防止其他回话进入订单操作流程

3、支付后变更支付状态,并插入流水记录
粘址地栏mrw.so/2LTLqB
update bill set status = 1 where id = 1;
后续的插入操作

4、结束事务。(注意:在上面流程中有失败的情况必须进行rollback,退出事务,防止持续加锁或者数据长时间未提交,可以使用try catch)
粘址地栏mrw.so/2LTLqB
commit;
end transaction;

5、关于订单系统重复点击支付流程。
6、在1号会话进入订单支付流程时候,会进行select * from bill where id = 1 for update;锁定记录操作。

7、2号会话在此同时进入select * from bill where id = 1 for update;锁定记录,首先必须等待1号会话提交或者回滚,因为1号会话已经对此订单加持行锁。

8、1号会话完成订单的事务操作,将status从0变为1。

9、2号会话成功进行select * from bill where id = 1 for update;并查出status的状态为1,已经已经支付。

10、2号会话进行一次rollback操作,因为此订单已经完成。rollback操作将释放for update的锁定,不然整行记录会一直加持行锁,导致后续的死锁出现。
