「MySQL高级篇」MySQL锁机制 && 事务( 四 )

Mysql 的数据库的默认隔离级别为 Repeatable read,查看方式:
show variables like 'tx_isolation';

「MySQL高级篇」MySQL锁机制 && 事务

文章插图
InnoDB 的行锁模式InnoDB 实现了以下两种类型的行锁 。
  • 共享锁(S):又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改 。
  • 排他锁(X):又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改 。
对于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(悲观锁)即手动锁定一行悲观锁和乐观锁悲观锁:事务必须排队执行 。数据锁住了,不允许并发 。(行级锁:select后面添加for update) 乐观锁:支持并发,事务也不需要排队,只不过需要一个版本号 。
「MySQL高级篇」MySQL锁机制 && 事务

文章插图
案例准备工作create table test_innodb_lock( id int(11), name varchar(16), sex varchar(1))engine = innodb default charset=utf8;insert into test_innodb_lock values(1,'100','1');insert into test_innodb_lock values(3,'3','1');insert into test_innodb_lock values(4,'400','0');insert into test_innodb_lock values(5,'500','1');insert into test_innodb_lock values(6,'600','0');insert into test_innodb_lock values(7,'700','0');insert into test_innodb_lock values(8,'800','1');insert into test_innodb_lock values(9,'900','1');insert into test_innodb_lock values(1,'200','0');create index idx_test_innodb_lock_id on test_innodb_lock(id);create index idx_test_innodb_lock_name on test_innodb_lock(name);行锁基本演示
  • 我们采用两个客户端,首先要关闭掉自动提交功能:set autocommit = 0;
    • 普通的select不加锁,没有什么影响
    • 而insert和update就不一样了,会加排它锁,其他客户端陷入阻塞状态,不能对该行(注意得两个客户端操作的是同一行,才会阻塞,因为是行锁)进行修改,直到加锁的客户端提交完事务(相当于释放锁)

「MySQL高级篇」MySQL锁机制 && 事务

文章插图

「MySQL高级篇」MySQL锁机制 && 事务

文章插图
无索引行锁升级为表锁
如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟表锁一样 。

「MySQL高级篇」MySQL锁机制 && 事务

文章插图
由于 执行更新时,name字段本来为varchar类型,我们是作为数组类型使用,存在类型转换,索引失效,最终行锁变为表锁 ;(字符串类型,在SQL语句使用的时候没有加单引号,导致索引失效,查询没有走索引,进行全表扫描,索引失效,行锁就升级为表锁)
InnoDB 行锁争用情况showstatus like 'innodb_row_lock%';
「MySQL高级篇」MySQL锁机制 && 事务

文章插图