隔离级别
在Mysql中,有四种标准的隔离级别,分别是:
1.读未提交(read uncommitted)
2.读提交(read committed)
3.可重复读(repeatable read)
4.串行化(serializable)
读未提交是指:一个事务还未提交的时候,它做的变更可以被其他的事务看到。
读提交是指:一个事务提交之后,它做的事务才可以被其他事务看到。
可重复读是指:一个事务在执行过程中,它看到的总是和这个事务启动时的数据一致。
串行化是指:写会加写锁,读会加读锁,当出现读写锁冲突的时候,后面访问的事务必须等待前一个事务执行完成之后,才可以继续执行。
在实现上,数据库里面会创建一个视图,访问的时候以这个视图为准。在“可重复读”隔离级别下,这个视图是在事务启动时创建的,整个事务存在的期间都是用这个视图,"读提交"隔离级别下,视图是在每个SQL语句开始执行的时候创建的,"读未提交"隔离级别下没有视图这个概念,是直接返回记录上的值,"串行化"隔离级别下直接用加锁的方式来避免并行访问。
ORACLE数据的默认隔离级别是"提读交",所以如果我们要把应用从ORACLE上迁移到Mysql上,为了保证数据库的隔离级别一致,一定得把Mysql的隔离级别设置成"读提交"。
我们可以通过 show variables like '%transaction_isolation%'来查看当前的隔离级别。
事务隔离的实现:
在Mysql中,每条记录在更新的时候都会同时记录回滚操作。记录上的最新的值,都可以通过回滚操作,得到前一个状态的值,这里详细展开"可重复读隔离级别"。
当前值是4,视图1、2、3分别记录的值是1、2、3,也就是说同一条记录在系统中可以存在多个版本,这就是数据库的多版本并发控制(MVCC),对于视图2,要得到2这个值,就得依次执行图中的回滚操作。
还有,回滚日志不会一直保留,系统会判断,当没有事务再需要用到这些回滚日志时,回滚日志就会被删除,即系统里没有比这个回滚日志更早的视图时。
这边建议你尽量不要使用长事务,长事务意味着系统里面会存在很老的事务视图,因为这些事务可能随时会访问数据库里的任何数据,所以数据库会保留可能用到的回滚记录,这样会导致占用大量的空间去保留这些回滚日志,所以尽量不要使用长事务。
可以在information_schema库的innodb_trx这个表中去查询长事务,如:
查询持续时间超过30s的事务
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started)) >60;
事务的启动方式:
启动事务的语句:begin或者start transaction,提交语句是commit,回滚语句是rollback。
set autocommit=0,这个命令是指你不需要去用begin或者start transaction去启动事务,当你执行一条sql语句的时候,事务就启动了,但是还是需要你去主动执行commit或者rollback