事务隔离:
mysql是支持多引擎的系统,这个在我们设计数据库原型的时候经常碰到,一张表是使用InnoDB还是MyISAM引擎,可以根据自己的需要选择。值得一提的是,MyISAM作为mysql的原生自带引擎,不支持事务,所以一般我们设计mysql表的时候,选用InnoDB作为数据库引擎,就是为了支持事务。
先理解下事务的概念,名词听说过很多次,每当说起事务,ACID必然第一时间出现在脑海里:
A:atomicity,原子性
C:consistence,一致性
I:isolation,隔离性
D:druability,持久性
当数据库有多个事务在进行时,可能出现脏读,幻读,不可重复读:描述查看链接
那么为了解决这些问题,我们有了事务隔离的概念。
事务隔离的实现:
数据库更新的时候,同时会记录一条回滚的操作---->回滚记录的值,可以通过回滚操作,回到更新之前的值。
假设数据亏一个值被修改成从1到2,3,4,记录如下
采用可重复度的隔离状态,当前值是4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的read-view。如上图的review-view ABC,对于review-view A,要的到1,必须按照图中的顺序执行所有回滚得到。
同时会有,即使现在还有事务正在将4修改成为5,这个事务跟A,B,C都不会冲突。
回滚日志由系统判断,在不需要的时候删除。
基于上面的说明,这里说一下为什么不建议使用长事务。
长事务到导致系统存在比较老的事务视图,这些事务随时可能访问数据库里面的任何数据,所以这个事务提交之前,数据库里面这个事务可能用到的所有回滚记录都继续保留,这回导致占用大量的存储空间。
在mysql5.5之前的版本,回滚记录日志跟数据字典放在ibdata里面,即使长事务最终提交,回滚段被清理,文件也不会变小,作者实际经验有见过数据有20G,但是回滚日志有200G的情况,为了清理回滚段,只好重建数据库。
除了回滚段的影响,长事务还占用锁资源,也可能拖垮整个库。
事务启动的方式:
很多情况下我们并没有主动去使用长事务,误用导致出现长事务的情况有很多。
mysql的事务启动方式有如下几种:
1.显式事务启动语句,begin或者start transaction,配套提交语句是commit,回滚语句是rollback。
2.set autocommit=0,这个命令会将这个线程的自动提交关掉,就是说,如果你一个查询语句使用了这个命令,事务启动了,但是不会自动提交,事务会存在直到你主动使用commit或者rollback,或者断开连接。
有些客户端框架会默认连接成功之后先执行一个set autocommit=0的命令,这会导致在接下俩的查询都在事务中,如果是长连接,就弄出了长事务。
因此这里建议总是显式使用set autocommit=1来启动事务。
ps:在mysql自带表information_schema中,可以通过sql查询长事务:
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60
文章评论