Learn by Making Notes.
Share by Posting Notes.
Mon, Apr 13, 2015
数据库的锁/加锁策略(lock/locking)和数据库的隔离级别(isolation level)不是同一个 概念(虽然有关联)。隔离级别主要关心的是一个transaction对其它transaction修改的可见性。 锁/加锁策略主要关心如何控制多个transaction对某个资源(row or page)的并发访问。
加锁策略 Locking
数据库有两种加锁的策略,optimistic locking以及pessimistic locking。它们也经常被 翻译成或者叫成“乐观锁”和“悲观锁”。实际上,不是说一个锁有”乐观“和”悲观“之分;而是说在使用 锁的”态度“上有”乐观“和”悲观“之分。下面可以看到optimistic locking根本不会使用锁。
悲观的加锁策略 Pessimistic Locking
通过使用锁(不同类型的锁)来防止数据(row or page)被其它的用户修改。用户A在执行操作(比如读或者 更新操作)前加上锁,如果其它用户对数据的操作和锁有冲突,那么在用户A释放锁之前,其它用户的这些 操作将不能执行。
因为用户在执行操作前不管未来是否会有冲突发生总是加锁,所以叫pessimistic locking。这种加锁 策略适用于数据竞争(data contention)发生的概率很高的情景。因为在这种情景下,如果采用 乐观的加锁策略,transaction的回滚概率高,使得回滚的总开销比加锁带来的开销还大。
乐观的加锁策略 Optimistic Locking
采用optimistic locking时,用户在读数据时不会使用锁。当用户A更新数据时,数据库会检查其它 用户有没有修改过这份数据(比如通过对比内存中用户A的数据的版本信息和更新时数据库中的版本 信息)。如果用户A要更新的数据已经被其它用户更新过,数据库会报错。通常用户收到错误消息后会 回滚并重试。
为什么是乐观的?因为采用这种策略时,用户倾向于认为数据之间是没有竞争的。这种策略适用于数据 竞争很少的场景。这种场景下,偶尔的回滚(并重试)带来的开销要低于加锁防止冲突的开销。
不同的锁
如果决定了使用pessimistic locking,那么有不同类型的锁可供使用。这篇微软的文档讲了 SQL Server提供的不同类型的锁。其它的数据库应该也会提供类似的锁。
阅读更多…Thu, Apr 09, 2015
今天在使用git时遇到一个“奇怪”的问题。操作系统是Windows 7,分别在Git Bash和cygwin里运行
git status
命令,输出的结果相差非常大。cygwin下运行该命令提示有大量的文件被修改了(“Changes
not staged for commit”),但是实际上我并没有对这些文件做过任何的改动。
Google了一下后,发现是换行符导致的问题😔。Unix,Linux和OS X用LF
表示换行(new line),而
Windows用CRLF
表示换行。git在checkout一个文件时可以按照以下方式处理换行符:
- 把文本文件中的换行符统一转换成
LF
- 把文本文件中的换行符统一转换成
CRLF
- 把文本文件中的换行符换成本地操作系统中的换行符
- 认为这个文件是二进制文件,不做任何处理
在我工作的这个仓库(repository)里,很多文件的换行符策略被配置成“转换为本地系统的换行符”。
我是在Windows上用Git Bash克隆仓库的,所以这些文件的换行符是CRLF
。当我在cygwin里运行
git status
时,git以为自己运行在Unix环境里😔,所以它认为这些文件的换行符从LF
被换成了
CRLF
。
More Details
如果我们的git仓库永远都是工作在同一种操作系统下,那么换行符相关的问题可能不会困扰我们。但是 实际上我们常常会有意无意地跨操作系统进行工作。比如来自不同的操作系统的文件可以通过Dropbox、浏览器 、压缩包等途径进入到我们的git仓库。
git有自己“数据库”(.git目录)存着所有的commit;也有“working directory”,也就是当前的工作
目录。为了解决换行符问题,首先最好是让git在写“数据库”时使用LF
作为换行符。
下面介绍一下git中换行符相关的一些设置。
阅读更多…Wed, Mar 18, 2015
🦄 🤔 😈
Emoji是unicode的一部分,UTF-8编码也是可以表示Emoji的。
比如😁对应的unicode是U+1F601
,对应的UTF-8编码是\xF0\x9F\x98\x81
。所以我们可以在UTF-8编码存储的
文本中(比如HTML文件)保存Emoji表情。
显示文本中的emoji
我们需要一种字体来显示以UTF-8编码的Emoji表情。通常,一种字体不能显示所有的UTF-8编码。不能显示时,通常
会显示成一个“小方块”。在较新的OS X系统上,Apple Color Emoji
字体可以显示Emoji表情。在较新的Windows上
(比如Windows 7/8),Segoe UI Symbol
字体可以显示黑白的Emoji表情。Windows 8上可以用
Segoe UI Emoji
字体来显示彩色的表情。
显示网页上的emoji
对于网页元素,我们可以通过CSS属性font-family
来指定(一系列)字体。比如,
font-family: Gill Sans Extrabold, sans-serif;
排在前面的字体优先级较后面的高。如果用户电脑上没有安装优先级高的字体,那么根据优先级依次尝试后续的 字体。如果所有的字体都没有找到,那么使用浏览器提供的字体(Initial value depends on user agent)。 在OS X上,如果font-family中没有指定可以显示Emoji的字体,Safari是可以正常显示Emoji的,而Chrome则不能。 这是因为这两个浏览器提供的默认字体有区别。
为了在Windows和OS X上都能显示Emoji表情,可以向font-family里加入Apple Color Emoji
,Segoe UI Emoji
,
和Segoe UI Symbol
字体。比如,
font-family: Helvetica, arial, freesans, clean, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
效果如下,
Chrome on Windows 7
IE 11 on Windows 7
Safari on OS X
Chrome on OS X
在OS X下输入emoji
OS X自带的中文输入法可以直接输入表情符号,比如,
输入法可以输入的emoji有限(毕竟你不太可能记住所有emoji对应的中文),这时可以通过表情与符号
来输入emoji。
在偏好设置
的键盘
下勾上在菜单栏中显示“虚拟键盘及表情与符号检视器”
。
然后点击菜单栏的输入法图标,点击显示表情与符号
,
现在就可以双击选择表情了,
###参考连接
Emoji Unicode Tables
Segoe UI Symbol
font-family MDN
font-family
Tue, Mar 17, 2015
JIT,Just In Time的缩写,就是在运行时把代码(字节码)编译成机器指令,然后直接执行机器指令来 提高运行效率。比如,如果一个函数在运行时被反复执行,那么可以把这个函数(对应的字节码)编译成 机器指令后直接执行对应的机器指令。
如何实现JIT?
一个可执行程序对应的机器指令是放在代码段(.text section)里的,运行时会被加载到内存里。CPU从 内存里取得机器指令,然后去执行。类似地,JIT就是把字节码转换成机器指令,放到一块内存里,然后 去执行这块内存里的指令。这篇文章给出了一个实现。
//通过mmap分配一块内存
//把权限设置成可读/写/执行,实际上为了安全应该是:刚刚分配的内存设置成可写的,
// 等往里面写入机器指令后去掉可写权限,只保留可读和可执行权限
//用mmap而不是malloc的原因是权限设置信息(protection bits)只能放在内存页的边界上,
// mmap分配的内存是从内存页边界开始的,而malloc分配则不一定。如果用malloc的话,
// 要自己处理权限问题,会麻烦一点。
void* alloc_executable_memory(size_t size) {
void* ptr = mmap(0, size,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (ptr == (void*)-1) {
perror("mmap");
return NULL;
}
return ptr;
}
void emit_code_into_memory(unsigned char* m) {
//机器指令
unsigned char code[] = {
0x48, 0x89, 0xf8, // mov %rdi, %rax
0x48, 0x83, 0xc0, 0x04, // add $4, %rax
0xc3 // ret
};
memcpy(m, code, sizeof(code));
}
const size_t SIZE = 1024;
typedef long (*JittedFunc)(long);
void run_from_rwx() {
void* m = alloc_executable_memory(SIZE);
emit_code_into_memory(m);
JittedFunc func = m;
//把内存地址当成函数地址直接去执行它
int result = func(2);
printf("result = %d\n", result);
}
Mon, Sep 22, 2014
摘自宾得K-7使用手册:
###在陷阱对焦模式下拍摄
在[C 自定义 5]菜单(第87页)中讲[35. 陷阱对焦]设置为[开启] 时,如果对焦模式设置为AF.S并安装有以下镜头类型中的一种,则 可使用陷阱对焦拍摄功能,并且当主体对准时快门会自动释放。
- 手动对焦镜头
- 具有AF/MF切换功能的DA或FA镜头(镜头上的该设定在拍摄 之前必须设定为MF)
####如何拍摄照片
- 将使用的镜头装在相机上。
- 将对焦模式杆转动至AF.S位置。
- 在主体将经过的位置处设置焦点。
- 完全按下快门释放按钮。
当主体进入设定焦点位置时,相机会自动释放快门。
在这篇文章也做了相应的介绍。具体的步骤如下:
- 相机设置在AF-S模式
- 相机设置在连拍模式
- 曝光模式设置成AV,这样可以用大光圈,得到浅的景深和很快的快门速度(作者估计是用来拍鸟的)
- 调整好焦点
- 盖上取景款,防止曝光错误
- Plug in the cable release, push the release button and block it.(估计就是用快门线来按下快门)
Mon, Jul 28, 2014
自己的博客是在Github Pages上搭建的,Github Pages使用Jekyll作为其背后的“引擎”。 因为Jekyll没有提供一个现成的“标签(tag)系统”,所以自己完成了一个简单的实现。最终效果见这里。
实现“标签”后的目录结构如下,
root_dir
├── ...
├── _config.yml
├── favicon.ico
├── css
├── script
├── images
├── _drafts
├── _layouts
├── _posts
│ ├── 2014-07-28-tag-impl-in-github-pages.md
│ └── ...
├── tags.html
├── index.html
└── about.html
下面简述一下实现的大致流程。
阅读更多…Sat, Jul 26, 2014
最近要写一些Javascript代码,发现Javascript相比其它的面向对象语言有着很大的不同。C++、Java等以类为基础 的(class-based)面向对象语言是通过子类-父类来实现继承的概念。Javascript只有对象,并没有“类(class)” 的概念(Javascript保留了“class”关键字,但是并没有使用)。
##概述 Javascript中的对象(假设为o)除了自有的属性(own property)之外,还维护着一个“链接”,这个“链接”指向另一个对象; 这个对象称为对象o的原型(prototype)。o的原型对象中也有一个“链接”指向它自己的原型。这样就形成了一个原型 链(prototype chain)。原型链以null为结尾。
Javascript中的对象在访问一个属性时,首先在自有属性中查找。如果没有找到,则会沿着原型链依次查看原型链上的对象是否 有该属性,直至找到或者到达原型链的终点。所以,一个对象的属性集合也包括了它原型链上的所有对象的所有属性;也就可以 说一个Javascript对象“继承”了它的原型。
Javascript在创建一个对象时会指派这个新建对象的原型。如果我们在创建不同的对象时指派同一个原型对象,那么就可以 认为这些对象“继承”自同一个“父亲(原型对象)”。
阅读更多…Thu, Jul 10, 2014
#!/bin/sh
# for details see here, http://git-scm.com/book/en/Customizing-Git-An-Example-Git-Enforced-Policy
# it seems that git on Windows doesn't support ruby, so use bash instead
# to function, put it into remote hook dir
# to disable, rename or delete file in remote hook dir
refname=$1
oldrev=$2
newrev=$3
# enforces fast-forward only pushes
check_fast_forward ()
{
all_refs=`git rev-list ${oldrev}..${newrev} | wc -l`
single_parent_refs=`git rev-list ${oldrev}..${newrev} --max-parents=1 | wc -l `
if [ $all_refs -ne $single_parent_refs ]; then
echo "Now not allow to push a non fast-forward reference."
echo "If it cause any inconvenient, please tell."
exit 1
fi
}
check_fast_forward
Name the above script as “update”, and put it into remote repo’s “hooks” directory. If necessary, make it executable. With simple test, this hook works well for me. It DOES block a client pushing any merge commit (no-fast-forward commit) to remote repository, meanwhile allow fast-forward push, which together ensure a clean history in remote.
My first try was using a example script from this link. However, that didn’t work. If you have successfully used that script, maybe you give me some hints :-)
The above script is implemented by bash script, and also works on Windows. My original implementation was used ruby, but failed on Windows.
If you find any bug or improvement, please let me know. And have fun :-)