Fork me on GitHub

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

 

posted @ 2019-04-10 17:37  小传风  阅读(147)  评论(0编辑  收藏  举报