首先说一下什么是ACID
1 ACID
(1) A:原子性(Atomicity)
(2) C:一致性(Consistency)
(3) I:隔离性(Isolation)
(4) D:持久性(Durability)
2 Mysql的锁
- 按加锁机制分,可以分为乐观锁与悲观锁
- 按数据库系统角度来分,可分为X锁与S锁
- 按锁粒度分,可以分为表锁,行锁,页锁
- 按锁模式分,可以分为记录锁,gap锁,next-key锁,意向锁,插入意向锁
(1) S锁与X锁
show variables like '%storage_engine%';
复制

create database test;
use test;
create table a
(
id int primary key auto_increment,
money int
);
复制
S锁
lock table a read;
复制
然后.....
X锁
set autocmmmit=0;
start transaction;
lock table a write;
复制
set autocommit=0;
start transaction;
select * from a;
复制
这里是等待操作,因为一直都没释放X锁.
同样也不能再加锁,也是等待中.
回到原来那个加锁的事务,嗯,什么事也没有,正常读写.
释放锁后:
unlock table;
复制
可以看到中断时间.
mysql本身没有提供乐观锁的支持,需要自己来实现,常用的方法有版本控制和时间戳控制两种.
- 版本控制
版本控制就是为表增加一个version字段,读取数据时连同这个version字段一起读出来,之后进行更新操作,版本号加1,再将提交的数据的版本号与数据库中的版本号进行比较,若提交的数据的版本号大于数据库中的版本号才会进行更新.
举个例子,假设此时version=1,A进行操作,更新数据后version=2,与此同时B也进行操作,更新数据后version=2,A先完成操作,率先将数据库中的version设置为2,此时B提交,B的version与数据库中的version一样,不接受B的提交.
- 时间戳控制
时间戳控制与版本控制差不多,把version字段改为timestamp字段
还有一种实现方法叫CAS算法,这个作者不怎么了解,有兴趣可以自行搜索.
悲观锁
set autocommit=0;
start transaction;
复制

两个事务都这样操作,然后其中一个事务输入:
select * from a where xxx for update;
复制
在另一事务也这样输入:
这时语句会被阻塞,直到上锁的那个事务commit(解开悲观锁).
在另一事务中可以看到这个事务被阻塞了2.81s.
以下这条语句:
*** lock in share mode.
复制
也会加上悲观锁.