数据库事务与锁(一)——事务的简单介绍 - Go语言中文社区

数据库事务与锁(一)——事务的简单介绍


前言

最近系统上线了,这两天收到反馈,操作按钮动不了了、删除按钮动不了了等等类似的问题,仔细查看日志错误,提示:Lock wait timeout exceeded; try restarting transaction。于是乎,就想把数据库事务与锁的知识深入了解一下,也为自己解决问题提供思路。本系列文章主要源于Kevin老师的《一次性彻底搞定数据库事务》,感谢老师的讲解。在本篇文章中,我们先来说说事务。

概念

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列读或写操作。其目的是提供三种方法:失败恢复到正常状态的方法、保持一致性的方法、并发操作之间保持隔离的方法,通俗的说是那一系列操作要么完全地执行,要么完全地不执行。

特性

A:原子性(Actomicity),该系列操作作为一个整体,不能被分割,要么全执行,要么都不执行;

C:一致性(Consistency),确保数据从一种状态变为另一种状态;

I:隔离性(Isolation),多个事务并发执行时,彼此之间互不影响;

D:持久性(Durability),当事务提交成功后,对数据的修改要永久保存在数据库中。

并发异常

回滚丢失:由于一个事务的失败回滚导致另一个事务的更新丢失了;

覆盖丢失:更新被其他事务给覆盖了;

脏读:一个事务读取了另一个事务修改未提交的数据;

不可重复读:一个事务对同一行数据执行了两次或更多次查询,但是却得到了不同的结果;

幻读:与不可重复读相似,不过针对的是数据的数量,当一个事务查询记录两次或多次时,得到的数量不一致。

隔离级别

读未提交:一个事务的更新语句没有提交,但是别的事务可以读到这个改变;

读已提交:一个事务只能看到其他事务已经提交的更新、看不到未提交的更新,消除了脏读和回滚丢失,Oracle/Sqlserver就是此类;

可重复读:一个事务中进行两次或多次同样的对于数据内容的查询,得到的结果是一样的,但不保证对于数据条数的查询是一样的,只要存在读改行数据就禁止写,消除了不可重复读和覆盖丢失,如Mysql,需要注意的是虽然Mysql的隔离级别为可重复读,理论上是不能解决幻读异常的,但由于Next-key,Gap-lock的存在,使得Mysql可以避免幻读问题;

串行化:事务执行不允许其他事务操作,只要存在读就禁止写,但可以同时读,消除了幻读,但是效率太低。

隔离级别与并发异常的对应关系
隔离级别并发异常 回滚丢失 脏读 不可重复读 覆盖丢失 幻读
读未提交
读已提交
可重复读
串行化

实战

这里以Mysql为例进行说明,工具使用的是Navicat。

操作之前,我们先来了解几个指令:

查看数据库版本:select version();
查看隔离级别:select @@session.tx_isolation;
修改隔离级别:set @@session.tx_isolation=参数;
可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE
开启事务:start transaction;
提交:commit;
回滚:rollback;

我们可以通过使用指令设置Mysql的隔离级别,来验证上述表格中内容是否正确,不过需要说明的是,由于Mysql的锁等内容,可能会导致有些情况无法验证或验证有差异。这里,我设置Mysql的隔离级别为读已提交,验证脏读异常是否存在。

操作步骤:

1)新建一个数据库,命名为代表db1,建一张表,命名为tbook;

CREATE TABLE `tbook` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  `price` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

2)右键数据库db1——命令列界面,这里我打开两个,模拟两个事务;

3)因Mysql默认的隔离级别为可重复读,因此我们需要先设置隔离级别为读已提交,在两个命令列界面中分别设置,同时开启事务:

set @@session.tx_isolation='READ-COMMITTED';

start transaction;

4)模拟脏读异常场景,在tbook表中插入一些数据。看下图效果显示,表明当隔离级别为读已提交,脏读异常不存在:

事务1 事务2
查询数据得到初始值1 查询数据得到初始值1
更新数据为2  查询数据值仍为1
commit commit
事务1
事务2

  

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/yuyinghua0302/article/details/81777440
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-07 15:14:42
  • 阅读 ( 1158 )
  • 分类:数据库

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢