MySQL——事务

什么是事务?在MySQL中数据开发中,我们为了完成某一功能,通常会写一组sql语句,为了保证sql语句操作数据的完整性,引入了事务。简单的说事务就是让多条语句要么全执行,要么全不执行。举个例子小王给小李转500块钱,小王的银行卡扣除了500,小李的银行卡里多了500,这才认为这次转账成功。在数据库中只要有一条语句出现异常,就会导致两个账户金额不同步,就像小王的钱少了500,小李却没收到,这就出现了转账错误。

MySQL必须满足4个特性,分别是原子性、一致性、隔离性和持久性

1、原子性是指:一个事务必须被视为一个不可分割的最小工作单元,只有事务中所有的数据库操作都执行成功,才算整个事务执行成功。事务中如果有任何一个SQL语句执行失败,已经执行成功的SQL语句也必须撤销,数据库的状态退回到执行事务前的状态。

2、一致性是指:事务将数据库从一个一致状态转变为下一个一致状态。在事务完成之前和完成之后,都要保证数据库内的数据处于一致状态。

3、隔离性是指:当一个事务在执行时,不会收到其它事务的影响。隔离性保证了未完成事务的所有操作与数据库系统的隔离,直到事务完成之后,才能看到事务的执行结果。当多个用户并发访问数据库时,数据库为每一个用户开启的事务不能被其他事物的操作数据所干扰,多个并发事务之间要相互隔离

4、持久性是指:事务一旦提交,对数据库中数据的修改就是永久性的。需要注意的是,事务的持久性不能做到百分之百的持久(比如电商交易记录保存两年即可看做满足持久性),只能从事务本身的角度来保证永久性,如果一些外部原因导致数据库发生故障(如硬盘损坏),那么所有提交的数据可能都会丢失。


事务的基本操作:

1、开启事务 START TRANSACTION;--在执行完这条语句后,后续的每一条SQL语句将不会默认自动提交。

2、手动提交事务 COMMIT;

3、回滚事务(撤回)ROLLBACK;-- 需要注意的是,ROLLBACK语句只能针对未提交的事务执行回滚操作,已提交的事务不能回滚。当执行COMMIT或ROLLBACK后,当前事务就会自动结束。

MySQL中的事务默认是自动提交,可以通过更改AUTOCOMMIT的值来更改是否自动提交,其中1表示开启自动提交,0表示关闭自动提交。

我们先使用这条语句看看是否开启自动提交。

SELECT @@AUTOCOMMIT;

如果想要关闭自动提交则使用这条语句

SET AUTOCOMMIT=0;

执行这条语句后,用户需要手动执行提交操作,事务才会提交。如果直接终止MySQL会话,MySQL会自动进行回滚。


事务的保存点:在回滚事务时,事务内的所有操作都会被撤销,如果只想撤销事务内的部分操作,就可以使用保存点。

创建保存点的语法:SAVEPOINT 保存点名称;

回滚到指定的保存点:ROLLBACK TO SAVEPOINT 保存点名称;

删除指定的保存点:RELEASE SAVEPOINT 保存点名;

需要注意的是,一个事务可以创建多个保存点。一旦提交事务,事务中的保存点都会被删除。另外,如果事务回滚到某个保存点后,该保存点之后创建的其他保存点也会被删除。


事务的隔离级别:MySQL支持多线程并发访问,用户可以通过不同的线程执行不同的事务。为保证多个事务之间互不影响,就需要为事务设置适当的隔离级别。

事务有4种隔离级别,分别为READ UNCOMMITTED(读未提交)、READ COMMITTED(读已提交,默认隔离级别)、REPEATABLE READ(可重复读MySQL默认的)和SERIALIZABLE(串行化)

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

  • SESSION:表示当前会话。

  • TRANSACTION:表示事务。

  • ISOLATION:表示隔离。

  • LEVEL:表示级别。

  •  READ UNCOMMITTED:表示当前设置的隔离级别。(读未提交)

在使用这几个隔离级别时,容易出现一些问题

UNCOMMITTED:最低隔离级别,会出现脏读(读取其他事务中未提交的数据 ),一致性很差基本不用(其他三个都不会出现脏读)

READ COMMITTED:读取提交的数据,不会出现脏读,但是会出现不可重复读和幻读

不可重复读是指在事务内重复读取别的线程已经提交的数据,由于多次查询,其它事务做了更新操作,因此出现多次读取的结果不一致的现象。使用REPEATABLE READ (可重复读)可以解决

为什么强调:事务内可重复读?

举例:(这里的隔离条件为READ COMMITTED)假设在银行金融系统,现在按照存款给与福利,满500的送一桶油,满700的送一袋米,现在张三的存款是550,事务A读取数据为550,满足福利一,系统给与一桶油。但在执行时,张三突然充值200,此时事务A读取数据为750,满足福利二,系统再给一袋米,张三获得了两个福利。

强调一个事务内可重复读:在事务开始的瞬间,时间就已经定格,与外界失联。只要我还没 commit/rollback结束这个事务,数据就不会再更新。可以防止上面例子多发福利的情况。

事务A:SELECT balance FROM accounts WHERE id = 1;  -- 第一次读到500
事务B:UPDATE accounts SET balance = 700 WHERE id = 1; COMMIT;
事务A:SELECT balance FROM accounts WHERE id = 1;  -- 第二次读到700

幻读:又被称为虚读,是指在一个事务内两次查询中的数据条数不一致。幻读和不可重复读类似,都是在两次查询过程中;不同的是,幻读是由于其它事务做了插入记录的操作,导致记录数有所增加。

事务A:SELECT * FROM orders WHERE amount > 1000;  -- 查到5条记录
事务B:INSERT INTO orders(amount) VALUES(2000); COMMIT;  -- 插入新记录
事务A:SELECT * FROM orders WHERE amount > 1000;  -- 查到6条记录

串行化SERIALIZABLE):通过加锁实现,读写冲突时后访问的事务必须等待

虽然事务的隔离级别设置为SERIALIZABLE可以避免脏读、不可重复读和幻读的现象,但是会导致使用数据库时性能太差,因此一般不会在实际开发中使用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值