前言

本文选自网站小册子《My家双雄:深度学习MySQL与MyBatis》:http://www.mybatis.cn/324.html。此书从数据访问存储层为入口,将延伸到分布式、高并发方面的关键技术。希望这本书能对每一个做Java Web开发的读者带来帮助,也欢迎大家提出更多的修改建议。

1、插入测试数据

drop table if exists person;

CREATE TABLE person (
id int primary key,
name VARCHAR ( 20 )
);

insert into person values(1,'A');

insert into person values(2,'B');

insert into person values(3,'C');

2、事务设置

查看是否是自动提交,如下所示:

select @@autocommit;

然后,取消SQL语句的自动提交功能

set autocommit=0;

3、Select的表锁和行锁

默认情况下,select语句是不会对数据加写锁的,也就是不会阻止写入(update delete),通过使用 for update可以对数据加写锁。

3.1 行锁

如果是按照主键查询的话,那么加的是行锁。请看下面的验证过程。

第一步:在第一个MySQL连接窗口中,执行:

begin;
select * from person where id =1 for update;

第二步:在第二个MySQL连接窗口中,执行:

update person set name='a' where id=1 ;

可以看到第二个连接的update语句一直在等待

第三步:在第三个MySQL连接窗口中,执行:

update person set name='b' where id=2;

执行结果为,瞬间更新成功:

Affected rows: 1
时间: 0.014s

说明按主键查询的话,加的是行锁。

第四步:在第一个MySQL连接窗口中,执行:

commit;

第一个连接commit之后,这时可以看到,第二个MySQL连接窗口中的update语句执行成功。

3.2 表锁

如果查询条件不是按主键查询,那么会对整个表加表锁。

第一步:在第一个MySQL连接窗口中,执行:

begin;
select * from person where name='a' for update;

第二步:在第二个MySQL连接窗口中,执行:

update person set name='c' where id=3;

可以看到,虽然 连接1中where name='a'的条件只能匹配id=1的一行,但是锁定了整张表。

第三步:在第一个MySQL连接窗口中,执行:

commit;

第一个连接commit之后,这时可以看到,第二个连接中的update语句执行成功。

4、InnoDB行锁和表锁实现方式

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

标签: none

添加新评论