首页 > 数据库 >mysql事务

mysql事务

时间:2023-05-18 17:55:49浏览次数:42  
标签:10 事务 name 账户 money 提交 mysql

事务(mysql)

第一章 事务概念

1、事务机制在程序开发过程中有着很大的作用。在现实生活中,经常进行转账操作,分为两个步骤:转入与转出,只有当两部分都完成才认为转账成功。

2、如果其中任意操作异常没有执行成功,则会导致两账户的金额不同步,造成错误,为了避免上述错误,数据库引入事务。

3、事务:就是对数据库的一组操作,可以为一条或多条 sql 执行,其特点:要么都做,要么都不做。

在数据库中使用事务时,必须先开启事务,命令如下:

start transaction;

事务开启后就可以执行 sql 语句,sql 语句执行完成后,需要相应语句来提交事务,可使用如下命令来结束事务

#提交
commit;
#回滚
rollback;

sql 语句是自动提交的,事务需要手动提交:commit

如果不想提交事务,可通过 rollback 来回滚事务,使事务结束。

已提交的事务不能回滚

案例操作:

创建表:

create table account(
	id int primary key auto_increment,
    name varchar(40),
    money float
);
#插入数据
insert into account(name,money) values('a',100);
insert into account(name,money) values('b',100);

演示事务操作:

  • 首先开启事务

    • start transaction;
      
  • 转账

    • update account set money=money-10 where name='a';
      update account set money=money+10 where name='b';
      
  • 提交事务

    • commit;
      

通过 a 账户向 b 账户转入 10元,结果如下:

注意:当 update 中出现错误,会导致事务不执行,这样保证了事务的同步性。

而事务有严格的定义,必须满足 4 个特性:

  • 原子性(atomicity)
    • 指一个事务必须视为一个不可分割的最小工作单元,当事务中所有的操作完成后,才算整个事务执行成功,事务中有一条 sql 失败,则执行成功的 sql 也必须撤销,数据库的状态回退到执行事务前的状态
  • 一致性(consistency)
    • 指事物将数据库从一种状态转换为另一种状态;例如事务执行失败,数据库回退到执行事务前的状态。
  • 隔离性(isolation)
    • 也称并发控制、可串性化、锁等,指事务各自执行,互不干扰
  • 持久性(durability)
    • 事务操作一旦提交,其修改的数据就会永久保存在数据库中。

第二章 事务提交

事务操作最后需要手动提交,这个过程为确认过程。

例如在第一章 中 a账户向 b 账户转账了 10元,现在反过来

start transaction;
update account set money=money+10 where name='a';
update account set money=money-10 where name='b';

执行上述命令,后查看数据

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

发现数据没有修改,因为事务需要手动提交,下面为手动提交后的结果:(重新登录数据库)

start transaction;
update account set money=money+10 where name='a';
update account set money=money-10 where name='b';
commit;

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

第三章 事务回滚

在操作事务时,发现当前事务中的操作不合理,此时只要事务还没有提交,就可以通过 回滚 来取下事务.

案例操作:a账户向 b 账户转账 10元

start transaction;
update account set money=money-10 where name='a';
update account set money=money+10 where name='b';

上述命令没有提交命令,也就是事务没有提交

执行结果如下:

可以看出转账操作成功执行,但此时 a 不想转账了,这时由于事务还没提交,所以可以撤销上述操作,通过如下命令:

rollback;

上述命令执行后结果如下所示:

可发现转账操作撤销了。

第四章 事务隔离级别

数据库是多线程并发访问的,所以很容易出现多个线程同时开启事务的情况,这样会出现以下情况:

  • 脏读
  • 重复读
  • 幻读
  • ......

为了避免情况的发生,需要设置事务隔离级别。

mysql 中的隔离级别有如下 4 种:

  • read uncommitted:读未提交
    • 最低级别
    • 该级别下的事务会读取到另一事务中未提交的数据,称为:脏读(dirty read),这是很危险的,所以很少用
  • read committed:读已提交
    • 大多数据库管理系统的默认隔离级别,如 oracle
    • 该级别下的事务只能读取其他事务已经提交的内容
    • 可避免脏读,但不能避免 不可重复读、幻读。
    • 不可重复读:指事务内重复读取别的线程已经提交的数据,但两次读取的结果不一致,原因是查询过程中其他事务做了更新操作。
    • 幻读:指在一个事务内两次查询中数据条数不一致,原因是查询过程中其他事务做了添加操作。
    • 不可重复读与幻读严格上说不是错误,但其情况不符合实际需求。
  • repeatable read:可重复读
    • MySQL 的默认事务隔离级别
    • 避免脏读、不可重复读问题
    • 会出现幻读情况
    • 确保同一事务的多个实例在并发读取数据时,看到的是相同的数据
  • serializable:可串行化
    • 事务的最高隔离级别
    • 会对事务强制排序,使其不发生冲突
    • 解决脏读、幻读、不可重复读问题。
    • 实际上就是在读数据时,进行加锁操作,可能导致大量的超时现象和锁争

4.1、脏读演示

脏读:一个事务读取了另外一个事务未提交的数据。

如 a 向 b 进货,a开启事务执行下述操作:

start transaction;
update account set money=money-10 where name='a';
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:

set session transaction isolation level read uncommitted;

session:当前会话

transaction:事务

isolation:隔离

level:级别

read uncommitted:当前隔离级别

查询事务隔离级别为:

select @@transaction_isolation;# mysql8

可发现修改成功。

2、演示脏读

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

a账户:开启事务,执行转账

start transaction;
update account set money=money-10 where name='a';
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账户事务隔离级别为:重复读,再次执行上述操作,结果如下。

发现结果一致。

标签:10,事务,name,账户,money,提交,mysql
From: https://www.cnblogs.com/xiarongblogs/p/17412829.html

相关文章

  • ModuleNotFoundError: No module named 'MySQLdb'
    想用FastApi搞点东西,之前没怎么接触过python,根据pyloong大佬的文章https://pyloong.github.io/pythonic-project-guidelines/practices/web/#36-fastapi创建demo,到运行是出现了这个错误:ModuleNotFoundError:Nomodulenamed'MySQLdb'。然后各种chatGPT,bing,google,找到的都是要我......
  • Mysql--函数
    时间,日期相关函数参考:https://www.cnblogs.com/Xinenhui/p/16348570.html 一、基本函数1.1count()统计数据表中包含的记录行的总数语法:SELECTCOUNT(*)FROMt1;SELECTCOUNT(字段名)FROMt1;用法:count(*)  统计表中的总行数,无论某列有值或者空值,包含nullcou......
  • .NET6 + EF Core + MySQL 创建实体和数据库、EFCore 数据迁移
    前言接上期文章《.NET6项目连接数据库方式方法》,有人问了我几个问题,现在就这几个问题,拓展延申一下创建实体类、数据库。把ORM框架和数据迁移都写进去。安装ORM框架,这里我们采用EFCore安装EFCore我的项目是在Linux上创建的,使用的是vscode开发工具远程开发。为了方便大家阅读和......
  • 服务器安装mysql
    数据库连接操作修改root的hostupdateusersethost=‘%’whereuser=‘root’andhost=“127.0.0.1”flushprivileges;设置不用密码updatemysql.usersetauthentication_string=’’whereuser='root'andhost='%';flushprivileges;创建新用户,并赋予所有权限create......
  • Navicat连接本地mysql报错-caching_sha2_password
     查询用户加密方式:selectuser,pluginfromuserwhereuser='root';修改用户加密方式改为mysql_native_password。alteruser'root'@'localhost'identifiedwithmysql_native_passwordby'123123';执行命令flushprivileges使权限配置项立即生效flushp......
  • mysql导出\导入数据库
    导出数据库mysqldump-upgms-ppgms-S/data/mysql_data/mysql/mysql.sock>pgms.sql;导出单表mysqldump-upgms-ppgms-S/data/mysql_data/mysql/mysql.sockt_organization>t_organization.sql;导入数据sourcet_bindinginfo.sql; ......
  • Linux中jdk11、tomcat10、防火墙的设置、MySQL、的安装步骤
    一般在Linux系统上安装软件步骤:1.上传  2.解压 3.配置环境 4.刷新配置 5.检查       jdk11    tomcat10 设置防火墙mysql ......
  • mysql代理技术
    文章目录mysql数据库代理技术代理简介名词功能产品图示mysql数据库代理技术代理简介名词DBproxy数据库中间件功能读写分离:读写分离导致处理速度迅速,一般情况下是主服务器进行写操作而从服务器进行读操作负载均衡支持数据的分片自动路由和聚合产品MySQLproxy是MySQL官方产品......
  • MySQL免密登录操作
    vi/etc/my.cnf添加到配置文件里面放在[mysqld]下面[mysqld]skip-grant-tables重启服务systemctlrestartmysql登录:mysqlmysql>updatemysql.usersetpassword=password('root')whereuser='root'andhost='localhost';再次回到/etc/my.cnf把刚才添加的......
  • MySQL在Linux中的安装
    MySql安装1、下载mysql安装包再mysql官方下载安装包2、删除依赖包#查找依赖包rpm-qa|grepmysqlrpm-qa|grepMySQLrpm-qa|grepmariadb#删除查询到的依赖包rpm-e--nodepsmariadb-libs-5.5.68-1.el7.x86_643、安装mysql#将安装包上传到linux中mysq......