Archive for the ‘Drizzle’ tag
filesystem storage engine can read /proc/cpuinfo now
As the support of ‘/proc/meminfo’ is added to the filesystem storage engine, I hurry into enhancing the support for file /proc/cpuinfo. The difficult part of this functionality is this file has multiple sections, so that after the transposing, there will multiple tuples instead of one as in /proc/meminfo.
The new code has been passed with param-build. Hmm, I’m afraid it’s a good time to propose for merge.
the status of filesystem storage engine in drizzle
The file system storage engine is in shape now.
There are lots of storage engines in Drizzle already. What’s this new storage engine used for? To give you a rough idea, you can use the below SQL statement to read the file ‘/proc/loadavg’ directly.
drizzle> CREATE TABLE LoadAverage ( load1 DECIMAL(3, 2), load5 DECIMAL(3, 2), load15 DECIMAL(3, 2), active_processes VARCHAR(12), lastpid INTEGER) ENGINE=FILESYSTEM, FILE="/proc/loadavg"; drizzle> select * from LoadAverage; +-------+-------+--------+------------------+---------+ | load1 | load5 | load15 | active_processes | lastpid | +-------+-------+--------+------------------+---------+ | 0.00 | 0.00 | 0.00 | 1/97 | 6061 | +-------+-------+--------+------------------+---------+
The file system storage engine eases our manipulation on disk file, especially those file under /proc directory. This engine tries to be small and useful, like the calculator at your hand.
There are several options available for this storage engine for now. Extra options provides extra functionalities.
- FILE. This option specifies which file composes the corresponding table. This is the most important and useful option, it’s a MUST option for this storage engine.
- ROW_SEPARATOR. This option specifies which characters should be taken as end-of-line. The default is “\n”.
- COL_SEPARATOR. This option specifies which characters should be taken as the delimiter for columns. The default is ” \t” (space and tab), it’s reasonable to make it as default.
- SEPARATOR_MODE. It has three values, STRICT, GENERAL, WEAK. This one is a little tricky to understand. It shows the rule how to treat continuous separators. For example, if we have the line “111<SPACE><SPACE><SPACE>222″, the columns in WEAK mode would be only two columns “111″ and “222″; the columns in other modes would be four columns “111″, NULL, NULL, “222″. GENERAL mode will omit empty lines in the file; while STRICT mode will ruthlessly add an entire empty tuple into this table.
- FORMAT. This is a newly added feature. It’s written to process the file “/proc/meminfo”. This file has the similar format as key and value each line. What about we transpose these columns and rows and make all these keys as the column in a table? That should be cool. Yes, we can do this. Specify “KEY_VALUE” as the value of this option and set the FILE to ‘/proc/meminfo’, here you go:
CREATE TABLE t1 (a int) ENGINE=FILESYSTEM,FILE="/proc/meminfo",FORMAT="KEY_VALUE",COL_SEPARATOR=": "; SELECT * FROM t1; Active AnonPages Bounce Buffers Cached CommitLimit Committed_AS DirectMap2M DirectMap4k Dirty HugePages_Free HugePages_Rsvd HugePages_Surp HugePages_Total Hugepagesize InactiveMapped MemFree MemTotal NFS_Unstable PageTables SReclaimable SUnreclaim Slab SwapCached SwapFree SwapTotal VmallocChunk VmallocTotal VmallocUsed Writeback WritebackTmp 1526364 198768 0 221004 2829356 2600136 495728 4186112 7040 1916 0 0 0 02048 1722772 51064 502844 4059680 0 27124 198000 12076 210076 0 570296 570296 34359655499 34359738367 82808 0 0 SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `Active` varchar(8) DEFAULT NULL, `AnonPages` varchar(7) DEFAULT NULL, ...some lines omitted... `Writeback` varchar(2) DEFAULT NULL, `WritebackTmp` varchar(2) DEFAULT NULL ) ENGINE=FILESYSTEM FILE='/proc/meminfo' FORMAT='KEY_VALUE' COL_SEPARATOR=': '
There are still some TODOs on my list:
- enclosing and quotation is not there.
- more test cases to cover some corner cases.
- …
I would like my project to be useful, and I encourage all DBAs, administrators to give a try and see whether it fits your daily use. Any feedback is welcome!
drizzle revision 1641
In this revision, some of the public fields in class TableList are changed to private and they have to be accessed via setter/getter.
There’re pros and cons for doing this. But accessing the fields via getter/setter makes it more object-oriented, however, it comes with a code line that may be longer than 80 columns.
Drizzle is under great refactoring, for several purposes: one is to show the difference with MySQL and the other is to correct what’s was wrong in MySQL. Hope that this refactoring/rewrite will not suffer the second system syndrome.
关于store_lock
store_lock 作为 mysql 中一种表锁机制而存在,所谓表锁,就是当需要更新某个文件的时候,直接把整个表给锁住,不让其他的更新进行,比如有一个 session 正在 update 一个表1,那么当另外一个 session 正好也在这个时候去做 update 的时候就必须等待,等待前面一个 session 的更新结束才可以开始。
大嘴牛前面犯了一个错误,再次将存储引擎的标志位给弄错了,为什么说又呢,因为前面错过一次了[1]。主要的表现是这样的,大嘴牛需要上层进行全表锁定,但是发现却不是这样的,最后跟踪发现原来是被跳过 store_lock 的这段,也就是说,全表锁定的代码没有被执行到,真是悲剧啊。这以前都是因为无意中加入了一个标志位 HTON_SKIP_STORE_LOCK 。而在 drizzled/lock.cc 中则是
if (table_ptr[i]->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK))
continue;
store_lock 的这个方法很奇怪,他的发展应该属于历史原因,这么难看的接口竟然还存在着。他主要的目的是为了让引擎的开发者有机会去修改表锁,使得上层的锁不至于太大,这样的话就有机会做行锁等等,就是一个 downgrade 锁的钩子函数。
当然,俗话说:“能力越大,责任越大”,如果自己愿意承担这样的责任,那么完全可以使用上面的这个 SKIP_STORE_LOCK 的标志位。不过那样的话,开发者自己需要考虑的事情就多多了。只能祝你好运了。
CSV的表必须是temporary的
Drizzle 中的 CSV 引擎对于创建表是有限制的,必须申明该表为临时性的。所谓临时的表,就是当你的这个 session 结束的时候,该表会被清除;另外其他的 session 是看不到你的这个临时表的(比如,你像大嘴牛一样想开另外一个 terminal 连接到数据库并试图获取这个临时表,这是不可以的)。其中的秘密就在于这个函数:
bool Tina::doDoesTableExist(Session &session, TableIdentifier &identifier)
{
return session.doesTableMessageExist(identifier);
}
她将对于表格的查询限制于这个 session 中,而不是像其他存储引擎一样是基于文件的,通过文件是否存在来判断该对应的表是否存在。
CSV引擎的文件处理方法
MySQL 和 drizzle 中都有 CSV 引擎,用以处理以逗号分隔的文本文件。对于文本文件而言,SQL 的操作包含了插入,删除,更新等操作,那么实际上最后这些更新都会变成对于文本文件本身的操作。
全表搜索
这个容易实现,只需要将每行读出,然后按照逗号进行切割,依次放到每个域中即可。
插入
对于文件的插入操作,最简单的就是以追加方式打开,随后添加到文件的末端。
删除
比如现在需要删除文本文件的中间一行,大嘴牛不能直接通过对一个文件描述符进行动作将这件事情搞定,一般的做法是生成一个临时的更新文件,随后通过 rename 来将更新文件替换成原始文件,rename 的操作是原子的[1]。
更新
可以的一种方式是将需要更新的文件的某一行的内容首先删除掉,随后通过追加插入的方式写到文件的末端。
方法
上面简单介绍了大致的方式,而 CSV 为了提高性能,假设可能文件的多处进行删除,当我们在做一个 SQL 的 delete 操作时,所有满足条件的记录都会被删除,如果看到一条记录需要删除,我们就马上删除的话,那这不也太弱智了点嘛,我们需要的类一遍扫描的方法。
方法也是有的,我们在删除记录的过程中记录下该被删除的记录在文件中的原始开始位置以及结束位置,将这两个位置作为一个元素,成为一个链表。那么,当全表搜索结束的时候,也就是我们更新文件的时刻,这个时刻,只需要我们把文件中对应于刚才链表中的元素,将没有挖去的部分存放到一个临时文件,随后将这个临时文件重命名为原始文件。
这里就存在一个小小的算法问题,假设有一个列表,其中的每个元素包含了需要挖去的开始位置与结束位置,那么请实现这种更新的操作。说起来简单,但实际在书写代码的过程中还是需要注意一些细节。
大致的思路就是这样子,有兴趣的可以参见相关 CSV 代码。
[1]. http://www.dazuiniu.com/blog/2010/05/26/unix-amotic-operations.html