您现在的位置是:首页 >技术交流 >【MySQL数据库 | 第十五篇】事务网站首页技术交流
【MySQL数据库 | 第十五篇】事务
目录
前言:
这章我们将进入到MySQL基础篇的最后一章:事务,希望大家可以坚持下去,跟着我一起走完MySQL的学习之旅。
介绍事务:
MySQL是一种关系型数据库管理系统,支持事务管理。事务是指一组数据库操作,它们按照特定的顺序执行,并且要么全部成功提交,要么全部失败回滚。在MySQL中,事务可以用来保证数据的完整性和一致性。
在MySQL中,通过使用事务,可以保证对数据的操作是可靠和安全的。当对数据进行复杂的操作时,使用事务可以确保一组操作都成功或者都失败,防止出现数据不一致的问题。
举例:
银行转账就是一个典型的事务,如果张三要给李四汇款,那么我们不能分开执行 给张三扣一千块,给李四转一千块,因为这样如果即使张三没有1000元,我们也会给李四转账。因此我们应该把这两个整理成为一个操作:先给张三扣钱,如果扣钱成功,再给李四汇款,这样如果张三的钱不够,我们就可以及时中断操作,而我们这样集成多个操作一起执行就叫做定义一个事务。
MySQL的事务时默认自动提交的,也就是说:当执行一条DML语句的时候,MySQL会立即隐式的提交事务。
控制事务:
- 开始事务(BEGIN):用于明确一个事务的开始,之后的所有操作都属于同一个事务范围内。
- 提交事务(COMMIT):用于将一个事务提交到数据库中,表示该事务所有的修改操作已经完成,数据已被持久化,该事务执行完成。
- 回滚事务(ROLLBACK):用于撤销一个事务中发生的所有修改操作,使得数据回到事务开始前的状态。当一个事务无法完成时,需要撤销该事务的所有变更。
1.查看/设置事务提交方式
SELECT @@ autocommit;//查询当前事务提交状态
SET @@ cutocommit =0;//1 自动提交 0 手动提交
2.提交事务
COMMIT;
3.回滚事务
ROLLBACK;
控制事务案例:
1.通过修改事务提交方式的方法来控制事务
我们可以通过代码来演示刚才所说的银行例子:
二人初始状态:
我们把事务提交方式修改为手动提交后进行转账操作:
select @@autocommit;
set @@autocommit =0;
-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';
我们此时如果执行这些语句:
结果:
这是因为我们把事务提交方式设置为了手动提交,这样系统执行语句并不会向数据库提交事务。
提交事务(commit):
select @@autocommit;
set @@autocommit =0;
-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';
commit;
结果:
需要注意的是如果我们不提交事务而不断执行操作,我们并不能够认为这些操作并没有执行,而是他被存储在了待执行操作里,只要我们提交了事务,这些操作就会一一执行:
证明:我们尝试第一次只进行语句执行操作不提交,第二次进行语句执行操作和提交
操作结果:
2.不通过修改事务提交方式来对事务进行操作:
1.开启事务
START TRANSACTION 或 BEGIN;
2.提交事务
COMMIT;
3.回滚事务
ROLLBACK;
代码:
START TRANSACTION ;
select * from account where name = '张三';
update account set money = money - 1000 where name = '张三';
update account set money = money + 1000 where name = '李四';
COMMIT ;
结果:
事务四大特性:
-
原子性(Atomicity):在一个事务中,要么所有的操作都成功提交,要么全部回滚到事务开始前的状态,保证操作的原子性。
-
一致性(Consistency):事务执行结束后,数据应该保持一致性状态,不管事务执行成功或失败,数据库都应该满足预定义的完整性约束条件。
-
隔离性(Isolation):在一个事务执行的过程中,不会被其他并发的事务所干扰,保证了事务的隔离性。
-
持久性(Durability):事务提交后,其所做的修改将永久保存到数据库中。
并发事务问题:
1. 脏读(Dirty Read):一个事务读取到了另一个事务尚未提交的数据,如果那个事务回滚或者修改了该数据,可能会造成数据不一致性。
2. 不可重复读(Non-repeatable Read):一个事务在多次读取一个数据时,由于这个数据被其他事务修改导致其多次读取到不同的结果,这种情况下,第一个事务可能会认为数据被修改了多次,但实际上只是一个事务修改了。
3. 幻读(Phantom Read):一个事务在多次读取一组数据时,由于其他事务插入了新的数据导致其读取到了不同的数据行,这种情况下,第一个事务可能会认为数据被修改或删除了,但实际上只是有新的行插入了。
解决这些问题的方法通常是加锁或者使用更高级的事务隔离级别。例如:
1. 通过在读取数据时加锁来避免脏读和不可重复读,例如使用行锁或表锁。
2. 提高事务隔离级别,例如升级到可重复读级别,这样防止了不可重复读,但不能完全避免幻读。
3. 使用更高级的隔离级别,例如串行化,这样可以同时避免脏读、不可重复读和幻读,但也会对性能造成一定的影响。
需要根据具体的业务场景、数据类型和访问模式选择合适的解决方案来保证数据的一致性和可靠性。
事务隔离级别:
-
读未提交(Read Uncommitted):一个事务可以读取另一个未提交的事务中的数据。本级别隔离最低,会存在脏读、不可重复度和幻读的问题,并发量最大,性能最优。
-
读已提交(Read Committed):读取另一并发事务提交的变化数据,读取操作时加锁,所以一定程度上可以避免脏读。但因为以读未提交为基础,因此仍然可能出现不可重复读和幻读的问题。
-
可重复读(Repeatable Read):在一个事务中多次读取同一记录时,它能够保证所读取的数据是一样的,该级别通过行级锁定已读取数据,避免了不可重复读,但仍可能出现幻读。
-
序列化(Serializable):所有事务顺序执行,即依次执行,不能并发执行,以此保证最高级别的隔离程度,也保证了隔离级别下的数据一致性。是最保险的事务隔离级别,但并发性最差,性能最低。
Repeatable Read是MySQL的默认事务隔离级别
语法:
1.查看当前事务隔离级别
SELECT @@TRANSACTION_ISOLATION;
2.设置事务隔离级别
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {隔离级别};
SESSION与GLOBAL区别:
- SESSION是指在当前客户端设置隔离级别
- GLOBAL是指在所有客户端设置隔离级别。
总结:
本片我们介绍了事务以及事务提交问题,MySQL数据库的基础篇就到此完结了,下一篇我会详细讲解什么是脏读,幻读,不可重复读。然后会持续更新进阶篇,也就是对各种语句的优化,欢迎大家持续阅读。
今天的内容到这里就结束了,感谢大家的阅读。
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!