mysql锁机制

mysql里面的锁的几种形式

锁机制:
当客户端操作表(记录)时,为了保证操作的隔离性(多个客户端操作不能相互影响),通过加锁来处理。
操作方面:
读锁:读操作时增加的锁,也叫共享锁,S-lock。特征是所有人都只可以读,只有释放锁之后才可以写。
写锁:写操作时增加的锁,也叫独占锁或排他锁,X-lock。特征,只有锁表的客户可以操作(读写)这个表,其他客户读都不能读。

  • 写锁只能加一个,与其他写锁和读锁互斥,
    读锁还能再加读锁.

锁定粒度(范围)
表级锁:开销小,加锁快,发生锁冲突的概率最高,并发度最低。
myisam引擎的表支持表锁,
行级锁:开销大,加锁慢,发生锁冲突的概率最低,并发度也最高。

表锁的演示

建立测试表,并添加测试数据:
create table user(
id int primary key auto_increment,
name varchar(32) not null default ‘’,
age tinyint unsigned not null default 0,
email varchar(32) not null default ‘’,
classid int not null default 1
)engine myisam charset utf8;
insert into user values(null,‘xiaogang’,12,‘gang@sohu.com’,4),
(null,‘xiaohong’,13,‘hong@sohu.com’,2),
(null,‘xiaolong’,31,‘long@sohu.com’,2),
(null,‘xiaofeng’,22,‘feng@sohu.com’,3),
(null,‘xiaogui’,42,‘gui@sohu.com’,3);

添加读锁的语法:lock table table_name read|write (读锁和写锁)
释放锁的语法:unlock tables

(1)添加读锁

语法:lock table table_name read;

读锁期间,没释放锁之前不能进行写操作。
在这里插入图片描述
第二个用户登录,也能执行查询操作, 但不能做修改操作。 直接被阻塞掉进行等待。
在这里插入图片描述
添加表锁定后, 针对锁表的用户,只能操作锁定的表,不能操作没有锁定的表。
在这里插入图片描述
开始释放锁
释放锁语法:unlock tables;
在这里插入图片描述
释放锁之后, 另一个用户, 也可以进行修改操作了。
在这里插入图片描述

(2)添加写锁

只有锁表的用户可以进行读写操作,其他用户不行。
当前锁表用户可读可写。
在这里插入图片描述
第二用户直接进入阻塞,等待。
在这里插入图片描述

行锁的演示

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

      行锁语法 
      begin;//添加行锁
      执行语句; 
      commit; //释放锁
    
  • 当第一个用户开启行锁的时候, 第一个用户可以对其进行查询和修改…
    在这里插入图片描述

  • 第二个用户只能对其进行全部查询或者查询同一行只能获取未修改前的数据. 修改同一行会进入阻塞等待.
    在这里插入图片描述

  • 但修改其他行是不会受到影响的.
    在这里插入图片描述

  • 第一个用户读写操作完毕后, 使用commit来释放锁.在这里插入图片描述

  • 之后第二个用户就可以正常对原先的那行进行操作了.

通过php代码实现锁机制(模拟并发)

apache\bin 目录下有个ab.exe 是用来模拟多个并发测试的.
语法: ab -n 总的请求数 -c 并发数 url地址
在这里插入图片描述

  • 不加锁
    php代码中不添加锁, 其中定有几个同时发生的. 必然会导致数据不准确.
    加粗样式
  • 加锁
    加上写锁后, 数据就准确了. (因为在一个用户还没进行完的时候, 其他操作也没办法做任何的读写操作);
    在这里插入图片描述
<?php
	$pdo = new PDO('mysql:host=localhost;dbname=testdemo','root','root');
	$pdo->exec('set names utf8');
	//添加写锁
	$pdo->exec('lock table a write');
	$res = $pdo->query('select id from a');
	$info = $res->fetch(PDO::FETCH_ASSOC);
	$id = $info['id'];
	//给id加1
	$id += 1;
	
	//把更改后的值再写入数据库
	$pdo->exec('update a set id='.$id);
	$pdo->exec('unlock tables');

虽然现在问题解决了, 但是如果碰到比如网站购物, 这样直接把一行记录锁死,就不是很好了.

文件锁flock()

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test','root','root');
$pdo->exec('set names utf8');

$fn = fopen("./lock.txt",'w');
//LOCK_EX 写锁
flock($fn,LOCK_EX);
$res=$pdo->query('select id from a');
$info=$res->fetch(PDO::FETCH_ASSOC);
$id=$info['id'];

$id += 1;

$pdo->exec("update a set id={$id}");
//关闭锁
flock($fn,LOCK_UN);

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值