質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

意見交換

クローズ

13回答

2716閲覧

直接ディスクとやりとりするようなデータベースは存在するのか

akiyama3284pga

総合スコア186

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

0クリップ

投稿2023/02/21 00:30

編集2023/02/21 00:32

0

0

自分はデータベースについて詳しくありません。
普段、postgresqlを使用しているのですが、そのデータ自体はファイルとして作成されファイル上で全て管理されているように思います。

抽象度として、

'''
パーティション(ディスク)

ファイルシステム

postgresql
'''

ファイルシステムの機能を利用しているので、当然ファイルシステムが無い状況では使用できないと思います。

そうではなくて、
'''
パーティション(ディスク)

データベース
'''

このような、直接的にディスクにアクセスしてデータを管理するようなデータベースは存在するのでしょうか。

linuxだと、直接的にそういった操作をAPIはユーザには提供されていないように思います(されてたらかなり危険?)。
なので、もし実現するとなると、ユーザプロセスとしてできる範疇を超えており、ファイルシステムのようにカーネル空間に直接組み込まれる形で用意されている必要があり、つまりはカーネルデーモンである必要があるように思います。

また、ファイルシステムも使用することがほとんどだと思うので、データがパーティション内で干渉しないようにする機構も必要になると思います。これもユーザレベルでは不可能だと思います。

このあたりにつきまして、ご意見等頂けましたら助かります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

回答13

#1

yambejp

総合スコア114839

投稿2023/02/21 00:37

質問の意図がわかりかねるのですが、「Unixは基本的に全てがファイル」なのでディスクがファイルでないことは無いと思います

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#2

matukeso

総合スコア1590

投稿2023/02/21 00:37

編集2023/02/21 00:39

昔のoracleとかはraw device(linuxなら/dev/sdb1とか)開けてた記憶があります。調べると12cで廃止ですか。
当然、専用パーティションになります。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#3

akiyama3284pga

総合スコア186

投稿2023/02/21 01:04

#1
ありがとうございます。おっしゃる通り、そのため(デバイス"ファイル"への命令を通じて)、ユーザからも直接操作できなくは無い。でした。
oracleがそれを成し遂げていることがわかりました。

#2
ありがとうございます。
raw deviceという用語を教えて頂き、ありがとうございます。
用語を使用して調べてみますと、色々と勉強になりました。

ファイルシステムを使用せず、ユーザプロセスから専用パーティションを用いて直接的にディスクを管理することができるということが驚きで、これから具体的にはどのようなコードを用いてそれを行えるのか、という点に関して
調べてみたいと思います。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#4

maisumakun

総合スコア145184

投稿2023/02/21 01:24

直接的にディスクにアクセスしてデータを管理するようなデータベースは存在するのでしょうか。

そのような操作が何のために必要なのか(通常のファイルを介した操作でできない、どのようなことを実現したいか)が気になりました。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#5

akiyama3284pga

総合スコア186

投稿2023/02/21 01:55

#4
おっしゃられております、逆と言いますか、いちユーザプロセスであるデータベースが、ファイルシステムを介さずにデータを管理するものがあるとするならば、通常のプロセスからddのような目の粗い操作ではなく、もっと細かなレベルでデータの読み書きを直接行う方法があるという証拠になり、これが今の自分の疑問を解消する、という理由で投稿いたしました。
また、今後postgres以外のデータベースを選ぶ際に考慮する材料にもなりそうだと考えております(今やほとんどがpostgres同様ファイルで管理するということがわかりました...)。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#6

maisumakun

総合スコア145184

投稿2023/02/21 02:02

編集2023/02/21 02:03

#5

「ddコマンド」という、直接ディスクにアクセスできるツールの実例がある(そして、設定次第では1バイトの読み書きすら可能である)以上、あとは「細かなレベルでデータの読み書き」を行う実装を行えばいいだけで、それ以上に何を疑問視しているのかがわかりません。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#7

dameo

総合スコア943

投稿2023/02/21 02:24

参考情報です。
https://www.quora.com/Are-there-any-DBMSs-that-manage-disk-blocks-directly

上記リンクの回答にあるように、大昔はほとんどのデータベースがraw deviceを扱えたと思うし、私も(速度的理由から)「最後はraw device使うよなぁ」と思ってましたが、あれよあれよと言う間に消えてなくなった気がします。消えてしまった正しい理由は知りません。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#8

otn

総合スコア84555

投稿2023/02/21 02:58

通常のプロセスからddのような目の粗い操作ではなく、

「目の粗い」というのが何のことか分かりませんが、ddも単なるユーザープログラムなので、
ディスクorパーティション全体を扱うならcpコマンドを使っても良いし、
特定位置を見るなら、Cでopen lseek read write closeしても良いし、他の言語でも可能です。

手元のLinuxにはRAWデバイスは定義されてないですね。
dfで表示されるパーティションはRAWでないブロックデバイスで、上記のような方法でアクセス出来ますが、OSがバッファリングを行います。RAWデバイスはOSのバッファリングを経由せずにディスクを直接扱うキャラクターデバイス(バイト単位デバイスというか)ですが、ディスクやパーティションの全体または特定位置のデータを読み書きするという観点ではどちらでも出来ます。
OracleがRAWデバイスを使っていたのは、OSのバッファリングとOracleのバッファリングが二重に行われて余計なオーバーヘッドがかかるのを回避するためですね。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#9

akiyama3284pga

総合スコア186

投稿2023/02/21 08:26

編集2023/02/21 08:29

#6
ごもっともなご意見ありがとうございます。
全く、おっしゃるとおりだったと思います。
ファイルシステムを介する場合と、そうでない場合で、全く別の方法が取られるはずだと何故か思い込みがあったため、理解があやふやになっていました。

ファイルシステムのパーティションであれ、ファイルやフォルダではなく、デバイスファイルをinput fileとしてやれば、直接のやりとりができているではないかと、気づくべきでした。

少し、ddの実装を見てみましたが納得できました。

ポイントは、
・ifd_reopen関数に渡すことになるinput_fil(ip)コマンドライン引数が、ファイル(ディレクトリ)なのか、デバイスファイルなのかをチェックして分岐するコードは見当たらない。

つまり、どちらであれ、その後行うであろうread()やseek()では、ユーザ側としては、そのfdがファイルを指すのか、デバイスファイルを指すのかは気にしなくていいということ。

・nread = iread_fnc (STDIN_FILENO, ibuf, max_bytes);
と続き、中で通常通りの手続きでread()されている(nread = read (fd, buf, size); )

■パーティションをローデバイスにするのか、ブロックデバイスにするのか、は本質的にはカーネル内でのバッファリングをするのかどうか、という点であり、どちらにおいても、直接扱う場合はddが示すようにopen(), read(), write(), seek() というようなAPIを使用して通常通り操作する。
※ただし前者ではパーティション全体をひとかたまりに扱うので、seekなどで目的の位置を探したりするのがかなり大変

なにかものすごく遠回りしていたような気がします...

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#10

akiyama3284pga

総合スコア186

投稿2023/02/21 10:26

#7
ありがとうございます。
資料参考にさせて頂きます。
また、なぜRAWデバイスのデータベースが少なくなってきたのか、自分なりに考えてみたいと思います。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#11

akiyama3284pga

総合スコア186

投稿2023/02/21 10:36

#8
ありがとうございます。
目の荒いという表現は間違っておりました。ddでも、任意のブロックサイズに指定できます。

通常のファイルシステムのパーティションにおいても、ddが使用できるということで、ではプログラムとしてはどんな具合なのかと、
コードを書いてみたのですが、エラーは出ないものの、肝心のreadしたものが出力されないと行った具合であります。

#define BUF_SIZE 512 int main(void) { int fd1, int byte_num; char buf[BUF_SIZE]; struct stat stat_buf; fd1 = 0; byte_num = 0; memset(buf, '\0', BUF_SIZE); fd1 = open("/dev/sda1", O_RDWR); lseek(fd1, 0, SEEK_CUR); byte_num = read(fd1, &buf[0], BUF_SIZE - 10); if(byte_num == -1) { fprintf(stdout, "read error\n"); return 1; } fprintf(stdout, "result -- %s\n", buf); close(fd1); return 0; }

ddであれば、
dd if=/dev/sda1 of=.for.txt bs=1000 count=3

のようにすると文字化けはしているものの、出力自体はされます。
ddもユーザプロセスということで、ddにできることが自分の書いたプログラムでできないことは無いと思うので、
どこか理解にミスがあるかと思うのですが...

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#12

otn

総合スコア84555

投稿2023/02/21 15:47

fprintf(stdout, "result -- %s\n", buf);

の意味を理解していないのでは?
これは、「"result -- の後に、bufの先頭から\0が出てくるまでを文字として表示して改行する」という意味なので、bufの先頭もしくは先頭から制御文字が続いた後に\0があるのでしょう。

bufの出力は、write(1,buf,byte_num)で行います。
もしくはfwrite(buf,byte_num,1,stdout)

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#13

akiyama3284pga

総合スコア186

投稿2023/02/22 01:04

編集2023/02/22 01:06

#12
ご指摘ありがとうございます。

以下のように改良後、

#include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include <stdio.h> #include <errno.h> #include <string.h> #define BUF_SIZE 1024 int main(void) { int fd1; int byte_num; char buf[BUF_SIZE]; struct stat* stat_buf; fd1 = 0; byte_num = 0; memset(buf, '\0', BUF_SIZE); fd1 = open("/dev/sda", O_RDWR); stat((int)fd1, stat_buf); //int size = stat_buf->st_size; //printf("sizesize%d\n",size); //printf("id%d\n", stat_buf->st_dev); if(fd1 == -1) { printf("print error code: %d\n", errno); return 1; } byte_num = read(fd1, &buf[0], 1024); if(byte_num == -1) { fprintf(stdout, "errrrrr\n"); return 1; } write(1,buf,byte_num); close(fd1); return 0; }


dd if=/dev/sda of=for.txt bs=1024 count=1

①、②共に全く同じ出力を確認することができました。

結局問題なのは、バフサイズ1000程度では、ファイルシステムの文字があるところまで到達できていなかった点のようで、
/dev/sda という母体を対象としますと、1000程度でも出力が確認できました。

バフサイズを10024に拡大して試したところ、/dev/sda1においても同じく①,②は同等の出力をいたしました。

ただ、当然といえば当然かもしれませんが、statなどのファイルを対象としたAPIは全く機能しませんでした。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

最新の回答から1ヶ月経過したため この意見交換はクローズされました

意見をやりとりしたい話題がある場合は質問してみましょう!

質問する

関連した質問