比如有如下操作:
(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
添加完读锁后,自己不能修改该表
注意:当前进程只能操作被锁定的表,如果想要锁定多张表,可以使用如下语句:
lock table tablename1 read, tablename2 read;
2. 添加写锁
对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其他进程的读写操作。
当前进程就可以执行读写操作。
总结:
read:所有人都只可以读,只有释放锁之后才可以写。
write:只有锁表的客户可以操作这个表,其他客户读都不能读。
缺点:阻塞。有些功能需要锁多张表,而有些表整个网站都要用,一旦锁定,会让整个网站处在阻塞状态。
三、mysql行锁的演示
InnoDB存储引擎是通过给索引上的索引项加锁来实现的,这就意味着:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB使用表锁。
语法:begin;
执行:commit;
四、锁机制在php代码里面演示
建立一个表,原始数据是100
模拟并发进行测试
比如模拟50个并发,使用apache里面有一个ab.exe工具,可以使用该工具进行模拟并发
ab.exe工具的语法:
ab.exe –n 总的请求数量 –c并发数 网页的地址;
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';