mysql中的锁的相关知识

Posted smalljunjun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql中的锁的相关知识相关的知识,希望对你有一定的参考价值。

数据库锁:数据库锁出现的原因是为了处理并发问题。

并发控制一般采用三种方法,分别是乐观锁和悲观锁以及时间戳

乐观锁认为一个用户读数据的时候,别人不会去写自己所读的数据,就是不做任何操作。悲观锁就刚好相反,觉得自己读数据库的时候,别人可能刚好在写自己刚读的数据,其实就是持一种比较保守的态度,悲观锁就是在读取数据的时候,为了不让别人修改自己读取的数据,就会先对自己读取的数据加锁,只有自己把数据读完了,才允许别人修改那部分数据,或者反过来说,就是自己修改某条数据的时候,不允许别人读取该数据,只有等自己的整个事务提交了,才释放自己加上的锁,才允许其他用户访问那部分数据。悲观锁所说的加“锁”。

悲观锁分为:

读锁/共享锁:共享的锁,多个客户端可以同时读取一个资源,互补干扰。
写锁/排它锁:一个锁会阻塞其他的写锁和读锁,确保一个时刻只有一个客户端对通过一个数据进行修改写入。

时间戳就是在数据库表中单独加一列时间戳,比如“TimeStamp”,每次读出来的时候,把该字段也读出来,当写回去的时候,把该字段加1,提交之前 ,跟数据库的该字段比较一次,如果比数据库的值大的话,就允许保存,否则不允许保存。

 

表锁 是开销比较小的策略,会锁定整张表。MyISAM和InnoDB都支持表级锁定。用户对表进行写操作,需要先获得锁,并且会阻塞用户对该表的所有读操作。 数据库中对表进行修改,如alter table会使用到表锁,会锁定整张表,因此此类操作在数据库中应该谨慎使用。

行锁 行锁可以高效的支持并发,当然锁开销也是最大。mysql的InnoDB引擎中实现了行锁,在用户写数据时,只锁定需要操作的数据行,相比于表锁并发度更好。

InnoDB支持事务,

事务是数据库区别于文件系统的额重要特性之一。事务符合ACID特性。原子性:原子性是指数据库事务是不可分割的工作单位。只有数据库事务中的所有数据库操作执行都成功,才算整个事务成功。如果事务中的任何一个SQL语句执行失败,已经执行的SQL语句也必须撤销,数据库状态退回到执行事务前的状态。

一致性:事务执行之前和之后,数据库的完整性约束没有被破坏。

隔离性:一个事物的影响在它提交前对其他事务不可见(通过锁来实现)

持久性:事务一旦提交,其结果就是永久性的。

原子性,一致性,持久性通过redo,undo来完成。

 

并发事务所带来的问题:

  • 更新丢失(Lost Update):当两个事务T1和T2读入同一数据做修改并发执行时,T2把T1或T1把T2的修改结果覆盖掉,造成数据的丢失更新问题,导致数据的不一致。
  • 脏读(Dirty Reads):事务T1更新了数据R,事务T2读取了更新后的数据R,事务T1由于某种原因被撤销,恢复数据R。这样T2读取的数据和数据库中内容不一样。
  • 不可重复读(Non-Repeatable Reads):一个事务对同一行数据读取了两次,结果不同。
  • (1)事务T1读取了数据R,事务T2读取并更新了R,当事务再读取R进行核对时,两次读取的值不一样。
  • (2)事务操作过程中进行了两次查询,第二次查询的结果包含了第一次查询中未出现的数据或缺少了第一次查询的数据,这种情况称为幻读。

间隙锁(Next-Key锁)

    当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制不是所谓的间隙锁(Next-Key锁)。
    举例来说,假如emp表中只有101条记录,其empid的值分别是1,2,...,100,101,下面的SQL:
SELECT * FROM emp WHERE empid > 100 FOR UPDATE
    是一个范围条件的检索,InnoDB不仅会对符合条件的empid值为101的记录加锁,也会对empid大于101(这些记录并不存在)的“间隙”加锁。
    InnoDB使用间隙锁的目的,一方面是为了防止幻读,以满足相关隔离级别的要求,对于上面的例子,要是不使用间隙锁,如果其他事务插入了empid大于100的任何记录,那么本事务如果再次执行上述语句,就会发生幻读;另一方面,是为了满足其恢复和复制的需要。有关其恢复和复制对机制的影响,以及不同隔离级别下InnoDB使用间隙锁的情况。
    很显然,在使用范围条件检索并锁定记录时,InnoDB这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。因此,在实际开发中,尤其是并发插入比较多的应用,我们要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件。

死锁

两个用户分别锁定一个资源,之后双方又都等待双方释放所锁定的资源,就产生一个锁定请求环,从而出现死锁。死锁往往出现在行级锁中。

如何解决死锁?

在InnoDB的事务管理和锁定机制中,有专门用于检测死锁的机制。当检测当死锁时,InnoDB会选择产生死锁的两个事务中的较小的一个完成回滚。

 


以上是关于mysql中的锁的相关知识的主要内容,如果未能解决你的问题,请参考以下文章

Mysql中的锁

Mysql中的锁

通过12334说说InnoDB里面的锁

通过12334说说InnoDB里面的锁

java中锁的概念/介绍

Mysql中的锁