mysql里面事务是通过存储引擎层面来支持的,所以innodb支持,myisam不支持。
事务的隔离主要是为了解决,多事务并发时候
可能出现的脏读,不可重复读和幻读等问题。
事务的隔离如果太严,那么效率就越低,所以需要按照业务需求寻找一个平衡点。
sql标准的事务隔离级别包括:
读未提交,读提交,可重复度以及串行化。
读未提交指的是,一个事务还没有提交的时候,他做出来的更改就可以被其他事务看到。
读提交指的是,一个事务提交之后,他的变更才被其他事务看到。
可重复读指的是,一股事务执行中看到的数据,和这个事务启动时候看到的数据是一致的。在可重复读隔离级别下,未提交的变更对其他事务也是不可见的。mysql默认的就是可重复读。
串行化指的是,对于同一行的记录,写和读会加锁,后访问的必须等前面的事务执行结束后才可以继续。
可以通过语句 show variables like 'tx_isolation';查看此时mysql的事务隔离级别:
实现上,可重复读事务启动的时候数据库会创建一个view,整个事务过程中都使用这个视图。读提交的view是每个sql语句执行的时候创建的。读未提交直接返回记录的最新值。串行化直接使用加锁的方法来避免并发。
这边再以更细节实现上讲下mysql默认的可重复读这个事务隔离级别。在mysql里面,每次update都会记录一下,并生成回滚操作记录。所以,通过回滚,可以获取前一个状态的值。这种同一条记录在mysql中有多个版本,就称为数据库的多版本并发控制(MVCC)。
这也是为什么尽量不要使用长事务的原因,长事务就会导致数据库中保留着很长的回滚记录,影响计算性能和空间占用,比如锁资源的占用。
事务的启动可以通过begin 和start transaction。通过commit进行事务提交,通过rollback进行事务回滚。这是事务的显示启动。
另外也可以通过set autocommit=0语句,默认让所有sql语句默认就开启事务,而且必须等到commit和rollback才结束任务。但是这样容易导致事务过长,占用系统资源过大,最后甚至拖垮mysql,所以一般建议 set autocommit=1,显示的启动事务。
所以很多时候mysql性能突然变得很慢,可能就是有过多的长事务在占用cpu,存储和锁资源。那么在mysql5.5以上版本可以通过下面这个语句来查询哪些过长的事务。
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>[多少秒]