mysql原生引擎MyISAM引擎是不支持事务的。
事务的四大特征(ACID):
- 原子性( Atomicity): 事务是最小工作单元,不可再分,事务内的DML语句必须都成功或者都失败。
- 一致性( Consistency): 事务前后的数据必须保持一致 (转账中转出和转入的钱必须一致)
- 隔离性( Isolation):事务A和事务B具有隔离性(多个事务同时执行的时候,可能会出现脏读,不可重复读 幻读)
- 持久性( Durability): 一个事务一旦被提交,它对数据库中的数据改变就是永久性的
事务隔离级别:
-
read-uncommited(未提交读): 事务的修改,即使没有提交,对其他事务也是可见的,事务可以读取未提交的数据,称为 “脏读”,在实际应用的很少应用。
-
read-commmited (提交读): 一个事务从开始到提交,对其他事务都是不可见的,也叫做 不可重复读,因为两次同样的查询,可能会有不一样的查询结果。
-
repeatable-read(可重复读):解决了脏读的问题,保证了同一个事务多次的读取记录的结果都是一样的,但是会导致幻读,读取某一行的数据时候,另一个事务插入了数据,这个时候再次读取的时候数据的数量就会发生变化
-
serializeable(可串行化):强制事务串行,避免幻读的问题。会在读取的每一行数据上加锁,会导致超时和锁的争用。
当事务级别是未提交读(脏读)的时候,因为事务A即使未提交,事务A也是可以读取到数据的结果的,所以v1 =v2= v3=2;
当事务级别是提交读(不可重复度),事务B在结束之前事务A是不可以看到数据的,所以v1只能看到之前的值v1=1,v2=v3=2。
当事务级别是可重复读,v1=v2=1,因为可重复读保证了事务在执行期间看到的数据都是一致的结果。v3是在事务B提交完之后查看的,所以v3=2
当事务级别是串行化的时候,事务B在将值改为2的时候,会加上锁;直到事务A提交完之后,事务B才会继续执行,所有v1=v2=1,v3=2
在执行sql的时候的,数据库会创建一个视图,访问数据的时候以视图里的数据为准。
当事务隔离级别是未提交读,直接返回记录上的最新值,没有视图的概念,
当事务隔离级别是不可重复读,这个视图是在sql执行的时候创建,
当事务隔离级别是可重复,这个视图是在事务启动时创建的,
当事务隔离级别是串行化,使用加锁的方式防止对数据的并行访问。
可以使用 show variables like ‘transaction_isolation%’ 命令查看当前的事务隔离级别:
mysql在执行每一个更新操作的时候,都会记录一条回滚操作;可以通过回滚操作让记录的值变回上一个状态的值。
为什么尽量不适用长事务:
长事务意味着存在很老的事务视图,由于这些事务随时可能访问数据库里面的任何数据,所以需要将回滚记录都一直
做保存,就会大量占用存储空间。
事务的启动方式有两种:
- 显式启动事务与语句,beigin或start transaction,对应的提交语句是commit,回滚语句是rollback。
- set autocommit = 0。 这个命令会将这个线程的自动提交事务关闭掉,如果启动了一个select语句,这个事务就启动了,
并且不会主动提交,这个事务回一直存在,直到主动commit或者rollback,或者断开连接。
可以通过set autocommit= 1显式的方式来启动和提交事务。对于频繁需要使用事务的背景,设置了set autocommit=0可以
不需要每次都手动去begin或者start transaction去启动事务,减少了语句的交互。这种情况可以使用 commit work and chain.
commit work and chain是个啥?
事务控制语句有下面这些:
START TRANSACTION | BEIGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT = {0 | 1}
SAVEPOINT identify : 允许在事务中新建一个保存点,一个事务中可以有多个保存点。
RELEASE SAVEPOINT identify: 释放一个保存点,如果没有保存点可以执行,回抛出一个出错。
ROOLBACK TO [SAVEPOINT] identify : 回滚到保存点
CHAIN和RELEASE用于在事务完成之后进行附加操作。completion_type系统变量的值决定了默认完成的性质。
completion_type默认值为0,表示没有任何操作,也就是NO_CHAIN。
当completion_type值为1,也就是CHAIN的时候,表示一个事务提交完毕之后马上开启一个相同事务隔离级别的事务;
当completion_type值为2的时候,也就是release的时候,表示在事务提交完毕之后断开连接。
实际操作记录:
select @@autocommit;可以看到默认是自动提交事务的。
我先截断week表,然后先执行start transaction;再执行插入语句,但是不执行commit语句,去刷新表是没有记录的;
然后再去执行commit;才回看到表里有数了。
再次截断week表,先执行start transaction;再执行插入语句,接着执行commit and CHAIN;,刷新表可以发现,已经插入
了一些数据,然后紧接着再去执行插入语句,可以看到提示是生效了几行数据,但是刷新表是看不到新数据的,再
执行commit语句,就可以发现表里多了一些数据。在第二次插入操作中是没有手动启动事务的,所以commit and chain
确实是自动开启了另一个事务。
同样的,先start transaction;开启一个事务,然后执行insert 语句,接着执行 commit release (不是commit and release),
但是表里是多了数据,但是我没有看到断开连接的提示,还是说dbeaver主动又连接了一次?