时间:2021-07-01 10:21:17 帮助过:12人阅读
把需要保证原子性、隔离性、一致性和持久性的一个或者多个数据库操作称为事务。
begin;//开启一个事务
some sql;//需要执行的语句
savepoint bussiness1;//事务保存点
some sql;
roll back to bussiness1;//回滚
commit;//提交事务
rollback;//如果需要手动回滚的话在提交之前删除这句
通常情况下mysql默认自动提交事务。既每一个语句都都会直接提交事务,可以通过set autocommit=off
来实现手动提交。
在一些操作下,哪怕在事务中也可能会自动把事务进行提交。
set session transaction isolation level [level];
level类型:
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 |
不可重复读、提交读(read-committed) | 否 | 是 | 是 |
可重复读(repeatable read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
翻了一通网上的文章和培训视频对脏幻不可重复读的理解就NM离谱……
去查了一下高性能mysql这本书。
脏读:
定义:事务中的修改,即使没有提交,对其他事务也是可见的。
实例:事务A查询记录1,事务B更新记录1(尚未commit),事务A再次查询记录1,得到事务B更新结果。
在rc级别上已经可以克服脏读的问题。
不可重复读:
定义:一个事务开始时,只能看见已经提交的事务所做的修改。
实例:事务A查询记录1,事务B更新记录1(commit),事务A再次查询记录1,得到事务B更新结果。
幻读:
定义:指的是当某个事务A在读取某个范围的记录时,另一个事务B又插入了一条,A再次查询时会得到查询出这条记录。
幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。
innoDB存储引擎记录数据的行有三个隐藏列:
select 时生成
对于RU级别的事务,直接读取最新记录的版本,对于使用Serializable级别的,使用加锁方式访问,使RC和RR级别的事务则需要使用版本链,核心:判断版本链中的哪个版本是当前事务可见的。
ReadView包含四个比较重要的内容:
在有了这个readview之后,需要按照下边步骤判断记录是否可见:
每次读取数据前都生成一个readview。
在第一次读取数据时生成一个readview
在RC级别下 原先数据为1
有两个事务A,B,时间线如下
B将数据更新,B此时可以读到2
此时A应该读更新前还是更新后的数据?
假设A的事务ID是100,B的是200
如果
min_trx_id=99,
max_trx_id=200;
m_ids=[99,100,200]
此时此时A事务符合规则4,读到的数据应该为1
X锁 | S锁 | |
---|---|---|
X锁 | 冲突 | 冲突 |
S锁 | 冲突 | 不冲突 |
对于普通的select语句InnoDB不会加任何锁。
将查找到的数据加上一个S锁,其他事务能读,但是不能写。
读出数据后:其他事务不能修改,但自己也不一定能修改,因为有可能有别的事务也可以使用select lock in share mode继续加读锁。
加上一个X锁。
delete:先加X锁,再执行删除。
insert:插入一条记录时,会先加隐式锁来保护这条新加入的数据在本事务提交之前不被别的事务访问到。
todo:隐式锁实现是啥呢……
mysql事务与锁
标签:repair lte 数据库 活跃 事务隔离级别 tab 不可重复读 隔离 也会