Mysql-锁

Posted 小传风

tags:

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

mysql中默认的是MyISAM数据引擎,可惜此引擎不支持事务处理,我们需要将默认的数据引擎改为InnoDB。InnoDB:用于事务处理应用程序,具有众多特性,包括ACID事务支持。

启动InnoDB引擎的方法如下:

1)关闭mysql的服务

2)修改my.ini

将default-storage-engine=INNODB前的注释(#)去掉

将skip-innodb这行注释(加上#)

3)保存后重启mysql服务;


 InnoDB实现了以下两种类型的行锁。

共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
 
 InnoDB行锁模式兼容性列表

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

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

¡  共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。

¡  排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。

InnoDB默认是行级别的锁,当有明确指定的主键时候,是行级锁。否则是表级别。

Hibernate中悲观锁的实现,是基于for update。

开启窗口:

可以看到,被另一个窗口锁住了。

for update 注意:

1.for update 仅适用于InnoDB,并且必须开启事务,在begin与commit之间才生效。

2.要测试for update的锁表情况,可以利用MySQL的Command Mode,开启二个视窗来做测试。

3.当开启一个事务进行for update的时候,另一个事务也有for update的时候会一直等着,直到第一个事务结束或等待锁时间超时

 

4.如果没查到记录会锁表,将会锁表。

查看锁情况的sql:

#查询表级锁争用情况
show status like \'c_tbl_users%\';
#获取InnoDB行锁争用情况
show status like \'innodb_row_lock%\';
#查看锁表情况
#Table_locks_immediate 指的是能够立即获得表级锁的次数 Table_locks_waited 指的是不能立即获取表级锁而需要等待的次数
show status like \'Table%\';
show status like \'%lock%\';
show open tables from chen;

 

参考:

https://www.cnblogs.com/jukan/p/5670950.html

 

以上是关于Mysql-锁的主要内容,如果未能解决你的问题,请参考以下文章

怎么给mysql加排他锁

mysql插入意向锁测试

Mysql加锁过程详解-基本知识

MySQL 进阶 锁 -- MySQL锁概述MySQL锁的分类:全局锁(数据备份)表级锁(表共享读锁表独占写锁元数据锁意向锁)行级锁(行锁间隙锁临键锁)

关于mysql 共享锁和排他锁 互斥问题?

mysql 锁机制