mysql的封锁机制以及读锁和写锁的区别

 

咱们在开发中也许都有感觉到,数据库的并发操做会带来许多问题,好比丢失更新、不可重复读、读脏数据(幽灵数据)等等,常见的好比自动售票系统,站点一、2同时读出剩余的票数n张,站点1售出一张票,并将n-1写入数据库,站点2也售出一张票并将n-1写入数据库,可是咱们都知道,应剩余n-2张票,这就是典型的丢失数据更新的实例。为避免该类问题的产生,咱们采用了封锁机制,简单点就是当一个线程要对数据库进行相关操做时,先给数据库加上适当的锁,以此来避免其余线程对数据库进行操做而带来的干扰。
并发操做之因此产生错误,是由于不一样线程并发执行事务互相干扰形成的。因此咱们要对事务的并发操做进行控制,即并发控制。通常DBMS进行并发控制的方法是封锁机制和事务机制。
封锁就是对数据表、数据行等操做以前,先向系统请求对其加锁,说通俗点就是操做以前先声明权限。
封锁的周期(环节):申请加锁、得到锁权限、释放锁权限
最基本的封锁类型有两种:排它锁(Exclusive Locks,X锁)和共享锁(Share Locks,S锁)。sql

  • 排它锁也称独占锁、写锁或X锁,若sessionA得到某数据表的排他锁权限,那么sessionA只能对该表进行读取或修改,其余session既不能读取也不能修改该表,更不能对该表加任何类型的锁,直到sessionA释放排它锁权限。加锁方式:lock tables tablename write;操做以下:
    sessionA:
    这里写图片描述
    sessionB:
    这里写图片描述
    从上图操做能够看出sessionA得到ha表排它锁权限之后sessionB执行访问ha表操做之后并没用显示ha数据而是在等待sessionA释放锁权限。数据库

  • 共享锁也称读锁或S锁,若sessionA得到某数据表的共享锁权限,那么任何session(包括sessionA)只能对该表进行读取,不能修改该表,sessionA能够继续对该数据表加X锁,其余session能够对该数据表继续加S锁但不能加X锁,直到sessionA释放共享锁权限。加锁方式:set tables tablename read;操做以下:
    sessionA:
    这里写图片描述
    sessionB:
    这里写图片描述
    从上图操做能够看出,sessionA得到ha表共享锁权限之后,sessionA和sessionB均可以访问ha表,可是当sessionA想更改ha表时直接报错(ERROR 1099 (HY000): Table ‘ha’ was locked with a READ lock and can’t be updated ha表有一个共享锁不能被修改),sessionB更改ha表时并无显示修改为功,而是在等待sessionA释放共享锁权限。session

  • 注意,在sessionA同时得到某数据表的S和X锁权限时,sessionA只能select该数据表,其余session将不能对该表进行任何操做,包括select、update、drop、delete、lock等等,直到sessionA释放相关锁权限。并发

 

 

表锁的加锁/解锁方式

 

MyISAM 在执行查询语句(SELECT)前,会自动给涉及的全部表加读锁,在执行更新操做 (UPDATEDELETEINSERT 等)前,会自动给涉及的表加写锁,这个过程并不须要用户干预,所以,用户通常不须要直接用LOCK TABLE命令给MyISAM表显式加锁。ide

若是用户想要显示的加锁可使用如下命令:线程

 
   
  1.  
    锁定表:LOCKTABLES tbl_name { READ | WRITE },[ tbl_name {READ| WRITE},…]
  2.  
     
  3.  
    解锁表:UNLOCKTABLES
  • 1
  • 2
  • 3
 

在用 LOCK TABLES 给表显式加表锁时,必须同时取得全部涉及到表的锁。code

在执行 LOCK TABLES 后,只能访问显式加锁的这些表,不能访问未加锁的表;blog

若是加的是读锁,那么只能执行查询操做,而不能执行更新操做。图片

在自动加锁的状况下也基本如此,MyISAM 老是一次得到 SQL 语句所须要的所有锁。这也正是 MyISAM 表不会出现死锁(Deadlock Free)的缘由。事务

相关文章
相关标签/搜索