美文网首页
2019-12-04 关于事务与锁的一次尝试

2019-12-04 关于事务与锁的一次尝试

作者: 江江江123 | 来源:发表于2019-12-04 10:27 被阅读0次

    事务:原子性,一致性,隔离性,持久性
    锁:多线程下,资源不会共享

            Transaction transaction = database.beginTransaction();
            checkName(request.name);
            database.execute("UPDATE categories SET has_children = ? WHERE id = ?", Boolean.TRUE, category.parentId);
            category.id = categoryRepository.insert(category).getAsLong();
            transaction.commit();
    

    上面这个事务保证我们在插入一个分类的同时,保证他父类的has_children为true,并在插入之前验证了name不重复

    但是在调试时,我尝试添加断点,postman发送请求的结果为服务器未响应,所以会重复发请求尝试

    结果就是我在同一个分类下创建了多个名字相同的类型;

    根据以上结论,我可以得出如果在并发环境下,有2个人同时是创建同名分类,我的校验是失效的

    解决方法:1.对该表的name添加唯一索引,这样第二个同名插入自然报错
    2.使用synchronized包含该方法

    进一步的思考:
    1.很多时候为了支持并发量,我们会将该工程多节点启动,通过负载均衡来访问,这样mysql上添加索引依然生效,但是添加synchronized则因为只能锁住当前工程中的线程而失效,可以通过redis实现锁来解决这个问题

    2.如何解决分布式下多个接口调用的事务

    目前最简单,有效的方法,通过记录日志,手动处理。。

    不过也可以考虑下复杂的方法。
    2.1什么时候发生?
    同时调用api1,api2,api3,如果1执行成功2执行不成功,但是1已经无法回滚
    2.2如果希望1回滚,需要什么
    2.2.1 1成功后返回一个取反的接口及参数,如果2,3失败则调用回滚接口
    2.2.1.1 存在问题:一定要保证回滚接口的正确,但是回滚这个事件要保证锁,不然可能导致回滚操作将另一个线程已提交的事务修改。
    那岂不是在调用1时加锁,一直要等到确定用户不回滚再解锁,所以该方案否决!当然在一些简单的新增,删除业务上还是能用用的。

    2.2.2 创建一个中间表,1,2,3执行前先创建一个待确认的数据,如果返回结果正确,将待确认改为正确,如果返回失败则继续向下执行。
    之后在创建一个job重复执行待确认的数据,当操作成功时修改待确认的数据

    相关文章

      网友评论

          本文标题:2019-12-04 关于事务与锁的一次尝试

          本文链接:https://www.haomeiwen.com/subject/syekgctx.html