首先说一下什么是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.
也会加上悲观锁.




