表題の通り。
PEはフォーマットが決まっているので、バイナリを直書きしてファイルに出力する。 これをもってEXEコンパイラ。
コード
使い方
$ wine a.exe
表題の通り。
PEはフォーマットが決まっているので、バイナリを直書きしてファイルに出力する。 これをもってEXEコンパイラ。
$ wine a.exe
BerkeleyDBの話。
すべて自前のAPIを有する 独立して使うこともできるが、共通のオブジェクトハンドルであるenvironmentハンドルを共有するようになった 共有メモリをサポート
http://d.hatena.ne.jp/maeyan/20091227/1261848549
ハンドルとは、各アプリやその中で使われているオブジェクト等に対し起動時に割り振られる数字のことです。一意な数字であり、アプリごとにハンドルがツリー構造をとって親子関係でつながっています
ライブラリを設計するときは名前空間を利用することが肝要
BerkeleyDBの続き
インメモリとは 〔 オンメモリ 〕 【 in-memory 】 - 意味/解説/説明/定義 : IT用語辞典
バッファープールとは,表や索引のデータ・ページをディスクから読み取る際や変更する際に,そのデータをキャッシュに入れておくためのメモリー
バッファー・プールの目的は、データベース・システムのパフォーマンスを改善すること
特集:基礎から理解するデータベースのしくみ - 基礎から理解するデータベースのしくみ(6):ITpro
ページには,テーブルを構成するレコードや,インデックスのエントリを複数格納する
ファイルシステム上で動かすことを前提としているため、ファイルを抽象化したAPIを公開
DBの書き込みはディスクからデータを取り出してメモリの中で計算して修正したデータをディスクに戻す。メモリにデータを書き込まれた状態をダーティと呼ぶ。
読み込み用として固定したページはダーティになったとしてもディスクに書き込める
データの読み込みでダーティ状態が発生するのか?
固定している最中に読み込みとか書き込みとかしてもいいのか?っていう話 書き込み中に書き戻しは当然だめだけど、読み込み中に書き込みはいいんじゃないのか
処理に失敗した場合の復旧 データを更新する前に変更内容のログをディスクに書き込む すべてのデータページにログシーケンス番号(LSN)を書き込み、特定のページへの直近の変更に対応するログレコードを記録する
本体とは別のところにLSNを書き込むスペースがある。DBが壊れたときはそのスペースのLSNから該当するSQLを見つけ出して復旧する
LSNからSQLを呼び出す専用のメソッドが存在し、それを呼び出さないとLSNは使われない
Berkeley DBの続き
ファイル→ページ→レコードという階層構造が存在する
二つの異なるロッカーが特定のオブジェクトをロックしようとしたときは、どちらも同じバイト文字列でそのオブジェクトを表す。つまり、オブジェクトを不透明なバイト文字列で表すときの規約についてはアプリケーション側で決めておく必要がある
ほとんどの場合、Berkeley DBで表す必要があるのはロックしたい特定のファイルやページだけ
インターフェース上で未定義のデータ型をopaque data type(不透明型)と呼び、そのような型を指すポインタをOpaqueポインタと呼びます Opaqueポインタについて - white wheelsのメモ
相互参照の問題を回避するために、Opaque型を利用する。中身がなんだかわからないけど定義されているもの
C言語とかC++とかでアレされているやつ
ページレベルのロックはアプリケーションの同時実行性を制限してしまう。ある制御スレッドがデータベースのレコードを変更すると、他のスレッドからは同じページにあるそれ以外のレコードを変更できなくなる。一方レコードレベルのロックなら、全く同じレコードを変更しようとしない限りはそんな制限を受けない。ページレベルのロックをすれば安定性が向上する
小規模な組み込みを想定している
システム内に存在するさまざまな型のロックとその相互作用について定義 ロックを保持するエンティティを「ホルダー」、ロックを要求するエンティティを「リクエスター」
わかりづらいけど✓はNGを意味する
リクエスター/ホルダー | No-Lock | Read | Write | Wait | iWrite | iRead | iRW | uRead | wasWrite |
---|---|---|---|---|---|---|---|---|---|
No-Lock | |||||||||
Read | ✓ | ✓ | ✓ | ✓ | |||||
Write | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
Wait | |||||||||
iWrite | ✓ | ✓ | ✓ | ✓ | |||||
iRead | ✓ | ✓ | |||||||
iRW | ✓ | ✓ | ✓ | ✓ | |||||
uRead | ✓ | ✓ | ✓ | ||||||
iwasWrite | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
階層化ロックとは、さまざまな項目を階層を保ったままロックすること
ページをロックしたらファイルもまるごとロックする
あるページをロックするということは、ファイルをロックするということでもあるからだ。あるページが変更されているとき、そのページを含むファイルを同時に変更することはできない
って書いてあるけど、ページをロックしたら自動的にファイルもロックするのか(インテンションロックも含んでいるのか)
iはインテンションの意
あるロッカーがコンテナに対するインテンションロックを獲得すると、そのコンテナの中身に対してもロックする意図があるということを表す iRead、iWrite、そしてiWRはすべてインテンションロックであり、それぞれ読み込み、書き込み、その両方に対する意図を指す
エンティティは要素、モノの意
ロックを結合するときには、ひとつのロックを保持するのは次のロックを獲得するまでの間となる。つまり、内部のBtreeページをロックするのは、次のレベルのページを選んでロックするための情報を読み込むまでの間である
汎用性重視の設計にしておいたことが、並列データ格納機能を追加するときに役立った
File←iwrite データ←write
より荒い粒度に対する要求なので許される
Berkeley DB
ログマネージャーは、構造化された追記限定のファイルを抽象化したものである
ログの概念は極めてシンプルである。不透明なバイト文字列を受け取り、それをシーケンシャルにファイルへ書き出し、各レコードに一意な識別子を付与する。この識別子はログシーケンス番号(LSN)と呼ばれる
LSNを使ってレコードの取得などをやる。
ソフトウェアの構造を改良するため根本的にフレームワークを変更してしまうことを恐れてはいけない。また、一部だけ変更して後で徐々に整えていこうなんて考えではいけない。やるなら全体的にやってしまって、それから次に進もう。何度となく言われているように、「今それをする時間がないのなら、いつまでたってもそんな時間はひねり出せないだろう」ってことだ。また、フレームワークを変更するときにはテストもきちんと書いておこう
ログには必ずレコード単位のメタデータが含まなければならない。そうすれば、LSNさえわかれば返すレコードのサイズもわかるようになる
レコードヘッダがログレコードに含まれる
トランザクションIDを見ればそのログレコードがどのトランザクションに属するのかがわかるので、リカバリー中にそのレコードを無視できるのか処理が必要なのかも判断できる
大量のソフトウェア部品を組み上げたり保守したりする能力はとてもはかないものだということである。大量のソフトウェア部品を組み上げたり保守したりするのは難しくて間違いを犯しやすい。そして、ソフトウェアアーキテクトとして、できる限りのことをしてできるだけ早くできるだけ頻繁にソフトウェアが運ぶ情報を最大化しなければならない
Building and maintaining significant pieces of software is difficult and error-prone, and as the software architect, you must do everything that you can, as early as you can, as often as you can, to maximize the information conveyed in the structure of your software.
積分値→整数値
ログ先行書き込みとなんの関係があるのだろう…
チェックポイントとは、ある特定時点のデータベースの状態をディスク上に書き出す処理のことである
一般に、ログマネージャー自身はレコードタイプを気にしないものだ。
ログマネージャーとトランザクションマネージャーがそれぞれログをまるごと読み込んで位置を調べるのではなく、トランザクションマネージャーがその処理をログマネージャーに委譲するということだ。抽象化による処理の切り分けに違反してでもパフォーマンスを求めたという、ありがちな話だ
有害なレイヤー化違反あるいは抜け目のないパフォーマンス最適化
Berkeley DBのログレコードの大半はデータベースを特定できなければならない。各ログレコードにデータベースファイルのフルパスを含めてもよいが、そんなことをすればログの容量が肥大化するしあまり美しくない
→かわりに一意な整数値を記録
ファイル名とログファイルIDのマッピングを管理
バグを修正するときには、単におかしなところを見つけるだけではいけない。なぜそうなったのか、何か誤解があったのではないかということを探るようにしよう。そうすれば、そのプログラムのアーキテクチャをより深く理解できるようになるし、そもそもの設計自体に根本的な問題があればそれもはっきりするだろう。
びっくりするほどいいこと言ってる
Berkeley DB
このモジュールは、独立したコンポーネントたちをとりまとめてトランザクショナルなACID特性を提供する
トランザクションサブシステムは begin commit abortの3つで構成
チェックポイントによって、予期しないシャットダウンやクラッシュの後の復旧中に、ログに格納されている変更をSQL Server データベース エンジンが適用するための最適なポイントが作成されます
リカバリーの目標は、ディスク上のデータベースを(おそらく整合性が崩れてしまっている状態から)整合性のある状態に戻す
直近のチェックポイントLSNに対して、コミットされていないすべてのトランザクションを取り消し(UNDO)、コミットされていたトランザクションをすべて再現する(REDO) ログファイルのIDと実際のデータベースとのマッピングを再構築
データベースのリカバリーは複雑なトピックであり、実装するのも難しいしデバッグも困難だ。というのも、リカバリー処理はそんなに頻繁に発生するものではないからである アーキテクトとして、そしてプログラマーとしての私たちの目標は、さまざまな道具を自由に使いこなすことだ。設計・問題の分割・レビュー・テスト・命名規約やコーディングスタイルなどの道具を使いこなし、プログラミングに関するさまざまな問題を、自分たちで解決可能な問題に落とし込む
Not Only SQL(RDBMSじゃないSQL)
データベース側に隠蔽されていた操作をアプリケーションの設計側に押し出した システムアーキテクトの立場で考えると、これらのシステムの仕組みをより深く知っておく必要がある
SQLを使えば、データのディスク上での配置や使うインデックスそしてデータを処理するアルゴリズムを知らなくても必要な情報をよしなに取り出すことができる
論理的に等価であるいろいろな問い合わせプランの中から最も効率的な問い合わせができるものを見つける
クエリ (データに対する問い合わせ) を実行する最も効率的な方法を決定
これだけ問題点はあるが、やっぱり枯れきった技術であるので、使うことを検討する必要はあると思う。
NoSQLが選択肢にあがるのは、何か特有の問題がある場合だ。たとえば大量のデータを扱う必要があったり作業量が膨大になったり、SQLとリレーショナルデータベースではうまく最適化できないようなデータモデリングを採用した場合などである
NoSQLムーブメントの起源をたどれば、その大半は研究コミュニティの論文に行き着く
Google BigTable 複数列からなる履歴データを分類して格納 Amazon Dynamo キー指向の分散型データストア
大掛かりなSQL標準規格と決別して、ストレージの設計に関してシンプルながらも段階的なソリューションを提供 データベースがデータを操作する方法を単純化すればするほど、アーキテクトは問い合わせのパフォーマンスを予測しやすくなる
NoSQLではRDBMSの大前提であるACID特性をゆるくした