数据库幻读解决方案

有时候我们会有业务场景去解决数据库幻读现象:(比如某条记录的某几个属性合起来需要在记录里唯一) 

这个时候我们需要做的是添加一个校验字段对他做唯一约束,值是这几个字段的拼接

这里为什么用校验字段而不用原字段呢? (有时候我们在做删除的时候只做逻辑删除 这时候唯一约束就好导致失效的记录让有效的记录无法插入, 而校验字段不一样 你在做失效处理的时候给校验字段赋一个随机值就好了)

一般要解决幻读的场景我们都需要(不存在插入并且返回插入值 存在直接查询结果值)

以下是代码示例

 public ComArea findAreaOrAdd(String comCode, String name, String flag, boolean throwException) {
        if (name == null || name.equals("null")) {
            logger.error("插入失败 请检查name是否位空 areaId={}", name);
            throw new BaseRuntimeException("0x00110301", "更新失败 请检查name是否位空");
        }
        ComArea comArea = new ComArea();
        comArea.setComcode(comCode);
        comArea.setComAreaId(UUID.randomUUID().toString().replace("-", ""));
        comArea.setName(name);
        String comFlag = "1" + flag.substring(1, flag.length());
        comArea.setComFlag(comFlag);
        comArea.setFlag(flag);
        comArea.setValid("Y");
        comArea.setDateCreate(new Date());
        comArea.setDateModify(new Date());
        //因为幻读会导致生成重复的code code=>comcode+name md5生成的
        String code = DigestUtils.md5DigestAsHex((comCode + name).getBytes());
        comArea.setCode((comCode + code).substring(0, 32));
        //standardcode 做了唯一约束删除的时候要给standardcode一个随机值
        comArea.setStandardCode(comArea.getCode());
        ComArea comArea1 = null;
        try {
            comArea1 = comAreaService.save(comArea) ? comArea : null;
        } catch (Exception e) {
            if (throwException) {

                throw new BaseRuntimeException("0x00110301", "插入失败 请检查名称是否重复 [" + name + "]");

            } else {
                comArea1 = comAreaService.getOne(new QueryWrapper<ComArea>().lambda().eq(ComArea::getComcode, comCode)
                                .eq(ComArea::getName, name).eq(ComArea::getValid, "Y")
                        , false);
            }
        }
        return comArea1;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
幻读是指在一个事务中,前后两次相同的查询语句返回了不同的结果行数或数据内容。幻读问题通常出现在并发环境下,当一个事务在读取数据时,另一个事务对数据进行了插入、更新或删除操作,导致前后两次读取的数据不一致。 MySQL 提供了以下几种方式来解决幻读问题: 1. 使用锁机制:通过使用共享锁(S锁)或排他锁(X锁)来保证读取数据和修改数据的互斥。可以使用 SELECT ... FOR UPDATE 语句在读取数据时加上排他锁,或者使用 SELECT ... LOCK IN SHARE MODE 语句在读取数据时加上共享锁。 2. 使用事务隔离级别:MySQL 提供了多个事务隔离级别,包括读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。将事务隔离级别设置为可重复读或串行化可以解决幻读问题,但会增加并发性能开销。 3. 使用间隙锁(Gap Locks):在可重复读或串行化隔离级别下,MySQL 可以使用间隙锁来防止幻读。间隙锁是在索引范围内的空隙中设置的锁,用于防止其他事务在该范围内插入新的数据。 4. 使用 MVCC(Multi-Version Concurrency Control):MVCC 是通过版本号或时间戳来控制事务的并发访问。在可重复读或串行化隔离级别下,MySQL 使用 MVCC 来为每个事务提供一个独立的数据快照,避免了幻读问题。 需要根据具体的业务需求和并发情况选择适合的解决方案。同时,还需要注意合理设计数据库索引、优化查询语句等措施,以提高数据库的并发性能和减少幻读的发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值