MySQL锁

时间:2014-06-15 22:14:44   收藏:0   阅读:373

MySQL锁

不同的存储引擎支持不同的锁:

3种锁类型:


1、MyISAM表锁

1)查询表锁争用情况

show status like ‘table%‘; --Table_locks_waited值比较高则说明存在严重的表锁争用

2)表锁的锁模式

3)表锁兼容性
     bubuko.com,布布扣

4)如何加表锁

隐式加锁:MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行更新(增、删、改等)操作前,会自动给涉及的表加写锁。
显示加锁:(只能访问显示加锁的这些表,不能访问未加锁的表)

  •    lock table tablename1 read/write [local], tablename2 read/write [local];
  •    unlock tables;
  •    lock table tablename as t; --当表存在别名时,同时个别名也要加锁

5)并发插入控制

变量concurrent_insert控制并发插入行为:

  • 0:不允许插入
  • 1:如果myisam表中没有空洞(即表的中间没有被删除的行),允许在一个进程读表的同时,另一个进程从表尾插入记录。默认
  • 2:无论myisam表中有没有空洞,都允许在表尾并发插入记录

6)MyISAM锁调度

     bubuko.com,布布扣
    相关参数:max_write_lock_count

 

2、InnoDB行锁

1)InnoDB相对MyISAM最大的不同

2)并发事务处理带来的问题

例如:
  张三的工资为5000,事务A中把他的工资改为8000,但事务A尚未提交。
  与此同时,
  事务B正在读取张三的工资,读取到张三的工资为8000。
  随后,
  事务A发生异常,而回滚了事务。张三的工资又回滚为5000。
  最后,
  事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。

例如:
  在事务A中,读取到张三的工资为5000,操作没有完成,事务还没提交。
  与此同时,
  事务B把张三的工资改为8000,并提交了事务。
  随后,
  在事务A中,再次读取张三的工资,此时工资变为8000。在一个事务中前后两次读取的结果并不致,导致了不可重复读。

例如:
  目前工资为5000的员工有10人,事务A读取所有工资为5000的人数为10人。
  此时,
  事务B插入一条工资也为5000的记录。
  这是,事务A再次读取工资为5000的员工,记录为11人。此时产生了幻读。

理解:

  • 不可重复读的重点是修改:同样的条件,你读取过的数据,再次读取出来发现值不一样了
  • 幻读的重点在于新增或者删除:同样的条件,第1次和第2次读出来的记录数不一样

      从总的结果来看, 似乎两者都表现为两次读取的结果不一致。但如果你从控制的角度来看, 两者的区别就比较大:

  • 对于前者, 只需要锁住满足条件的记录
  • 对于后者, 要锁住满足条件及其相近的记录


3)事务隔离级别(ISO/ANSI SQL92定义)

      bubuko.com,布布扣
     注:不同数据库实现不一致

4)获取innodb行锁争用情况

show stauts like ‘innodb%‘;

5)InnoDB行锁模式

  • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
  • 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

      为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁:

  • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
  • 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

6)InnoDB行锁模式兼容性列表
     bubuko.com,布布扣

     如果一个事务请求的锁模式与当前的锁兼容,InnoDB就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。

     意向锁是InnoDB自动加的,不需用户干预。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁:

7)InnoDB行锁实现方式

     InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着只有通过索引条件检索数据,InnoDB 才使用行级锁,否则,InnoDB将使用表锁!在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。

8)间隙锁(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使用间隙锁的目的:

    在使用范围条件检索并锁定记录时,InnoDB这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。因此,在实际应用开发中,尤其是并发插入比较多的应用, 要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件。

     InnoDB除了通过范围条件加锁时使用间隙锁外,如果使用相等条件请求给一个不存在的记录加锁,InnoDB也会使用间隙锁!

9)什么时候使用表锁

对于InnoDB表,在绝大部分情况下都应该使用行级锁,因为事务和行锁往往是我们之所以选择InnoDB表的理由。但在个别特殊事务中,也可以考虑使用表级锁:

 

      当然,应用中这两种事务不能太多,否则,就应该考虑使用MyISAM表了。

在InnoDB下,使用表锁要注意以下两点。

SET AUTOCOMMIT=0;           --如果需要写表t1并从表t2读
LOCK TABLES t1 WRITE, t2 READ, ...;
[do something with tables t1 and t2 here];
COMMIT;
UNLOCK TABLES;

10)死锁

 (定义:两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去)

    MyISAM表锁是deadlock free的,这是因为MyISAM总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁。但在InnoDB中,除单个SQL组成的事务外,锁是逐步获得的,这就决定了在InnoDB中发生死锁是可能的。

    发生死锁后,InnoDB一般都能自动检测到,并使一个事务释放锁并回退,另一个事务获得锁,继续完成事务。但在涉及外部锁,或涉及表锁的情况下,InnoDB并不能完全自动检测到死锁,这需要通过设置锁等待超时参数innodb_lock_wait_timeout来解决。这个参数不是只用来解决死锁问题,在并发访问比较高的情况下,如果大量事务因无法立即获得所需的锁而挂起,会占用大量计算机资源,造成严重性能问题,甚至拖跨数据库。通过设置合适的锁等待超时阈值,可以避免这种情况发生。

    通常来说,死锁都是应用设计的问题,通过调整业务流程、数据库对象设计、事务大小,以及访问数据库的SQL语句,绝大部分死锁都可以避免:

      如果出现死锁,可以用:show engine innodb status\G 命令来确定最后一个死锁产生的原因。

其他mysql锁相关命令

 1)show processlist;

      show processlist显示哪些线程正在运行。您也可以使用mysqladmin processlist语句得到此信息。如果您有SUPER权限,您可以看到所有线程。否则,您只能看到您自己的线程(也就是,与您正在使用的MySQL账户相关的线程)。如果有线程在update或者insert 某个表,此时进程的status为updating 或者 sending data。

     show processlist;只列出前100条,如果想全列出请使用:show full processlist;

2)show open tables;

    这条命令能够查看当前有那些表是打开的。In_use列表示有多少线程正在使用某张表,Name_locked表示表名是否被锁,这一般发生在Drop或Rename命令操作这张表时。所以这条命令不能帮助解答我们常见的问题:当前某张表是否有死锁,谁拥有表上的这个锁等。

 

 资料:

 

MySQL锁,布布扣,bubuko.com

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!