假如mysql update过程中的where条件,没有索引,会发生什么情况

154 阅读2分钟

假如有一个sql update from tableA set a=100 where b=8989,ab都没有一二级索引这个时候会发生什么情况

全表扫描

假如update的where条件没有匹配到索引,那么会触发全表扫描,去匹配符合条件的数据,这是一个很重的操作

加行锁

然后在update操作时,会给符合where条件的数据加行锁

死锁

假如update操作加锁的数据很多,那么并发条件下,可能会发生死锁,update的数据越多,并发量越大,发生死锁的概率越高

假如sessionA触发了update操作,sessionB同时也触发了update操作,A在update的过程中触发了全表扫描。而且update了大量的数据, 其中包括一条数据A,这个时候,sessionB只更新两条数据,B和A,这时候:

  • sessionA和sessionB分别给A和B数据加锁
  • 当sessionA的update操作,更新到了B数据的时候,发现有锁,sessionA会等待这行数据释放锁
  • 这时sessionB也要更新数据A,发现A数据已经加锁了,这样就需要等待A的锁释放
  • 这个时候死锁的条件就满足了sessionA在等待sessionB释放B,sessionB在等待sessionA释放A,就形成了死锁

结论

那么是不是加了索引就能解决这些问题?

也不是,假如通过索引查询出来了大量的数据,还是会出现这种情况,但是也印证了一个规则,就是为什么,大量重复的字段,不适合加索引

那么出现了这种大批量更新的情况,要如何避免死锁呢?

  • 分批更新:将大的批量更新拆分成较小的批次,以减少锁竞争。
  • 调整事务隔离级别:选择适合应用需求的隔离级别,较低的隔离级别通常会减少锁竞争,但可能会引入其他数据一致性问题。
  • 使用乐观锁:在数据行中添加版本号或时间戳字段,每次更新时检查版本信息,以避免不必要的锁竞争。
  • 重试策略:在遇到锁等待超时或死锁错误时,实现重试逻辑,可能需要随机化重试间隔以避免同步问题。