InnoDB是MySQL默认的事务型存储引擎,它通过redo log和undo log实现了事务的提交和回滚操作,redo log为事务提供了持久性和原子性的保证,undo log提供了隔离性和一致性的实现。
事务的四个特性ACID,atomicity,consistency,isolation,durability;
原子性,原子操作,同时成功同时失败;
一致性,事务开始和结束后,数据库的完整性不会被破坏 ;
隔离性,事务之间互不影响,四种隔离级别 RU(读未提交)、RC(读已提交)、RR(可重复读)、SERIALIZABLE (串行化);
持久性,事务提交后,对数据的修改是永久性的,即使系统故障也不会丢失 。
为什么要引入隔离级别事务并发执行会触发读取问题,
脏读,当读取数据时读取到了其他事务为提交的数据,而最终事务进行了回滚,那么当前程序所读取到的数据就是脏数据,并导致程序出现错乱;
幻读,就是在某个事务的读取范围之内,另一个事务也在相同的范围内插入了数据,导致当前事务再次查询时出现了幻行;
不可重复读,当事务的执行过程中,另一个事务完成了提交,导致当前事务在读取同一个变量的时候产生了不同的结果。
隔离级别和多版本并发控制 什么是隔离级别InnoDB具有四种隔离级别,隔离级别针对于事务;
read uncommitted,读未提交,/事务未提交的数据可以被其他事务读取到;
read committed,读已提交,事务可以读取到其他事务提交的数据;
repeatable read,可重复读,事务可以重复读取数据,不会受到其他事务修改的影响;
serializable,串行化,事务在读取或写数据时会添加锁,后访问的事务必须等待当前事务释放锁后才能进行读取。
MySQL可以通过 transaction_isolation设置不同的隔离级别,其中可重复读是InnoDB的默认的隔离级别。
如何实现的隔离级别MySQL每次数据库操作都会生成一条回滚记录,也就是undo log日志,对于同一个数据,在undo log中会存在不同的版本数据(read-view),这就是多版本并发控制;
多版本并发控制MVCC将数据的读取操作分为快照读和当前读,快照读为设置指针指向某个undo log版本,后续的数据更改对当前事务不可见;当前读就是读取最新数据,由此实现了事务间数据的隔离性。
回滚日志的删除回滚日志提供了事务的可回滚性和隔离性,但是回滚日志也不会一直存在,当系统判断回滚日志没有事务需要用到的时就会进行删除。也就是说系统会保存最早事务所需的版本数据,也就是回滚日志。
长事务长事务会导致系统中存在很老的事务视图,导致该事务之后的回滚日志都要保存,导致占用大量的内存;此外长事务会占用锁资源,如果该事务一直不提交,会导致其他需要请求锁资源的程序无法获取锁导致死锁;
所以尽量不使用长事务;
如果操作事务1. 显示的启动事务语句,通过begin或start transaction;然后通过显示的commit进行提交,或通过rollback对事务进行回滚操作;
2. 设置 set autocommit=0,将该线程的自动提交关闭,这样只要执行SQL语句,就会开启事务,且不进行提交,必须手动commit或rollback或者断开连接,才会进行事务提交或回滚;
3. 如果不想开启长事务,可以通过commit work and chain设置提交并开启新事务;
总结MySQL的事务主要是通过InnoDB实现的,并实现了不同的事务隔离机制。
link:03 | 事务隔离:为什么你改了我还看不见? (geekbang.org)
link:InnoDB事务及索引原理 - 知乎 (zhihu.com)



