InnoDB中的死锁因为不同的事务持有对方需要的锁 , 导致这些事务不能执行下去 。 由于每个事务都在等待资源变成可用 , 都不会释放它持有的锁 。
可能出现的场景:多个事务以不同的顺序锁定多个表中的行(通过类似这样的语句:UPDATE或SELECT … FOR UPDATE) , 锁定范围索引记录和间隙 , 每个事务因为时间的原因只获取一部分锁 。
为了减少死锁的可能 ,
- 使用事务而不是LOCK TABLES语句;
- 保持insert或update的事务足够小 , 让他们不会长时间打开;
- 当不同的事务更新多个表或者大范围的行 , 在每个事务里使用相同顺序的操作(例如SELECT … FOR UPDATE);
- 在SELECT … FOR UPDATE和UPDATE … WHERE 语句中使用到的列上创建好索引
- 如果使用锁定读(SELECT … FOR UPDATE或者SELECT … FOR SHARE) , 尝试使用例如READ COMMITTED这样的低隔离级别
- 添加选择度高的索引到表中 , 这样查询只需要扫描更少的索引记录 , 相应的也就设置更少的锁 。 使用EXPLAIN SELECT来查看
InnoDB多版本控制 MVCCInnoDB是一个多版本的存储引擎 。 它持有被更改过的行的旧版本信息 , 以支持例如并发和回滚这样的事务特性 。 这个信息存储在undo表空间里面一个叫rollback segment的数据结构中 。 InnoDB使用回滚段里的信息来执行事务回滚里面的undo操作 。 它还使用这信息来构建更早版本的行用于实现一致性读 。
InnoDB内部在数据库里存储的每个行里添加了三个字段:
- 6-byte DB_TRX_ID , 表示最近一个插入或更新行的事务的事务标识符 。 删除在内部也是被视为更新 , 行里面一个特定的bit会设置以标识它为已删除
- 7-byte DB_ROLL_PTR , 滚动指针 。 它指向回滚段里的一条undo日志记录 。 如果行被更新了 , 这条undo日志记录会包含更新前重建行所需要的必要信息
- 6-byte DB_ROW_ID , 包含了随着新行插入而单调递增的行ID 。 如果InnoDB自动生成了一个聚簇索引 , 索引会包含行ID的值 。 否则DB_ROW_ID列不会出现在任何索引里
建议定期提交事务 , 包括仅发出一致性读的事务 。 否则InnoDB不能从更新的undo日志里丢弃数据 , 这样回滚段可能会增长得太大 , 充满它驻留的整个undo表空间 。
回滚段里的undo日志记录的物理大小通常比相应的插入或更新行更小 。 可以使用这个信息来记录回滚段需要的空间 。
在InnoDB多版本控制方案中 , 当使用SQL语句删除的时候 , 该行并不会立即从数据库中物理删除 。 InnoDB仅在丢弃为删除而写入的更新undo日志的时候 , 才会物理删除相应的行和索引记录 。
多版本和二级索引InnoDB 多版本并发控制(MVCC)对待二级索引不同于聚簇索引 。 聚簇索引中的记录会就地更新 , 其隐藏的系统列指向undo日志项 , 从中可以重构早期版本的记录 。 二级索引不包含隐藏的系统列 , 也不进行就地更新 。
更新二级索引列时 , 旧的二级索引被删除标记 , 新记录被插入 , 删除标记的记录最终被清除 。 当二级索引记录被删除标记 , 或者二级索引页被更新的一个事务更新时 , InnoDB会在聚簇索引中查找数据库记录 。 在聚簇索引中 , 检查记录的DB_TRX_ID , 如果在读取事务启动后修改了记录 , 则从undo日志里检索出记录的正确版本 。
- 微信|遇到不认识的字,用微信1秒就能读出来,操作简单,比字典还方便
- 诈骗|女子遇诈骗反赚骗子1千多 认识炒股专家被坑惨:官方提醒不要想暴富
- 黑科技与建筑的无缝结合,带你回溯千年历史
- 微信|带你了解微信新版本的几个实用功能
- 对于知网论文查重系统带你们来深刻探索一下!
- 本文转自:新华网第十届中国(绵阳)科技城国际科技博览会于11月16日至19日在四川绵阳举...|记者带你体验科博会上的“新”“奇”“特”
- 欧盟|苹果手中的“灰色”出货神器,带你了解卡贴机黑解背后的底层逻辑
- 华硕|11月17日登场!一文带你提前看完我10系列亮点,屏幕太绝
- “智慧水电”应用上线啦!一篇文章带你一探究竟…
- 显示器|无愧经典,从不落伍的CD机带你重拾听音的纯粹