,第一反应是用户在绑定手机号过程中,多次点击绑定按钮,导致绑定接口被调用多次,造成多线程并发调用用户注册接口,进而生成多个账号。 ,首先代码被 @Transactional 注解包含,就是在自动事务中执行注册逻辑 现在博主带大家回忆一下,MySQL 事务的隔离级别有4个 • Read uncommitted:读取未提交,其他事务只要修改了数据 下面结合上述代码给出分析过程:上述注册逻辑都包含在 Spring 提供的自动事务中,整个方法都在事务中。 而加锁也在事务中执行。最终导致我们注册 线程B 在当前事物中查询不到另一个注册 线程A 所在事物未提交的数据, 举个例子 eg: 1. 三 解决方案: 给出三种解决方案 3.1 修改事务范围,将事务的操作代码最小化,保证在加锁结束前完成事务提交,代码如下开启手动事务,这样其他线程在加锁代码块中就能看到最新数据 @Autowired private
,多次点击绑定按钮,导致绑定接口被调用多次,造成多线程并发调用用户注册接口,进而生成多个账号。 ,首先代码被 @Transactional 注解包含,就是在自动事务中执行注册逻辑现在博主带大家回忆一下,MySQL 事务的隔离级别有4个Read uncommitted:读取未提交,其他事务只要修改了数据 :上述注册逻辑都包含在 Spring 提供的自动事务中,整个方法都在事务中。 而加锁也在事务中执行。 三 解决方案:给出三种解决方案3.1 修改事务范围,将事务的操作代码最小化,保证在加锁结束前完成事务提交,代码如下开启手动事务,这样其他线程在加锁代码块中就能看到最新数据@Autowiredprivate
为了确保这个流程是原子的,或者“全部成功或全部失败”,我们将循环包装在了一个数据库事务中。 很简单,对吧?从这里开始就是一堆麻烦事了。 Bug 这个批量流程也正常用了一段时间。 那么是什么引发了这个问题呢?当所有付款仍标记为待处理时,为什么系统就把通知发出去了?我们仔细查看批量流程的实现,终于发现了问题。 嵌套事务 将付款标记为已到账的那个函数是在数据库事务内执行的。 注意代码中,即便第三笔付款失败导致外部事务回滚所有三笔付款,前两笔付款的成功通知还是会发送出去。 这种方法的主要缺点是,除非另有明确说明,否则测试将在一个数据库事务中运行。这将导致使用事务的测试全部失败。 由这个嵌套事务引起的“bug”最后导致一些用户收到了多条付款到账消息,不过所有这些用户最后都拿到了钱。
问题描述 有一天,测试妹子W向我提了一个BUG,问题描述如下,当操作动作D时,动作D可以看作更新,更新我当前选择的那一条数据,妹子W看到操作D成功页面中多出一条一样的数据,期望的结果是只会更新当前选择行的数据 最后,只能把这个BUG先放一边,忙着修复其它Bug。 当我把所有的事情都忙完了,我又重新看了动作D的逻辑,看到插入的逻辑,这个插入数据的逻辑我是直接调用同事写好的方法,我看到产生BUG的原因,因为插入的数据有可能有许多,那段的逻辑使用了多线程插入数据。 多线程影响事务回滚,事务没办法回滚多线程的数据。 解决步骤 发现问题后,当然要解决问题,多线程影响事务回滚,那我就用最笨的方法,重新写一段插入数据的逻辑,解决这个事务问题。 这个坏习惯影响着我,以后的工作中应该避免这类事情的出现。还有一个问题,就是使用别人的代码一定要看中间的逻辑,别人使用没有问题,并不代表你使用那部分代码也没有问题,所以工作中要仔细。
问题描述 有一天,测试妹子W向我提了一个BUG,问题描述如下,当操作动作D时,动作D可以看作更新,更新我当前选择的那一条数据,妹子W看到操作D成功页面中多出一条一样的数据,期望的结果是只会更新当前选择行的数据 最后,只能把这个BUG先放一边,忙着修复其它Bug。 当我把所有的事情都忙完了,我又重新看了动作D的逻辑,看到插入的逻辑,这个插入数据的逻辑我是直接调用同事写好的方法,我看到产生BUG的原因,因为插入的数据有可能有许多,那段的逻辑使用了多线程插入数据。 多线程影响事务回滚,事务没办法回滚多线程的数据。 解决步骤 发现问题后,当然要解决问题,多线程影响事务回滚,那我就用最笨的方法,重新写一段插入数据的逻辑,解决这个事务问题。 这个坏习惯影响着我,以后的工作中应该避免这类事情的出现。还有一个问题,就是使用别人的代码一定要看中间的逻辑,别人使用没有问题,并不代表你使用那部分代码也没有问题,所以工作中要仔细。
事务注解不生效的问题 出现该问题的主要原因主要有两点: Spring的事务没有生效 出现异常时无法正常回滚 Spring事务不生效的情况 @Transactional用在非public方法上 未通过代理手段调用事务方法 正常注入Spring中,在调用方法时使用This调用事务方法,Spring不会注入this,所以无法使用事务。 未正确处理异常,事务生效也不一定能回滚 多次数据库操作,未配置事务传播 事务生效不能回滚的情况: try/catch包裹标记了@Transactional注解的方法,方法满足一定条件时才会回滚。 ③:catch的作用就是捕捉方法中的异常,使回滚不传播到外层事务,以免对其他事务产生影响。 : 用户注册时在主表中新增数据,同时需要在子表中关联主表数据,现在业务要求,子表执行错误时回滚,子表不影响主表事务,也就是子表不能影响主流程,需要主表和子表不在同一个事务中。
我们曾经在初级和中级培训中给大家详细讲解了Modbus通讯的开发,并多次强调了一定要按照标准协议的要求编写Modbus驱动程序,可是现实中仍然有很多工程师不按照标准,导致通讯中会出现bug,最近也有猿友微我说他的 小猿曾经在嵌入式培训中多次强调告诫大家Modbus通讯中帧完成检测,也就是我们常说的t3.5个字节的帧中断完成检测,和t1.5的字节间检测。 在标准协议中明确要求,我们在来温习一下,希望大家牢记这段,因为这是Modbus驱动中最重要的部分。 ? ? ? 如果按照相同的值来检测,那么通信就会出现bug。另一个常见的bug是因为没有做t1.5检测引入的,如上图所示,如果不做t1.5检测,那么不正常的帧2就会被认为是正常,引入通信bug。 希望这两个地方引起大家的重视。 其实在标准协议中已经给出了程序的状态图,可以按照下面的图示开发你的程序就不会带来bug。 ?
解Bug之路-NAT引发的性能瓶颈 笔者最近解决了一个非常曲折的问题,从抓包开始一路排查到不同内核版本间的细微差异,最后才完美解释了所有的现象。 具体见笔者之前的博客: https://my.oschina.net/alchemystar/blog/3119992 Bug现场 好了,介绍完环境,我们就可以正式描述Bug现场了。 四次挥手里面的Seq和Ack对应的值和三次回收中那个错误的ACK完全一致! 如何解释LVS的监控曲线? 等等,564TPS?这个和LVS陡然下跌的TPS基本相同!难道在端口号复用之后LVS就不会新建连接(其实是LVS中的session表项)?从而导致统计参数并不增加? 在问题解决过程中,从LVS源码看到Linux 2.6内核对TIME_WAIT状态的处理,再到3.10内核和3.10.1127内核之间的细微区别。 为了解释所有的疑点,笔者始终在找寻着各种蛛丝马迹。
当对数据修改时,如果两个线程同时去修改同一条数据,这样产生的结果就不是我们预期的结果。这时候就需要对修改操作进行加锁,让jvm里同一时刻只能有一个线程能够执行修改方法。 下面是一个未加锁的修改方法: public void update(Entry entry){ dao.update(entry); } 现在讨论下传统的加锁方法。 与采用默认设置(使用不公平锁)相比,使用公平锁的程序在许多线程访问时表现为很低的总体吞吐量(即速度很慢,常常极其慢),但是在获得锁和保证锁分配的均衡性时差异较小。 不过要注意的是,公平锁不能保证线程调度的公平性。因此,使用公平锁的众多线程中的一员可能获得多倍的成功机会,这种情况发生在其他活动线程没有被处理并且目前并未持有锁时。 对比synchronized这个锁是独立的,在一个类中多个同步块之间都是独立的,互不影响。
发现猫腻(yarn.lock) 当我一筹莫展发呆时,突然发现目录树中的yarn.lock变色了,看来是有改动了,我寻思着不可能啊,我没动package.json中的依赖项啊,怎么会发生变化呢? ,修改了package.json中的build命令。 我们来验证下吧,将dependencies中的那两个包放到peerDependencies中,重新install下,再build看下。 不出意料,果然报错了。 dependencies dependencies是package.json中的一个属性,里面放运行代码时所需的依赖,在install时这些包会被安装,打包项目时,这里面的包也会被打包进去。 既然dependencies中的依赖包只要和调用者的版本号一致,就不需要重新安装依赖,那我们把它的版本号放开,给个范围,这样不就可以了 在package.json中的版本号可以带下述符号: ~波浪号,匹配最新补丁版本号
,它包含了一个字符串类型的 name 与列表类型的 sons 属性; 在使用时首先创建了该类的一个实例 m1 并往 sons 中写入一个列表数据;紧接着又创建了一个实例 m2 ,也往 sons 中写入了另一个列表数据 如果只放在类中,和 Java 中的 static 静态变量效果类似;这些数据由类共享,也就能解释为什么会出现第一种情况,因为其中的 sons 是由 Mom 类共享,所以每次都会累加。 的字典(也就是 Java 中的 map)可以做到在整个类中共享,无论创建多少个实例。 虽说能满足并发要求了,但其实这样的实现也不够优雅;仔细想想这里 mySQLDriver = &MySQLDriver{} 创建实例只会调用一次,但后续的每次调用都需要加锁从而带来了不必要的开销。 查看源码会发现 once.Do() 也是通过锁来实现,只是在加锁之前利用底层的原子操作做了一次校验,从而避免每次都要加锁,性能会更好。
这个地方之前是有bug的: 第一次是有线程安全问题 第二次是事务与分布式锁重叠的问题 会出现事务没提交,但分布式锁已经释放,前端连续发起多次取消时,会引发幂等问题。 要等aio10执行完成【提交事务】并释放锁后,才可以 用来互斥的分布式锁呢? 正在没有头绪之际,突然想起来,之前在本地测试时,同一次操作中,有3条日志,现在怎么才两条: 构建好互斥信号量时【redis key】,打印日志 lock Key is: ${key} 加锁成功时【在redis redis中的key进行续期。 ),可过期性信号量(PermitExpirableSemaphore)和闭锁(CountDownLatch)这些实际当中对多线程高并发应用至关重要的基本部件。
最近在做基于模型的设计,在matlab的sateflow工具箱和simulink下实现基于模型的设计,在设计模型,并生成代码的时候,因为stateflow不支持类似下面的表达式 ? j1939tp_txbuf[index].num_cur>=j1939tp_txbuf[index].num_packes) j1939tp_txbuf[index].num_cur++; 由于大意在模型中采用了第一种方式 ,结果在收发多帧的时候每次只能收到第一帧数据,引入了bug,随分析模型,并调整模型修改为第二种模式 ? 可以看到生成的代码符合预期,bug也消除,整个收发都正常, ? 因为stateflow和C语言在有的语法上不兼容,所以在设计的时候要仔细设计符合自己预期的模型。 另外建议大家都学学基于模型的设计,现在很流行的开发方法。
本文原创来自我部门框架组核心开发李文龙 先看下发现这个bug的一个背景,但背景中的问题,并非这个bug导致: 最近业务部门的一位开发同事找过来说,自己在使用公司的框架向数据库新增数据时,新增的数据被莫名其妙的回滚了 公司的框架是基于SpringBoot+Mybatis整合实现,按道理这么多项目已经在使用了, 如果是bug那么早就应该出现问题。 我的第一想法是不是他的业务逻辑有啥异常导致事务回滚了,但是也并没有出现什么明显的异常,并且新增的数据在数据库中是可以看到的。于是猜测有定时任务在删数据。询问了这位同事,得到的答案却是否定的。 现在我们回到标题重点没有考虑Interceptor线程安全,导致断点调试时才会出现的bug晚上下班后,突然想到调试中遇到的org.apache.ibatis.executor.ExecutorException 这看似mybatis-spring在实现SqlSessionInterceptor 时考虑不周全导致的一个bug,为了不泄露公司的框架代码还原这个bug,于是单独搭建了SpringBoot+Mybatis
多个事务同时并发更新一行数据时, 就有脏写问题。脏写绝对不允许,可依靠锁机制让多个事务更新一行数据的时候串行化,避免同时更新一行数据。 有个事务要来更新一行数据,他会先看这行数据有没有人加锁? 看到没人加锁,该事务就会创建一个锁,包含自己的trx_id和等待状态,然后把锁跟这行数据关联在一起。 更新一行数据,必须将其所在数据页从磁盘文件读到缓存页才能更新,所以此时这行数据和关联的锁的数据结构,都在内存。 因为事务A给那行数据加了锁,所以此时该数据被加锁。就不能再让别人访问了! 此时事务B也想更新那行数据,就检查当前这行数据是否被别人加锁,然后发现事务A抢先给这行数据加锁了,这可咋办? 锁一旦释放,他就会去找,此时还有无别人对这行数据也加锁了呢?他发现事务B也加锁了。于是,就会把事务B的锁里的等待状态修改为false,然后唤醒事务B继续执行,此时事务B就获取到锁了:
具体见笔者之前的博客: https://my.oschina.net/alchemystar/blog/3119992 Bug现场 好了,介绍完环境,我们就可以正式描述Bug现场了。 四次挥手里面的Seq和Ack对应的值和三次回收中那个错误的ACK完全一致! 这个和LVS陡然下跌的TPS基本相同!难道在端口号复用之后LVS就不会新建连接(其实是LVS中的session表项)?从而导致统计参数并不增加? container_of(work, struct inet_timewait_death_row, twkill_work); bool rearm_timer = false; int i; BUILD_BUG_ON 在问题解决过程中,从LVS源码看到Linux 2.6内核对TIME_WAIT状态的处理,再到3.10内核和3.10.1127内核之间的细微区别。 为了解释所有的疑点,笔者始终在找寻着各种蛛丝马迹。
1 背景 项目中使用到了UILable来展示相关的文本内容,但内容的大小不确定,有可能会超过屏幕的大小,因此需要在外层嵌套一个UIScrollView来保证内容可以被完全展现给用户,在UILabel确定相关的高度后 3 问题的分析 在发现实现的效果没有达到想要的效果后,就开始进入问题的分析排查阶段。 因此就排除了初始y值设置不对引起的距离过大的猜测。 3.2 排查方向二 在发现不是初始y值的影响后,就猜测大概率是父View的影响,仔细查看了父View的设置代码后,发现其并没有设置顶部Top的距离,一行行代码排查后,怀疑是ContentSize的设置引起的 contentSize时,系统会自动帮你调整子View的偏移量,这其实也解释了在排查方向二时出现的现象:调整了contenSize时,整体的偏移量会多出很多的问题。
具体见笔者之前的博客: https://www.cnblogs.com/alchemystar/p/13444964.html Bug现场 好了,介绍完环境,我们就可以正式描述Bug现场了。 四次挥手里面的Seq和Ack对应的值和三次回收中那个错误的ACK完全一致! 这个和LVS陡然下跌的TPS基本相同!难道在端口号复用之后LVS就不会新建连接(其实是LVS中的session表项)?从而导致统计参数并不增加? container_of(work, struct inet_timewait_death_row, twkill_work); bool rearm_timer = false; int i; BUILD_BUG_ON 在问题解决过程中,从LVS源码看到Linux 2.6内核对TIME_WAIT状态的处理,再到3.10内核和3.10.1127内核之间的细微区别。 为了解释所有的疑点,笔者始终在找寻着各种蛛丝马迹。
但是,SwiftUI 中的一些系统控件并没有完全遵循响应式的设计原则,由此在某些情况下会出现严重的错误,影响用户体验,并使开发者无所适从。 本文将解析 SwiftUI 中两个由于未能贯彻响应式编程原则而导致的严重错误,并提供相应的解决方案。 它的复现条件如下: iOS 16 系统,在真机或模拟器上测试 点击视图列表中的按钮,可以进入下一级视图。 在我们遇到问题的两个场景中,应用程序都恰好使用了导航容器,并且通过特定的操作,使 RunLoop 处于了适合 AG 打包更新的状态。 随着版本的提高,SwiftUI 的功能也确实得到了相当程度的增加。不过,即使在最新的版本中,在一些对 UIKit(AppKit)进行二次包装的控件中,仍有不少细节处理不到位的问题。
作者通过精心挑选并分析具体项目案例,将复杂的框架设计原理和实践技巧娓娓道来,使得读者能够更加直观地理解微服务架构的精髓。引言随着多线程和并发处理需求的增加,线程池成为了提升系统性能的重要工具。 任务队列:存放待执行任务的队列,当核心线程数已满且还有任务到来时,任务将被放入队列中。饱和策略:当线程池和任务队列均已满时,如何处理新提交的任务。。 日志中的错误信息如下:java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@17ebe8b3 小明的故事是一个关于成长和学习的过程。从最初的无知到最终的成熟,他不仅仅是修复了一个 BUG,而是提升了自己作为开发者的能力。结尾在技术的道路上,我们都可能遇到挑战和困难。 正如小明所经历的,通过不断的学习、反思和改进,我们能够克服这些困难,成为更优秀的开发者。希望每位读者都能在自己的旅程中,像小明一样,迎接挑战,收获成长。