MySQL- 事务隔离机制学习笔记

mgs2002 2020年01月22日 102次浏览

事务隔离级别

事务隔离级别:读未提交,读已提交,不可重复读,串行化
区别:
读未提交: 事务更新未提交的数据另外一个事务可以获取
读已提交: 事务对数据做的变更只有提交才会另外事务获取
不可重复读:一个事务开启事务后会生成一个视图,其他事务看到的数据跟这个事务未提交前的一致
串行化: 最高的事务级别,读数据的时候加读锁,写数据的时候加写锁,后面的事务必须等待前一个事务执行完毕,完全防止并发操作的问题

实现方式

事务隔离机制使用数据库多版本并发机制实现MVCC),不同时刻开启的事务会生成不同版本的数据快照(视图),看起来就像是同一条记录在系统里有多个版本,每次更新操作都会记录回滚日志,当事务结束后自动删除回滚日志。

事务的开启

  • 显式启动事务语句, begin 或 start transaction。配套的提交语句是 commit,回滚语句是 rollback。
  • set autocommit=0 手动提交事务模式,开启这个模式意味着在没有手动commit或者rollback的时候,事务不会提交或者回滚
  • set autocommit=1 自动提交事务模式(MySQL默认),这个模式的事务结束的时候会自动提交,除非显式(begin)的开启一个事务。
    通过如下语句可以查询数据库事务提交模式
show variables like 'autocommit';

MySQL事务提交模式.png
从结果可见MySQL默认是自动提交事务的。
如需改成手动提交通过如下语句

set autocommit = 0;

长事务的弊端

  • 长事务一般执行时间比较长,事务里面包含了很老的事务视图,由于这些事务随时可能访问数据库里面的任何数据,所以这个事务提交之前,数据库里面它可能用到的回滚记录都必须保留,会占用大量磁盘空间。
  • 占用锁资源导致数据库效率降低甚至挂掉。
    可以在 information_schema 库的 innodb_trx 这个表中查询长事务,比如下列数据查询持续时间超过60秒的长事务
select * from information_schema.innodb_trx 
where TIME_TO_SEC(timediff(now(),trx_started))>60

课后思考题

如何避免使用长事务

  • 缩短事务的执行范围,只在需要使用事务的方法开启,避免长时间占用.
  • 定期查询库里是否有长事务,监控 information_schema.Innodb_trx 表,设置长事务阈值,超过就报警 / 或者 kil。如果无法避免,保证逻辑日志空间足够用,并且支持动态日志空间增长