MySQL中有4个事务隔离级别:读未提交,读已提交,可重复读和串行化。 事务的四大特性ACID(Atomicity原子性、Consistency一致性、Isolation隔离性、Durability持久性。 隔离级别的设定为数据库服务器的并发,可靠性和性能之间提供了选择。隔离级别越高,性能越低,ACID的完成度越高。 而不同的级别设定,一般带来如下图所列的问题:
MVCC
Mysql mvcc行更新过程: https://yq.aliyun.com/articles/283418?spm=a2c4e.11153940.0.0.4b3224eb4hoiqb。 重点: 每个事务做update的时候,copy原始数据到undo log中,然后会修改DB_TRX_ID为当前事务ID,及修改数据本身,如果存在更老版本的数据会更新回滚指针DB_ROLL_PTR。 MVCC只解决了阻塞读的问题,事务以排他锁的形式修改原始数据。
Innodb的实现真算不上MVCC ,因为并没有实现核心的多版本共存,undo log中的内容只是串行化的结果,记录了多个事务的过程,不属于多版本共存。但理想的MVCC是难以实现的,当事务仅修改一行记录使用理想的MVCC模式是没有问题的,可以通过比较版本号进行回滚;但当事务影响到多行数据时,理想的MVCC据无能为力了。 多行数据修改时, 会遇到2pc相同的问题。多行数据的情况下, 会遇到部分失败下,无法完美回滚。
Read View
read view其实就是一个保存事务ID的list列表。记录的是本事务执行时,MySQL还有哪些事务在执行。readview是记录的当前活跃的事务列表。 因为undo log链表中,存在过时的事务log, 需要等待purge线程定期清理。 而readview可以快速响应用户的read request,副本中保存的是系统当前不应该被本事务看到的其他事务id列表。当用户在这个事务中要读取该行记录的时候,innodb就会从根据 read view,来决定是读取该行记录的当前版本,还是需要从undo-log中去寻找更早的版本。 大致过程是: 根据readview中up_id 和low_id判断,如cur_id>up_id,可以读取, cur_id (之前网上摘抄部分博客, 没记录原文地址. 原作者看到有问题联系我)
在undo log中记录的老版本的数据。 但一个长事务,需要读取老版本的数据时,需要顺着undo log链表找到老版本的数据。(查找条件是什么?DB_ROLL_PTR指针进入到undo log 的链表中) undo log存储在ibdata表空间中,或者独立的undo tablespace中。 定义:运行时间比较长,操作的数据比较多的事务
2.大事务风险:
a)锁定太多的数据,造成大量的阻塞和锁超时,回滚所需要的时间比较长。
b)执行时间长,容易造成主从延迟
3.如何处理大事务
a)避免一次处理太多大数据
b)移出不必要在事务中的select操作
回滚段
大事务带来的影响