什么是事务?
事务就是保证一组数据库操作要么全部成功,要么全部失败。MySQL中,事务的支持是在引擎层实现的。InnoDB支持事务,MyISAM不支持事务,这也是InnoDB逐渐取代MyISAM的原因之一。
事务有哪些特性?
为什么需要隔离级别?
数据库有多个事务在同时执行的时候,可能会出现脏读、不可重复读、幻读等问题,为了解决这些问题,便出现了隔离级别。
MySQL事务隔离级别
每一种隔离级别可以解决对应的问题,如下:
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
读未提交 | 未解决 | 未解决 | 未解决 |
读提交 | 解决 | 未解决 | 未解决 |
可重复读 | 解决 | 解决 | 未解决 |
串行化 | 解决 | 解决 | 解决 |
MySQL事务隔离级别如何实现?
串行化隔离级别是通过直接加速的方式避免并行访问。
读未提交是直接返回记录上的新值。
其他隔离级别的实现是通过创建视图的方式来实现的,在访问时以视图的逻辑结果为准,只不过每种隔离级别创建视图的时机不同:
上述的视图不是指的我们create view的那个视图,而是InnoDB用到的一致性视图。
MySQL事务隔离级别设置
1.通过配置文件my.cnf修改
[mysqld]
transaction-isolation = REPEATABLE-READ
transaction-read-only = OFF
2.通过SQL语句执行
-- 查看当前隔离级别
show variables like 'transaction_isolation';
-- 针对当前会话设置隔离级别
set session transaction isolation level read committed ;
-- 设置全局事务隔离级别,对已连接的会话不生效
set global transaction isolation level read committed ;
MySQL的回滚日志?
MySQL在执行更新的时候除了会记录redo log以外,还会记录一条回滚操作到undo log,通过回滚日志可以得到前一个状态的值。
假设一个值1按照顺序改成了2、3、4,会有如下回滚日志:
在查询这条记录的时候,不同时刻启动的事务会有不同的视图,在视图A、B、C中这个记录的值分别为1、2、4,同一条记录在系统中可以存在多个版本,这成为数据库的多版本控制(MVCC)。
关于MVCC的详细细节我们在后续了解完锁以后一起说,这样update语句的所有操作基本就全了(锁+事务+日志)。
MySQL的回滚日志什么时候删除?
系统判断没有比这个回滚日志更早的视图的时候(也就是没有事务再用到这些回滚日志时),回滚日志就会被删除。
长事务会存在很多老的视图,事务可能会访问数据库里的任何数据,因此这个事务提交前,数据库里面用到的回滚记录都必须保留,这就会导致回滚日志占用大量的存储空间。
因此如果系统中存在过多的长事务,会导致数据库存储空间增加迅速,并且也会占用锁资源,将有可能拖垮整个库。
MySQL如何启动事务?
1.set autocommit=1;
该方式下事务会自动提交。
-- 显示开启事务
begin/start transaction ;
-- 提交事务
commit;
-- 提交事务并自动启动下一个事务
-- 对于事务频繁使用的系统,可以减少begin/start transaction的一次交互。
commit work and chain ;
-- 回滚事务
rollback;
2.set autocommit=0;
该命令会将线程的自动提交关闭,只要执行一个select语句便开启事务,并且事务不会自动提交,必须手动commit和rollback。
推荐使用第一种方式set autocommit=1的方式,这种方式事务会自动提交,避免忘记手动commit带来的长事务。