数据库锁和隔离级别
程序员文章站
2022-06-14 17:15:49
...
事务
事务即acid
a,原子性,都成功或都失败
c,一致性,数据一致性
i,隔离性,事务互不干扰
d,持久性,一旦完成就会保存下来
事务隔离级别
脏读,不可重复读,幻读 是不同隔离级别需要解决的问题。每个事务都可以设置自己独立的隔离级别。
- 读未提交
别的事务未提及的信息,也可以读到。脏读问题。 - 读已提交
自己能够读到未提交,但是别的事务被隔离了,只能读到已提交的内容。解决脏读,但是不可重复读问题存在。 - 可重复读
在同一个事务内,对数据的查询,数据是不变的。(不论其他事务是修改数据还是新增数据)解决不可重复读,但是幻读问题存在。如果想了解可重复读的机制,请查看我的帖子 mvcc机制 - 串行化
事务排队,只要有某事务对某一数据进行查询,其他事务就不能对该数据进行修改。
幻读定义:
幻读错误的理解:说幻读是 事务A 执行两次 select 操作得到不同的数据集,即 select 1 得到 10 条记录,select 2 得到 11 条记录。这其实并不是幻读,这是不可重复读的一种,只会在 R-U R-C 级别下出现,而在 mysql 默认的 RR 隔离级别是不会出现的。
幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。
select @@tx_ioslation;
set tx_isolation = 'read-uncommited';
select * from account;
start transaction;
锁机制
锁就是解决并发访问同一个资源的一种方案。
- 共享锁
s锁,读锁,一个事务在对某些数据加上该锁后,其他事务只能在读该数据和对该数据加共享锁,而不能写该数据。select * from account where id = 1 lock in share mode;
- 排他锁
x锁,写锁。一个事务在对某些数据加上该锁后,其他事物就不能再加共享锁和修改该数据,但是可以用不加锁的方式查看数据。select * from account where id = 1 for update;加了排他锁,行锁。 select * from accoutn where name = "66" for update;加了排他锁,因为条件不是索引,所以只能全表扫描,会锁表。 update account set name = "55" where id = 1;加了排他锁,行锁。
- 意向共享锁
IS锁,获取共享锁之前,先去查看是否有意向锁,有,就直接返回了,提高性能。 - 意向排他锁
IX锁,解释同上。 - 自增锁
就算事务没提交而是回滚,id还是会自增。 - 临键锁
update语句条件是一个范围,如果条件不是索引,就会加表锁,如果条件是索引,那么会加一个范围的锁,范围的值是根据底层相邻节点值来确定的,左开右闭。 - 间隙锁
临键锁没有匹配成功的情况下,就是间隙锁了, - 记录锁
当用索引作为update条件时,比如ID= 2,这种精确的上锁,就是记录锁。
隔离级别和锁的关系
解决脏读、不可重复读依赖mvcc机制和锁机制。解决幻读,主要依赖于数据库对该serilizable事务的每一个操作都加了x锁。
串行化的时候,每一次读和写都应该是加了排他锁,才会有这种对同一条数据的读和写不能同时存在的机制出现。其他的隔离级别就是正常的写的时候加排他锁而已。如果想在可重复读的级别下也防止幻读,那么就要对每一次读和插入操作加一个排他锁。
上一篇: Python进程间通信之共享内存详解