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

MySQL中的锁

程序员文章站 2022-07-09 21:02:09
数据库中有很多锁,但锁是为了解决什么问题?具体都有哪些锁呢?这篇文章简单对MySQL中的锁做了一个总结 一、锁的设计是为了解决什么问题? 当多用户读写数据的时候,就有可能会出现同一时刻对同一条数据的读写,如果是大家都只是对同一条数据进行读,无所谓,大家读到数据都是一样的,但当有的想要读取数据,有的想 ......

数据库中有很多锁,但锁是为了解决什么问题?具体都有哪些锁呢?这篇文章简单对mysql中的锁做了一个总结

一、锁的设计是为了解决什么问题?

当多用户读写数据的时候,就有可能会出现同一时刻对同一条数据的读写,如果是大家都只是对同一条数据进行读,无所谓,大家读到数据都是一样的,但当有的想要读取数据,有的想要修改数据的时候,或者大家都想要修改数据的时候就会出现问题。比如有一行数据现在值是5,同一时刻有两个用户都想要修改这行数据,用户1和用户2此刻读到的数据都是5,用户1在数据5的基础上加了1变成6,并将6存进数据库里面,用户2在数据5的基础上加了2变成7,然后将7存进了数据库里面,这里面就出现了一个问题,用户1的修改丢失了。

所以数据库为了解决用户和共享数据的出现的问题,引入了锁。当用户1想要修改数据时,先必须获取锁,然后在修改,用户2想要修改数据时,也要先获取锁,但锁被用户1获取了,他只能等用户1修改完,释放锁后,才能继续修改数据。

根据锁的类型可以分为读锁,写锁

根据锁的范围可以分为全局锁,表级锁,行锁

二、读锁,写锁

当我们需要对一个数据进行读取的时候,就需要获取读锁,当我们对一个数据进行修改的时候,就需要获取写锁

读锁之间不互斥,当对一个数据加了读锁后,还可以对它继续加读锁,不能添加写锁

写锁与读锁之间,写锁与写锁之间互斥,当对一个数据加了写锁后,不能继续添加其他锁了,必须要等待写锁释放

三、全局锁

全局锁,会锁住整个数据库,整个数据库不可写入数据,不可修改数据表结构,只能读取数据,这样的话,就保证了整个数据库只读,最典型的应用就是全局备份数据,备份数据期间,我们不希望有数据能写入数据库中,不然后有可能备份后的数据是不完整的数据。

比如有两个表中的数据是关联的,第一张表a,第二张表b,表a增加一条记录时,表b就会记录一条关于表a操作的记录

现在在我们备份的时候,不加全局锁,考虑下面的情况

时刻1. 备份表a

时刻2. 表a插入了一条记录,表b也要记录一条

时刻3. 备份表b

这样的顺序下来,备份后的数据表b中多记录了一次操作

我们可以通过加全局锁,来实现在备份过程中,只能读取数据,无法修改数据,来保证备份后数据的一致性

四、表级锁

表级锁可分为两种,一种是表锁,一种元数据锁(mdl)

mdl锁不需要显示使用,在访问表的时候会自动加上

当要读取一个表时,要获取mdl读锁,当要修改一个表的结构的时候,就要获取mdl写锁。mdl主要是为了防止ddl和dml并发的冲突。

表锁锁一整表,锁的范围还是太大了。

五、行锁

行锁时目前最细粒度的锁了,只有innodb引擎支持,myisam引擎只支持到表级锁

innodb事务开启后,行锁是需要的时候才会加上,但不是不需要了就会立即释放行锁,而是等整个事务提交之后,才会释放行锁。这个就是mysql的两阶段锁协议。

有这么一种场景,一个事务执行中,要执行很多条语句,其中有一条语句会更新同一行数据。当多个事务并发的时候,必定会争夺同一行数据的锁,当一个事务持有锁的时候,其他事务就必须等待。在这种场景下,我们该如何设计语句的执行顺序,让等待的时间最少?

我们已经知道了两阶段锁协议,锁在事务结束的时候才会释放,所以,把更新同一行数据的语句越往后放,等待的时间就会越少。

innodb已经有了行锁,但还是不能够保证并发事务的正确性,为此,innodb引入了新的锁,叫间隙锁,当要更新数据时,在一行行扫描加锁的过程中,不仅会加行锁,还会添加间隙锁,也就数据行之间的锁。

六、总结

mysql中的锁机制就是为了解决共享资源的问题,为了从不同程度控制资源的读写,相应的引入了全局锁,表级锁,行锁,以及不同锁类型。