【MySQL学习篇】— 事务
引入事务
假设在银行转账过程中,需要先执行减钱SQL语句,然后执行加钱SQL语句,可万一中间出现意外,就会有人遭受损失
UPDATE bank SET money=money-200 WHERE id='119';
#中间出现意外,钱减了,但是另一方没有加上
UPDATE bank SET money=money+200 WHERE id='911';
这时候,就需要引入事务来解决,保证这两部分是一个整体。
什么是事务?
多组操作,要么全部成功,要么全部失败
起点(start transaction):开启事务
(中间失败:回滚 到 起点)rollback;
终点(commit):提交 当前事务已经结束
START TRANSACTION ;
UPDATE bank SET money=money-200 WHERE id='119';
UPDATE bank SET money=money+200 WHERE id='911';
COMMIT;
也就是说,等到执行 commit 的时候,数据库中的数据才真正的发生更改。
事务的四大特性:
-
原子性(automic):同一事务中多组操作不可分割,必须是一个整体
-
一致性(consisent):事务操作前与事务操作后总量保持一致
-
隔离性(ISOLATION):多个事务之间互不干扰
-
持久性(durable):数据一旦提交后进入库中、表中,就永久存在
四种隔离级别
四种隔离级别(由低到高):read uncommitted、read committed、repeatbale、Serializable
隔离级别越高,性能越差
查看mysql软件隔离级别
SELECT @@transaction_isolation;#(8.0以后)
select @@tx_isolation;#(8.0以前)
修改mysql软件默认隔离级别: SET GLOBAL TRANSACTION ISOLATION LEVEL 隔离级别;
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
不同的隔离级别会引发不同的问题
脏读:
当mysql事务隔离级别为read uncommitted(可读没有提交过的)时,会引发脏读。
一个事务可以读取另一个未提交的事务:两个事务同时开启,甲事务若操作增删改查,但未提交,乙事务能够读取的到。
解决脏读,可改级别为read committed时,引发不可重复读
不可重复读
在MySQL事务隔离级别为read committed(只读已经提交的)时,引发不可重复读。
在同一事务中,多次读取结果不一致:当在统计财务报表时,开启一个事务,有另一事务在更改表中财务数据,事务提交后,导致统计事务每次统计值不一样。
如何解决不可重复读:级别改为repeatable read就可以
虚读(幻读)
当级别为repeatable时,会引发虚读(幻读)
不可重复读会因为数据的更改,而虚读是因为数据条数的增加,影响统计值。