欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据库锁和隔离级别

程序员文章站 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锁。
串行化的时候,每一次读和写都应该是加了排他锁,才会有这种对同一条数据的读和写不能同时存在的机制出现。其他的隔离级别就是正常的写的时候加排他锁而已。如果想在可重复读的级别下也防止幻读,那么就要对每一次读和插入操作加一个排他锁。