目录
②设置当前mysql的事务隔离级别(注,要在命令行中执行才有效)
④read committed规避脏读和read committed的不可重复读的演示
⑤repeatable read避免不可重复读与repeatable read的幻读
事务由单独单元的一个或多个SQL语句组成,在这个单元中,每个MySQL语句是相互依赖的。而整个单独单元作为一个不可分割的整体,如果单元中某条SQL语句一旦执行失败或产生错误,整个单元将会回滚。所有受到影响的数据将返回到事物开始以前的状态;如果单元中的所有SQL语句均执行成功,则事务被顺利执行。
即开始事务后执行的所有SQL都是一个整体,一个单元,要么都执行,要么都不执行。这里不执行的意思就row back即回滚,就是回到事务执行前的状态。
1、查看存储引擎
在mysql中,有不同的存储引擎,有些存储引擎支持事务,有些不支持。现在用的最多的是innodb,myisam ,memory
其中innodb支持事务,而 myisam、memory等不支持事务
①查看当前存储存储引擎:
show engines;
2、事务的属性:
1. 原子性(Atomicity)
2. 一致性(Consistency)
3. 隔离性(Isolation)
4. 持久性(Durability)
3、事务的隔离级别
Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE。 Oracle 默认的事务隔离级别为: READCOMMITED
Mysql 支持 4 种事务隔离级别. Mysql 默认的事务隔离级别为: REPEATABLE READ
4、不同的隔离级别会产生的问题
脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
不可重复读: 对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.
幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.
5、mysql事务隔离级别实战
每启动一个 mysql 程序, 就会获得一个单独的数据库连接. 每 个数据库连接都有一个全局变量 @@tx_isolation, 表示当前的事务隔离级别.
①查看当前事务隔离级别:
SELECT @@tx_isolation;
可知mysql事务的默认级别是可重复读
②设置当前mysql的事务隔离级别(注,要在命令行中执行才有效)
set session transaction isolation level read uncommitted;
SELECT @@tx_isolation;
③read uncommitted的脏读演示:
先创建一个表:
开启事务,并修改一列数据
重新打开一个命令行,注意:每启动一个 mysql 程序, 就会获得一个单独的数据库连接,所以新打开的事务隔离级别还是repeatable read:
若此时用另一个mysql程序查看表时,发现对应的值修改为王五了,若此时第一个mysql程序执行回滚,则读到的数据又变为张三了,此时就出现了脏读情况即读到了脏数据。
④read committed规避脏读和read committed的不可重复读的演示
将两个mysql程序都设置为read committed隔离级别
注:之前的事务虽然回滚了,但还没有提交,要进行下一个操作的话先执行commit;提交事务
可以发现蓝色这边的mysql程序读到的是未提交的数据,就可以避免脏读
黑色这边提交之后,蓝色才能读到:
但也导致了两次连续的查询 查询到的结果不一样,就导致了不可重复读。
⑤repeatable read避免不可重复读与repeatable read的幻读
提交之前的事务并设置事务为可重复读
先看一下现在表有什么数据,不要到时候混乱了:
黑色这边修改数据,蓝色这边查看数据还是原来的,规避了脏读
黑色这边提交,蓝色这边读到的仍然是原来的数据
只有当蓝色这边也提交了才能看到修改的数据,这就能使蓝色这边事务进行过程中读到的数据是一致的。
再次开启事务,演示幻读:
黑色这边先查询有两个数据,此时蓝色这边插入了一条数据并提交了,此时黑色这边就会出现一个问题就是我明明是要修改两个数据的,结果却修改了3个,就导致了幻读。
⑥serializable解决幻读问题
首先还是老样子,提交之前的事务,然后设置事务为serializable
此时在黑色事务打开时,在蓝色这边对数据进行插入操作,发现蓝色这边的操作执行不了,这就是serializable的隔离机制,即之前有事务在进行操作,新的事务要对表进行增删改时就会阻塞改操作,知道当前事务提交才能修改:
那个插入数据之所以没成功,是等待时间太长了,被系统杀死了,大家在操作的时候就不要让另一个事务等太久。
⑦总结
mysql默认隔离级别是repeatable read,因为serializable的缺点很明显,虽然能大大提高安全性,但效率太低了。
注意:serializable名字叫可串行化,并不是说使用了serializable隔离级别所有的事务都要串行执行,它允许事务并发执行,但系统必须保证并发调度是可串行的,即我允许你并行执行,但要求你的并发调度不致发生错误,即如果你的另一个事务只进行查数据,那当然对我的事务无影响,我就允许你执行,但如果你另一个事务有增删改这些操作,就会被阻塞以保障不发生错误。