-
事物四大特性:原子性、一致性、隔离性、持久性(ACID)
-
mysql默认事物自动提交
show variables like "autocommit"; 查看显示 autocommit 为 on
如果我们手动开启一个事物,那 autocommit(自动提交)失效,必须手动 commit之后修改的数据才会生效
即:
begin; 事物上下文... commit;
-
与隔离性息息相关的隔离级别:
- 读未提交(READ-UNCOMMITTED):
- 读已提交(READ-COMMITTER):
- 可重复读(REPEATABLE-READ):Mysql默认的隔离级别
- 串行化(SERIALIZABLE):
-
mysql5.x版本查看隔离级别
show variables like 'tx_isolation'; 或者 select @@tx_isolation;
mysql8.x版本查看隔离级别
show variables like 'transaction_isolation'; 或者 select @@transaction_isolation;
-
可重复读(REPEATABLE-READ)
当前事物只有提交了,才能读到另一个事物已提交的数据;
一个事物A更新了一条数据,如果该事物A没提交,那另一个事物B不会读到更新的数据;
即使事物A提交了,如果事物B没提交,也是读不到的;操作示意:图片上数字代表操作流程
会出现的问题:
幻读
一个事物读到了另一个事物insert、delete的数据,就像出现了幻觉一样
事物A提交了,事物B更新命中事物A新增的数据,就会导致两次查询数据不一致(第二次莫名其妙的多了)
还有一点需要注意的是:事物A未提交之前,update一条数据,会给这条数据加写锁,
事物B再想更新这条数据就会失败,锁等待超时,只有事物A提交了,才会释放锁,另一事物B才可以更新该条数据
(1205 - Lock wait timeout exceeded; try restarting transaction)
但是不更新同一条数据是不会产生锁等待情况的
插入也是一样:事物A新插入一条数据,然后未提交,事物B更新命中到该数据,也是等待锁
所以:综合来看,可重复读(REPEATABLE-READ)并发性和隔离性都还可以
-
串行化(SERIALIZABLE):
与 可重复读(REPEATABLE-READ)不同的是:事物A更新数据库某张表,就会给该表加上写锁,
只要事物A未提交,另一事物B想要查询、更新都会等待锁所以: 串行化(SERIALIZABLE)并发性不行,隔离性非常优秀(但是不用。。)
-
读已提交(READ-COMMITTER)
事物A更新的数据提交之后,事物B未提交就可以读到(相对 可重复读(REPEATABLE-READ)事物B必须提交才能读到)
所以 读已提交(READ-COMMITTER)还会存在一个新的问题:
不可重读
一个事物读到了另一个事物update的数据,两次读取数据不一致
因为只要事物A提交了,事物B就可以读到
相比 可重复读(REPEATABLE-READ) 并发性增强了,但是隔离性变低了
-
读未提交(READ-UNCOMMITTED)
事物A做的更新,不用提交,事物B就可以查询到改变
那除了会出现幻读、不可重读外,还会出现
脏读
一个事物读到了另一个事物未提交的数据,这数据是“脏”的,飘忽不定的,不是最终确定的数据
所以:读未提交(READ-UNCOMMITTED)并发性很优秀,但是隔离性很差
-
总结:
- 事物的隔离级别中,并发性和隔离性是此消彼长的,一方强,另一方则弱
- 串行化(SERIALIZABLE)不会出现问题,但是并发性太差,很少使用
可重复读(REPEATABLE-READ)会出现幻读,是mysql默认的隔离界别
读已提交(READ-COMMITTER)会出现幻读和不可重读,并发性提升、隔离性下降
读未提交(READ-UNCOMMITTED)会出现幻读、不可重读、脏读,并发性最佳,但是隔离性最差