ToB企服应用市场:ToB评测及商务社交产业平台

标题: mysql事务 [打印本页]

作者: 张国伟    时间: 2023-5-19 01:42
标题: mysql事务
事务(mysql)

第一章 事务概念

1、事务机制在程序开发过程中有着很大的作用。在现实生活中,经常进行转账操作,分为两个步骤:转入与转出,只有当两部分都完成才认为转账成功。
2、如果其中任意操作异常没有执行成功,则会导致两账户的金额不同步,造成错误,为了避免上述错误,数据库引入事务。
3、事务:就是对数据库的一组操作,可以为一条或多条 sql 执行,其特点:要么都做,要么都不做。
在数据库中使用事务时,必须先开启事务,命令如下:
  1. start transaction;
复制代码
事务开启后就可以执行 sql 语句,sql 语句执行完成后,需要相应语句来提交事务,可使用如下命令来结束事务:
  1. #提交
  2. commit;
  3. #回滚
  4. rollback;
复制代码
sql 语句是自动提交的,事务需要手动提交:commit
如果不想提交事务,可通过 rollback 来回滚事务,使事务结束。
已提交的事务不能回滚
案例操作:
创建表:
  1. create table account(
  2.         id int primary key auto_increment,
  3.     name varchar(40),
  4.     money float
  5. );
  6. #插入数据
  7. insert into account(name,money) values('a',100);
  8. insert into account(name,money) values('b',100);
复制代码

演示事务操作:
通过 a 账户向 b 账户转入 10元,结果如下:

注意:当 update 中出现错误,会导致事务不执行,这样保证了事务的同步性。
而事务有严格的定义,必须满足 4 个特性:
第二章 事务提交

事务操作最后需要手动提交,这个过程为确认过程。
例如在第一章 中 a账户向 b 账户转账了 10元,现在反过来
  1. start transaction;
  2. update account set money=money+10 where name='a';
  3. update account set money=money-10 where name='b';
复制代码
执行上述命令,后查看数据

上述事务没有提交|回滚操作,这样会导致数据只是临时修改,当重新登录数据库后,数据库中没有改变,如下:

发现数据没有修改,因为事务需要手动提交,下面为手动提交后的结果:(重新登录数据库)
  1. start transaction;
  2. update account set money=money+10 where name='a';
  3. update account set money=money-10 where name='b';commit;
复制代码

所以事务一定需要提交,否则事务操作是暂时的。
第三章 事务回滚

在操作事务时,发现当前事务中的操作不合理,此时只要事务还没有提交,就可以通过 回滚 来取下事务.
案例操作:a账户向 b 账户转账 10元
  1. start transaction;update account set money=money-10 where name='a';
  2. update account set money=money+10 where name='b';
复制代码
上述命令没有提交命令,也就是事务没有提交
执行结果如下:

可以看出转账操作成功执行,但此时 a 不想转账了,这时由于事务还没提交,所以可以撤销上述操作,通过如下命令:
  1. rollback;
复制代码
上述命令执行后结果如下所示:

可发现转账操作撤销了。
第四章 事务隔离级别

数据库是多线程并发访问的,所以很容易出现多个线程同时开启事务的情况,这样会出现以下情况:
为了避免情况的发生,需要设置事务隔离级别。
mysql 中的隔离级别有如下 4 种:
4.1、脏读演示

脏读:一个事务读取了另外一个事务未提交的数据。
如 a 向 b 进货,a开启事务执行下述操作:
  1. start transaction;update account set money=money-10 where name='a';
  2. update account set money=money+10 where name='b';
复制代码
这时,a中的事务没有提交,通知 b 查询账户,而 b 的隔离级别低,就会读取到 a 中未提交的数据,b发现账户增加了 10元,于是向 a 发货,等 b 发货后,a 回滚事务,此时 b 就会亏损。如下操作演示上述问题:
1、设置 b 中的事务隔离级别

mysql 中默认隔离级别为repeatable read:可重复读,
这里设置其隔离级别为:read uncommitted:
  1. set session transaction isolation level read uncommitted;
复制代码
session:当前会话
transaction:事务
isolation:隔离
level:级别
read uncommitted:当前隔离级别
查询事务隔离级别为:
  1. select @@transaction_isolation;# mysql8
复制代码

可发现修改成功。
2、演示脏读

b账户:先开启一个事务,在其中查询余额信息

a账户:开启事务,执行转账
  1. start transaction;update account set money=money-10 where name='a';
  2. update account set money=money+10 where name='b';
复制代码

b账户:查询账户余额

发现账户显示钱已到帐,可以发货,当发货后,a账户回滚事务,这样 b账户就会亏损
当 b账户设置隔离级别为:读已提交 后,再次执行上述操作,发现 b账户中没有变化。


4.2、演示不可重复读

指事务中两次查询结果不一致,原因是查询过程中其他事务做了更新操作。
例如:银行统计报表期间,第一次 a账户有 100元,第二次查询 a账户有 99元,原因是统计期间 a账户取出了 10元,这样会导致多次统计报表的结果不一致。
演示:
b账户:开启事务,在事务中查询账户余额信息

a账户:直接修改数据,不用开启事务

b账户:查询数据:

当设置 b账户事务隔离级别为 :repeatable read;时,重复上述操作:


发现不变。
4.3、演示幻读

指在一个事务中两次查询中数据条数不一致,因为其他事务做了插入操作
b账户:事务隔离级别设置为 :read committed;且查询账户余额

a账户:直接插入,不用开启事务

b账户:查询

发现账户多数据
当需改b账户事务隔离级别为:重复读,再次执行上述操作,结果如下。

发现结果一致。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4