比如有如下操作:

(1)从数据库中取出id的值

(2)把这个值加1

(3)在把该值存回到数据库

假如该id初始值为100,如果有两个用户同时操作。

第一个用户:

id=100
100+1
id=101

第二个用户:

id=100
100+1
id=101

经过两个用户操作数据库,值应该为102才对。

假如是一个购物网站,库存还剩1件,有两个用户同时购买1件商品。

mysql中的锁:同一个时间只有一个人可以获得锁,其他人只能阻塞等待第一个人释放锁。

第一个用户:

get lock(获得锁)
id=100
100+1
id=101
unlock(释放锁)

第二个用户:

waiting...
waiting...
waiting...
get lock(获得锁)
id+1
id=102
unlock(释放锁)

一、mysql的锁有以下两种形式

表级锁:开销小,加锁快,发生锁冲突的概率最高,并发度最低。MyISAM引擎属于这种类型。

行级锁:开销大,加锁慢,发生锁冲突的概率最低,并发度也最高。InnoDB属于这种类型。

二、mysql表锁的演示

1. 添加读锁

对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的请求,但会阻塞对同一表的请求。只有当读锁释放后,才会执行其他进程的操作。

添加读锁语法:lock table 表名 read
释放锁的语法:unlock tables

mysql 账号锁 mysql 锁定用户_mysql

添加完读锁后,自己不能修改该表

mysql 账号锁 mysql 锁定用户_mysql_02

注意:当前进程只能操作被锁定的表,如果想要锁定多张表,可以使用如下语句:

lock table tablename1 read, tablename2 read;

2. 添加写锁

对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其他进程的读写操作。

mysql 账号锁 mysql 锁定用户_mysql 账号锁_03

当前进程就可以执行读写操作。

mysql 账号锁 mysql 锁定用户_读锁_04

总结:

read:所有人都只可以读,只有释放锁之后才可以写。

write:只有锁表的客户可以操作这个表,其他客户读都不能读。

缺点:阻塞。有些功能需要锁多张表,而有些表整个网站都要用,一旦锁定,会让整个网站处在阻塞状态。

三、mysql行锁的演示

InnoDB存储引擎是通过给索引上的索引项加锁来实现的,这就意味着:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB使用表锁。

语法:begin;
执行:commit;

mysql 账号锁 mysql 锁定用户_mysql 账号锁_05

四、锁机制在php代码里面演示

建立一个表,原始数据是100

mysql 账号锁 mysql 锁定用户_mysql 账号锁_06

模拟并发进行测试

比如模拟50个并发,使用apache里面有一个ab.exe工具,可以使用该工具进行模拟并发

mysql 账号锁 mysql 锁定用户_sql_07

ab.exe工具的语法:

ab.exe –n 总的请求数量 –c并发数 网页的地址;

mysql 账号锁 mysql 锁定用户_mysql_08

php代码:

$conn = mysql_connect('localhost','root','123');
mysql_query('use test');
mysql_query('set names utf8');
mysql_query('lock table t8 write');
$sql = 'select id from t8';
$res = mysql_query($sql);
$row = mysql_fetch_assoc($res);
$id = $row['id']+1;
$sql = 'update t8 set id = '.$id;
mysql_query($sql);
mysql_query('unlock tables');
echo 'ok';