InnoDB中的B+Tree和MVCC

最近在公司做了一个分享,主题是InnoDB中的B+Tree的使用,以及InnoDB的MVCC机制的实现,PPT链接见下
B+Tree_MVCC
PPT本身内容不多,大部分还在演示者视图的备注中。而且分享过程中有一部分用了网易何登成大神的PPT,他的PPT链接在我的PPT中也有给出,有兴趣可以去下载,我这儿就不贴链接了

[php+mysql]关于防止并发的小探究

其实是上个月的事儿,草稿在wp存了好久,今天终于有时间写完

有这样一个需求,用户用所得到的积分兑换礼品,于是我写了如下代码

[cc lang=’php’ ]
public function assignGift($money){
//判断钱数是否足够
if($this->getMoney()>=$money){
$this->saveGift();
//扣钱
$this->addMoney(-$money);
return true;
}
return false;
}[/cc]

于是测试工程师跟我说,我对这个操作做了1000次的并发,就可以用1份的积分兑换一大堆礼物,之后钱变成负数

我‘哦’了一声,改了一下

[cc lang=’php’ ]
public function assignGift($money){
//判断钱数是否足够
if($this->getMoney()>=$money){
//扣钱
$this->addMoney(-$money);
$this->saveGift();
return true;
}
return false;
}[/cc]

这个修改简直是弱爆了。显然结果是测试工程师又来跟我说,还是不行。

问题在哪儿呢,我们来看一下getMoney和addMoney里面写的什么
[cc lang=’php’ ]
public function getMoney(){
$money = $mysql->query(
‘SELECT Money
FROM user
WHERE UserId = ‘. $this->userId);
return $money[‘Money’];
}
public function addMoney($money){
$money = $mysql->query(
“UPDATE user
SET Money = Money+$money
WHERE UserId =”. $this->userId);
return true;
}[/cc]
问题来了吧(哪儿呢)。

在大量并发到来的时候,每个并发都先执行getMoney中的query,然后执行addMoney去减积分。执行顺序成了这样

process 1 :getMoney();

process n :getMoney();
process 1 :addMoney();

process n :addMoney();

于是就杯具了。

跟大家讨论了下,打算在用户提交请求的时候,顺便提交个token,验证后销毁。由于某些原因,服务器不能写session,所以用memcache替代

由于某些原因,服务器不能写session,所以用memcache替代
[cc lang=’php’ ]
public function assignGift($money){
if($_GET[‘token’] != $memcache->get(‘token’))
return false;
//清除缓存
$memcache->clear(‘token’);
//判断并扣钱
if($this->getMoney()>=$money){
……
}
return false;
}[/cc]
这次测试,并发时命中率低了不少,但是还是有额外命中的,肿么回事?

因为memcache的get和clear也要时间(尤其是实际环境memcache是分多台服务器,不在本地)

所以木有办法,最后加了一层mysql的事务解决(innoDB)

我以前没听说过还有事务这种东西,查了一下(链接自己查去= =)

简单说,就是在提交查询的时候加一条行锁,在整个事务流程完成前,不会再进行新的查询

[cc lang=’php’ ]
public function assignGift($money){
$mysql->query(
‘SET AUTOCOMMIT = 0 ;
START TRANSACTION ;’);
……
//判断并扣钱
if($this->getMoney()>=$money){
……
$mysql->query(
‘COMMIT ;
SET AUTOCOMMIT = 1;’);
return true;
}
$mysql->query(‘SET AUTOCOMMIT = 1;’);
return false;
}
public function getMoney(){
$money = $mysql->query(
‘SELECT Money FROM user
WHERE UserId = ‘. $this->userId
. ‘FOR UPDATE’);
return $money[‘Money’];
}[/cc]

另外求好用的wp贴代码的插件,codecolorer不好用,不能调整大小,不能设置临时的高亮(或许是我没去看源代码= =)

再另求好看的贴图的插件……

[Javascript]自动补完框的小探究

之前和同事做项目的时候,有一个拉取好友的框,可以在输入框中输入字符来过滤好友。过滤的功能我在后端完成了,告诉前端说,你去ajax带个参数去拉json数据就ok。过了一会儿,前段同学跟我说他对那个框做了onkeydown的检测blabla。我问他直接onchange的时候把框内容ajax过去不就行了么。于是林哥跟我说不行,这样请求太频繁。

在我的印象里面,百度和谷歌的自动补完都是很快速的,不像是有间隔啊。于是我看了一下它们的post

咦怎么发成相册了,好吧相册就相册

百度的post“几乎”是变化就发送,尤其在中文情况下,输入速度远赶不上请求速度。请求大概100ms就返回了,也就是输入速度要达到600字/min才能赶上发送速度。

对中文虽然不可能,但是英文还是有戏的。输入英文的时候,并不是每输入一个字母就request,有一个小延迟,以我的打字速度,最多没超过3个字母就request了。不得不说服务器真给力

Google有些不同,首先是请求频率低一些,同样的英文,大概4、5个字母request一次。速度慢一些,因为众所周知的原因,木有办法呀。

而且Google的request是可以cancel的,新的request会导致以前的request被cancel掉,(大概减轻了压力)

至于百度为啥没这么做呢,我猜,百度来不及cancel就已经request ok了………………

PS.排版神马的,等我有空研究下吧

PPS.@AsterOcclu有木有什么好的展示照片的插件,我之前好想看你blog上有

PPPS.推荐下http://water7.tk

PPPPS.在google测试补完的时候,我是用“啊啊啊”测试的……结果呢……

Welcome Back

首先欢迎大家光临新站

虽然域名还是 http://loland.tk 但是这次彻底在墙外呆着了,随时有被校长大人封掉的危险

不过我应该不会发什么敏感内容就是了

最近挺忙(一直挺忙),所以这个站就暂时是这样,基本的wp,加上随手选的模板

等以后有时间了(?)会逐渐加上一些奇奇怪怪的东西

毕竟是VPS,不能就当个blog用了……

作为blog来说,这里大概会更新一些技术贴,吐槽贴,一些懒得在SNS或者微博上发的东西

但是更新频率果然保证不了

至于其他功能,看心情,10G的空间不能浪费不是

————————————————————————————

其实我把日志导入到这里来的时候,看到一篇隐藏的文章。

整个人都Crash掉了。Crash。