要使用官方的bustub-web-shell,就需要安装vercle,但是它用上了一些新的语法糖,比如:
if (typeof this._dest?.[method] === "function") {
(theme) => theme?.style)
store.hooksCleanup[index]?.();
所以我希望在一个早上的时间部署完,而短时间内我没法在我的ubuntu 20.04服务器上跑起来,所以我做了这个webshell。
仓库地址:https://github.com/Afeather2017/web-bustub
单个SQL
select * from test_simple_seq_2;
select * from __mock_t8;
select * from __mock_t8 where v4 > 4 and v4 < 7;
select * from __mock_t8 left join test_simple_seq_2 on v4 = col1;
由于SQL语句解析器的限制,不支持""
形式的字符串,所以只能用''
形式的字符串。
create table t1(a int, b varchar(4));
insert into t1 values (0, '0'), (1, '1'), (2, '234');
update t1 set a = 3 where b = '234';
select * from t1;
delete from t1 where a >= 2;
select * from t1;
使用快照隔离级别的事务
更改端口为8000,比如localhost:8000
。如果提示表创建失败,可能是别的面试官已经输入了相同的sql。 表不能够重复
- 打开2个网页
首先在网页A执行:
create table t1(a int, b int);
create index t1i1 on t1(a);
insert into t1 values (0, 0), (1, 1), (2, 234);
在网页B执行:
select * from t1;
insert into t1 values (0, 0), (1, 1), (2, 234);
此时B一定会Abort
- 新打开1个网页,输入:
create table t2(a int);
insert into t2 values (0), (0), (1), (1);
commit;
再同时新打开两个网页,分别输入:
update t2 set a = 1 where a = 0;
commit;
以及
update t2 set a = 0 where a = 1;
commit;
两者均会显示,由于事务不一样,所以可能略有不同:
再新打开一个网页,输入:
select * from t2;
可见,他不是串行化应该有的结果。串行化的结果应当是:要么全部是0,要么全部是1。
使用串行化隔离级别的事务
更改网页的端口为8001,比如localhost:8001
。如果提示表创建失败,可能是别的面试官已经输入了相同的sql。 表不能够重复
打开一个新网页,输入:
create table t3(a int);
insert into t3 values (0), (0), (1), (1);
commit;
再同时打开两个新网页,其中网页A输入:
update t3 set a = 1 where a = 0;
commit;
这个网页会显示:
另一个输入:
update t3 set a = 0 where a = 1;
commit;
此时会Abort
设计笔记
- 思路
整个项目依赖于bustub-nc-shell,它创建一个bustub数据库服务器。每次创建一个新的连接,都会给该连接绑定一个事务。也就是说一个连接只有一个事务。一旦这个事务长期未通讯(这里是6分钟),或者执行失败Abort了,或者commit了,这个事务都再也不能够用了。
而一个网页与一个事务一一对应,所以如果你commit了,或者手动Abort了,或者自动Abort了,你都要:复制网页域名和端口,重新打开一个网页即可。
- 潜在BUG
简单问题用简单方案。除非我要做一个完整好用的工业级客户端,否则目前的是够用的。留下这些BUG是功能和时间的取舍。
a. 由于TCP的特性,字符串长度比较长的SQL可能会导致输出错误。
比如你有一句长度是1M的SQL,中间有一处换行符,那么在TCP传输的时候可能会出现传完了换行符前面的前一半,而后一半没有传输完成的现象。而bustub-nc-shell会在读到换行符的时候输出...
,这是因为bustub-nc-shell是为了交互式终端而设计的,所以它会有这种情况。
真的要修复它,需要修改bustub本身。
b. 长SQL阻塞
由于要等待SQL执行完成,所以长时间执行的SQL会阻塞这个网页服务器(而不是数据库服务器本身)。除非面试官真的很感兴趣,否则这大概率不会发生。要修复则必须改为异步架构
c. 自动重置数据库时段时间阻塞,见第5点
- 单引号和双引号
由于binder暂且不支持双引号,所以不可以使用它。
- 利用异常减少分支
Python中socket的recv方法在对方关闭连接的情况下再读取,会返回0。此时我们关闭套接字即可。之后再读取会触发文件描述符错误。
套接字的send也可能触发sigpipe。反正处理方式都是一样的,为什么非得多一个分支?
- 自动重置数据库
可能某个面试官插入了表t1
,另一个面试官来试着执行相同的sql。此时必然无法插入表。
估计没有面试官会想着修改上述的例子吧……所以这一步是有必要的。
方法也很简单,killall杀死线程后,清理一下。网页服务器等待2秒。这样网页端可能要等待2秒。