Varnish4.1 では最初の `Set-Cookie` しか read/write できない

先に結論

  • Varnish4.1 では最初の Set-Cookie しか read/write できないし、writeすると他の Set-Cookie は消える
  • varnish-modulesのcookieやheaderを使えば、他の Set-Cookie もread/writeできる

サンプルコード

vcl

vcl 4.0;

import std;
import directors;

sub vcl_init {
}

sub vcl_recv {
  return (hash);
}

sub vcl_pipe {
  return (pipe);
}

sub vcl_pass {
}

sub vcl_hash {
  hash_data(req.url);
}

sub vcl_hit {
  return (fetch);
}

sub vcl_miss {
  return (fetch);
}

sub vcl_backend_response {
  return (deliver);
}

sub vcl_deliver {
  if ( resp.http.set-cookie ~ "abc=123" ){
    set resp.http.set-cookie = "zzz=123";
  }

  return (deliver);
}

sub vcl_purge {
}

sub vcl_synth {
  return (deliver);
}


sub vcl_fini {
  return (ok);
}

varnishtest

varnishtest "example"

server s1 {
    rxreq
    expect req.url == "/"
    txresp -hdr "set-cookie: abc=123"  -hdr "set-cookie: def=456"
}
server s1 -start

varnish v1 -vcl+backend {
    include "/etc/varnish/default.vcl";
} -start

client c1 {
    txreq -url "/"
    rxresp
    expect resp.status == 200
    expect resp.http.set-cookie == "zzz=123"
    expect resp.http.set-cookie == "def=456"

} -run

テストの実行結果(一部)

**** c1    1.7 http[ 0] | HTTP/1.1
**** c1    1.7 http[ 1] | 200
**** c1    1.7 http[ 2] | OK
**** c1    1.7 http[ 3] | Content-Length: 0
**** c1    1.7 http[ 4] | Date: Mon, 06 May 2019 11:15:49 GMT
**** c1    1.7 http[ 5] | X-Varnish: 1001
**** c1    1.7 http[ 6] | Age: 0
**** c1    1.7 http[ 7] | Via: 1.1 varnish-v4
**** c1    1.7 http[ 8] | set-cookie: zzz=123
**** c1    1.7 http[ 9] | Accept-Ranges: bytes
**** c1    1.7 http[10] | Connection: keep-alive

vcl_deliver にある set resp.http.set-cookie = "zzz=123"; が実行されると、 set-cookie: def=456" が消えてしまう...!

結論

複数のcookieをread/writeしたい時には、varnish-modules の cookie を使いましょう

参考

labs.gree.jp

labs.gree.jp

Rubyでインクリメンタルする Quine AA を書いた

デモ

実行するごとにAAの白抜きの数字が増えていきます

コード

コードジェネレータ

前回解説したように、Quine AA は、AAを作るコード自身をAAに変換するジェネレータを作って作成します

blog.kasei-san.com

解説

  • k=0; がどの数字を表示するか決定します
  • base64の配列は0〜9までの数字のAAのデータです
  • その後は、数字のデータを元にソースコードをAAに展開するコードです
    • 途中の 0.upto(70){o<<e[j+=1]};o<<10;0.upto(25){o<<e[j+=1]}; はマージンです
    • もっと短くできるはず...
  • ポイントは 29行目の o[12] = ((o[12].to_i+1)%10).to_s; で、出力するコードの k=0; の数字をインクリメントしたものに変換しています
    • これにより、次に表示されるAAがインクリメントされた数字になります

感想

  • Quineで状態を変更するの、どうしたら良いのかと最初悩んだが、outputするコードを直接書き換えれば良いことに気がつけてよかった
  • Rubyist界隈ではQuine程度ではまだまだのようなので、次は別のキモいコードにチャレンジしてみます!

Rubyで書く! Quine AA!

こちらの記事を元に自分で作ってみた時の記録です

mickey24.hatenablog.com

ソースコード

     eval$s=%w'     
   b="BAhsK2Lgf4    
 D/D/7/8/9///j/B/9  
/8P8H/3/w/wf/f/7/7/ 
///+//P/   j/Af5/AOA
PAPwAAM     CHH3z4wY
cffPjBh     x98+MGHH
/z/wf8/     /P+D/z/g
nwMAAAA     PAPgBAA8
AAADAPw     D8A4A/AP
gDgB8A+  AGAHwD4AeA/
AP4D4D8A /gMAAOD8A/7
/4P8f/v/D/z/88MMPP/z
 www8//PDDDz/88AMA  
   APD/wP8//v//D/   
     7/////f///8x8A 
             /wPg/z/
              8/wP/P
                    
  wA=";    n=Mars   
  hal.l    oad(b.   
  unpac    k("m")   
  [0]);    x=20;y   
  =74;e    ="eval   
  $s=%w    "<<39<   
  <($s*    3);o="   
  ";j=-1;0.upto(x   
  *y){|i|o<<((n[i]  
  ==1)?e[j+=1]:32)  
   ;o<<((i%x==x-1)  
     ?10:"")}  ;o[  
                    
        -10,        
       6]=""<       
        <39<        
                    
      <".join"      
      ;puts(o)      
       ;#b="BA      
       hsK2Lgf      
       4D/D/7       
       /8/9//       
       /j/B/9       
       /8P8H/       
     3/w/wf/f/      
     7/7////+/      
     /P/j/Af5/      
     AOAPAPwAA      
                    
 MCH  H3z4wYcf      
 fPjBhx98+MGHH/z    
 /wf8//P+D/z/gnwM   
 AAAAPAPgBAA8AAADA  
  PwD8A4A/APgDgB8A  
  +AGAHw    D4AeA/  
  AP4D4D    8A/gMA  
  AOD8A/    7/4P8f  
  /v/D/z    /88MMP  
  P/zwww    8//PDD  
  Dz/88A    MAAPD/  
  wP8//v    //D/7/  
                    
    ////f///8x8A    
  /wPg/z/8/wP/PwA=  
 ";n=Marshal.load(b.
unpack("     m")[0])
;x=20;y=74;e="eval$s
=%w"<<39<<($s*3);o= 
"";j=-1;0.upto(x*y  
){|i|o<<(           
(n[i]==1)?          
 e[j+=1]:32);o<<((  
  i%x==x-1)?10:"")  
    };o[-10,'.join  

キモいですね!

作り方

以下の手順に沿ってコードを書いていく

  1. QuineにしたいAAを用意
  2. AAをBase64文字列に変換
  3. 「Base64文字列からAAを表示する」ジェネレーターを作成
  4. 「AAジェネレータ自身のコードをAAにする」ジェネレーターを作成
  5. 「AAジェネレーターをAAのQuineにする」ジェネレータを作成

AAのコードを実行可能にして、さらにQuine化

1. QuineにしたいAAを用意

このサイトで文字列をAAにできるので、これを元に作成。おすすめのフォントはdoh

https://www.askapache.com/online-tools/figlet-ascii/

aa=<<EOS
00000111111111100000
00011111111111110000
01111111111111111100
11111111111111111110
11111111000111111111
11111110000011111111
11111110000011111111
11111110000011111111
11111110000011111111
11111110000011111111
11111110011111111111
11111111011111111111
11111111111111111111
01111111111111111100
00011111111111111000
00000111111111111110
00000000000001111111
00000000000000111111
00000000000000000000
00111110000111111000
00111110000111111000
00111110000111111000
00111110000111111000
00111110000111111000
00111110000111111000
00111110000111111000
00111111111111111000
00111111111111111100
00111111111111111100
00011111111111111100
00000111111110011100
00000000000000000000
00000000111100000000
00000001111110000000
00000000111100000000
00000000000000000000
00000011111111000000
00000011111111000000
00000001111111000000
00000001111111000000
00000001111110000000
00000001111110000000
00000001111110000000
00000001111110000000
00000111111111000000
00000111111111000000
00000111111111000000
00000111111111000000
00000000000000000000
01110011111111000000
01111111111111110000
01111111111111111000
01111111111111111100
00111111111111111100
00111111000011111100
00111111000011111100
00111111000011111100
00111111000011111100
00111111000011111100
00111111000011111100
00111111000011111100
00000000000000000000
00001111111111110000
00111111111111111100
01111111111111111111
11111111000001111111
11111111111111111111
11111111111111111110
11111111111111111100
11111111100000000000
11111111110000000000
01111111111111111100
00111111111111111100
00001111111111111100
EOS

解説

  • このAAの1 の部分に後ほどソースコードが入る
  • ソースコードの文字数は当然ながら、AAで表現できる文字数よりも少ない必要がある
  • ソースコードにAAのデータも入るため、base64に変換して、格納可能にする

2. AAをBase64文字列に変換

普通に [Marshal.dump(bits)].pack("m") を使って変換

bits = aa.gsub("\n", "").reverse.to_i(2)
bin = [Marshal.dump(bits)].pack("m").gsub("\n", "")
puts bin #=>BAhsK2Lgf4D/D/7/8/9///j/B/9/8P8H/3/w/wf/f/7/7////+//P/j/Af5/AOAPAPwAAMCHH3z4wYcffPjBhx98+MGHH/z/wf8//P+D/z/gnwMAAAAPAPgBAA8AAADAPwD8A4A/APgDgB8A+AGAHwD4AeA/AP4D4D8A/gMAAOD8A/7/4P8f/v/D/z/88MMPP/zwww8//PDDDz/88AMAAPD/wP8//v//D/7/////f///8x8A/wPg/z/8/wP/PwA=

作成したBase64文字列は次のコードで使用するのでコピーする

3. 「Base64文字列からAAを表示する」ジェネレーターを作成

ジェネレータの概要

  1. Base64文字列にしたデータをデコード
  2. デコードしたBase64文字列を元に、0ならば空白。1ならば '1' を出力
  3. もともとのAAのサイズを元に、一定数出力したら改行

コード

# ↓AAをBase64文字列にしたデータ
b="BAhsK2Lgf4D/D/7/8/9///j/B/9/8P8H/3/w/wf/f/7/7////+//P/j/Af5/AOAPAPwAAMCHH3z4wYcffPjBhx98+MGHH/z/wf8//P+D/z/gnwMAAAAPAPgBAA8AAADAPwD8A4A/APgDgB8A+AGAHwD4AeA/AP4D4D8A/gMAAOD8A/7/4P8f/v/D/z/88MMPP/zwww8//PDDDz/88AMAAPD/wP8//v//D/7/////f///8x8A/wPg/z/8/wP/PwA="

# Base64文字列をデコード
n=Marshal.load(b.unpack("m")[0])

# AAのサイズ
x=20;y=74

# 出力結果が格納される変数
o=""

# デコードしたBase64文字列を展開
# 0ならば空白。1ならば '1' を出力
# 後でQuine化するときに改行や空白は使えないので数値で表現
0.upto(x*y){|i|
  o<<((n[i]==1)?'1':32) # 32 は空白
  o<<((i%x==x-1)?10:"") # 10 は改行
}
puts(o)

実行結果

     1111111111     
   1111111111111    
 11111111111111111  
1111111111111111111 
11111111   111111111
1111111     11111111
1111111     11111111
1111111     11111111
1111111     11111111
1111111     11111111
1111111  11111111111
11111111 11111111111
11111111111111111111
 11111111111111111  
   11111111111111   
     11111111111111 
             1111111
              111111
                    
  11111    111111   
  11111    111111   
  11111    111111   
  11111    111111   
  11111    111111   
  11111    111111   
  11111    111111   
  111111111111111   
  1111111111111111  
  1111111111111111  
   111111111111111  
     11111111  111  
                    
        1111        
       111111       
        1111        
                    
      11111111      
      11111111      
       1111111      
       1111111      
       111111       
       111111       
       111111       
       111111       
     111111111      
     111111111      
     111111111      
     111111111      
                    
 111  11111111      
 111111111111111    
 1111111111111111   
 11111111111111111  
  1111111111111111  
  111111    111111  
  111111    111111  
  111111    111111  
  111111    111111  
  111111    111111  
  111111    111111  
  111111    111111  
                    
    111111111111    
  1111111111111111  
 1111111111111111111
11111111     1111111
11111111111111111111
1111111111111111111 
111111111111111111  
111111111           
1111111111          
 11111111111111111  
  1111111111111111  
    11111111111111  
 

このAAジェネレータを元に、「AAジェネレータ自身のコードをAAにする」ジェネレーターを作成

ややこしくなってまいりました

4. 「AAジェネレータ自身のコードをAAにする」ジェネレーターを作成

概要

  • eval$s=%w'〜'.join を使って、$sをAAの材料にするジェネレータを作成する
  • の中にはAAジェネレータが入る

ソースコード

eval$s=%w'b="BAhsK2Lgf4D/D/7/8/9///j/B/9/8P8H/3/w/wf/f/7/7////+//P/j/Af5/AOAPAPwAAMCHH3z4wYcffPjBhx98+MGHH/z/wf8//P+D/z/gnwMAAAAPAPgBAA8AAADAPwD8A4A/APgDgB8A+AGAHwD4AeA/AP4D4D8A/gMAAOD8A/7/4P8f/v/D/z/88MMPP/zwww8//PDDDz/88AMAAPD/wP8//v//D/7/////f///8x8A/wPg/z/8/wP/PwA=";
n=Marshal.load(b.unpack("m")[0]);
x=20;
y=74;
e=$s*3;
o="";
j=-1;
0.upto(x*y){|i|o<<((n[i]==1)?e[j+=1]:32);o<<((i%x==x-1)?10:"")};
puts(o);
#
'.join

解説

  • eval$s=%w'〜'.join を使って、%$(すなわちジェネレータのコード) をAAにしている
    • %w'〜'.join することで、AAに余分な改行や空白が入らないようにしている
    • 結果としてコードには、改行や空白や ' をいれることはできない
  • e=$s*3; で、AA化するソースコードが、AAの文字数より多くなるように水増ししている
    • 10行目の # により、2回目以降出力されるコードはコメント扱いになる
  • 0.upto(x*y){|i|o<<((n[i]==1)?e[j+=1]:32);o<<((i%x==x-1)?10:"")}; にて、e に格納されたソースコードをAAに流し込んでいる

実行結果

     b="BAhsK2L     
   gf4D/D/7/8/9/    
 //j/B/9/8P8H/3/w/  
wf/f/7/7////+//P/j/ 
Af5/AOAP   APwAAMCHH
3z4wYcf     fPjBhx98
+MGHH/z     /wf8//P+
D/z/gnw     MAAAAPAP
gBAA8AA     ADAPwD8A
4A/APgD     gB8A+AGA
HwD4AeA  /AP4D4D8A/g
MAAOD8A/ 7/4P8f/v/D/
z/88MMPP/zwww8//PDDD
 z/88AMAAPD/wP8//v  
   //D/7/////f///   
     8x8A/wPg/z/8/w 
             P/PwA="
              ;n=Mar
                    
  shal.    load(b   
  .unpa    ck("m"   
  )[0])    ;x=20;   
  y=74;    e=$s*3   
  ;o=""    ;j=-1;   
  0.upt    o(x*y)   
  {|i|o    <<((n[   
  i]==1)?e[j+=1]:   
  32);o<<((i%x==x-  
  1)?10:"")};puts(  
   o)b="BAhsK2Lgf4  
     D/D/7/8/  9//  
                    
        /j/B        
       /9/8P8       
        H/3/        
                    
      w/wf/f/7      
      /7////+/      
       /P/j/Af      
       5/AOAPA      
       PwAAMC       
       HH3z4w       
       YcffPj       
       Bhx98+       
     MGHH/z/wf      
     8//P+D/z/      
     gnwMAAAAP      
     APgBAA8AA      
                    
 ADA  PwD8A4A/      
 APgDgB8A+AGAHwD    
 4AeA/AP4D4D8A/gM   
 AAOD8A/7/4P8f/v/D  
  /z/88MMPP/zwww8/  
  /PDDDz    /88AMA  
  APD/wP    8//v//  
  D/7///    //f///  
  8x8A/w    Pg/z/8  
  /wP/Pw    A=";n=  
  Marsha    l.load  
  (b.unp    ack("m  
                    
    ")[0]);x=20;    
  y=74;e=$s*3;o=""  
 ;j=-1;0.upto(x*y){|
i|o<<((n     [i]==1)
?e[j+=1]:32);o<<((i%
x==x-1)?10:"")};put 
s(o)b="BAhsK2Lgf4D  
/D/7/8/9/           
//j/B/9/8P          
 8H/3/w/wf/f/7/7//  
  //+//P/j/Af5/AOA  
    PAPwAAMCHH3z4w  

ここからジェネレータさらに加工して、上記AAを実行できるようにする

5. 「AAジェネレーターをAAのQuineにする」ジェネレータを作成

  • Syntax Error 回避のために、上記のコードを文字列として結合して、eval する処理を追加する
  • さらに、それをQuine化する

ベースとなるQuine

eval$s=%w'o="eval$s=%w"<<39<<$s<<39<<".join";puts(o)'.join
  • 39 は、'%w'〜'の中で'を使用するために数値を使用

このQuineは、o="...の前に任意のコードを埋めることができる

eval$s=%w'a="aaa";o="eval$s=%w"<<39<<$s<<39<<".join";puts(o)'.join

それを利用して以下のように、AAを作成するコードをQuineに埋め込む

ソースコード

eval$s=%w'b="BAhsK2Lgf4D/D/7/8/9///j/B/9/8P8H/3/w/wf/f/7/7////+//P/j/Af5/AOAPAPwAAMCHH3z4wYcffPjBhx98+MGHH/z/wf8//P+D/z/gnwMAAAAPAPgBAA8AAADAPwD8A4A/APgDgB8A+AGAHwD4AeA/AP4D4D8A/gMAAOD8A/7/4P8f/v/D/z/88MMPP/zwww8//PDDDz/88AMAAPD/wP8//v//D/7/////f///8x8A/wPg/z/8/wP/PwA=";
n=Marshal.load(b.unpack("m")[0]);
x=20;
y=74;
e="eval$s=%w"<<39<<($s*3);
o="";
j=-1;
0.upto(x*y){|i|o<<((n[i]==1)?e[j+=1]:32);o<<((i%x==x-1)?10:"")};
o[-10,6]=""<<39<<".join";
puts(o);
#
'.join

解説

  • e="eval$s=%w"<<39<<($s*3); が、Quineの先頭部分
  • o[-10,6]=""<<39<<".join"; で、AAで出力されるコードの末尾を '.join に置き換えて、Quineの末尾にしている

実行結果

     eval$s=%w'     
   b="BAhsK2Lgf4    
 D/D/7/8/9///j/B/9  
/8P8H/3/w/wf/f/7/7/ 
///+//P/   j/Af5/AOA
PAPwAAM     CHH3z4wY
cffPjBh     x98+MGHH
/z/wf8/     /P+D/z/g
nwMAAAA     PAPgBAA8
AAADAPw     D8A4A/AP
gDgB8A+  AGAHwD4AeA/
AP4D4D8A /gMAAOD8A/7
/4P8f/v/D/z/88MMPP/z
 www8//PDDDz/88AMA  
   APD/wP8//v//D/   
     7/////f///8x8A 
             /wPg/z/
              8/wP/P
                    
  wA=";    n=Mars   
  hal.l    oad(b.   
  unpac    k("m")   
  [0]);    x=20;y   
  =74;e    ="eval   
  $s=%w    "<<39<   
  <($s*    3);o="   
  ";j=-1;0.upto(x   
  *y){|i|o<<((n[i]  
  ==1)?e[j+=1]:32)  
   ;o<<((i%x==x-1)  
     ?10:"")}  ;o[  
                    
        -10,        
       6]=""<       
        <39<        
                    
      <".join"      
      ;puts(o)      
       ;#b="BA      
       hsK2Lgf      
       4D/D/7       
       /8/9//       
       /j/B/9       
       /8P8H/       
     3/w/wf/f/      
     7/7////+/      
     /P/j/Af5/      
     AOAPAPwAA      
                    
 MCH  H3z4wYcf      
 fPjBhx98+MGHH/z    
 /wf8//P+D/z/gnwM   
 AAAAPAPgBAA8AAADA  
  PwD8A4A/APgDgB8A  
  +AGAHw    D4AeA/  
  AP4D4D    8A/gMA  
  AOD8A/    7/4P8f  
  /v/D/z    /88MMP  
  P/zwww    8//PDD  
  Dz/88A    MAAPD/  
  wP8//v    //D/7/  
                    
    ////f///8x8A    
  /wPg/z/8/wP/PwA=  
 ";n=Marshal.load(b.
unpack("     m")[0])
;x=20;y=74;e="eval$s
=%w"<<39<<($s*3);o= 
"";j=-1;0.upto(x*y  
){|i|o<<(           
(n[i]==1)?          
 e[j+=1]:32);o<<((  
  i%x==x-1)?10:"")  
    };o[-10,'.join  
 

これで完成!!

ポイント

「AAのデータとアスキーアートジェネレーターをAAのQuineにする」ジェネレータを作って、AAのQuineを作成している

  • AAをBase64にしてコードに埋め込んでいる
  • AAの文字数とソースコードの文字数の不一致を何とかするために、コードの末尾をコメントにしてコードを3倍にしたものをAAに使用している
    • そのため、末尾の5文字はコメントのハズなので、'.join で置換しても問題がない
  • 基本となる Quine は eval$s=%w'puts"eval$s=%w"<<39<<$s<<39<<".join"'.join
    • eval$s='〜'.join というコードのために、' と空白文字が使用できない

感想

evalを使ったQuineは脳が裏返る感じがする

Rubyで書く! Quineのサンプルと解説

Quine ってなに?

クワイン(英: Quine)は、コンピュータプログラムの一種で、自身のソースコードと完全に同じ文字列を出力するプログラムである。

クワイン (プログラミング) - Wikipedia

基本の Ruby Quine

eval s="puts'eval s='+s.inspect"

解説

  • eval s="..." では、sに文字列を代入して、それが eval される
  • s の中身は "puts'eval s='+s.inspect"
  • なので、s を eval すると、'eval s='+s.inspect が puts される
  • s.inspect"puts'eval s='+s.inspect".inspect なので、 "\"puts'eval s='+s.inspect\"" となる
  • 結果、puts される文字列は、コードと同じ "eval s=\"puts'eval s='+s.inspect\"" となる

感想

  • s が再起っぽい挙動をするのがややこしいけど、理解すると eval すごいってなる

最短(と思われる) Ruby Quine

puts <<2*2,2
puts <<2*2,2
2

解説

  • 1行目の <<2 はヒアドキュメント
    • なので、2行目はすべて文字列
    • 3行目の 2 でヒアドキュメント終了
  • <<2*2 でヒアドキュメントの内容を2倍にしている
  • puts は複数の引数を渡されると改行してそれぞれを出力する
    • そのため、puts <<2*2,2,2 では改行後に2 を出力する
  • 結果として、コードと同一内容の文字列が出力される

f:id:kasei_san:20190501155916j:plain

感想

パッと見なにしているかわからない感がすごい

もっと短い Ruby Quine

$><<IO.read($0)

解説

  • $> は、 $stdout 標準出力
  • <<オブジェクトを出力させる命令
  • $0 は実行時に指定されたファイル名なので、IO.read($0) で、実行しているファイルの文字列を読み出す
  • 結果として、コードと同一内容の文字列が出力される
  • 仕組み上、irbでは実行エラーになる

感想

これはすこしずるいと思う

更に短い Ruby Quine

0

感想

ずるい

参考リンク

stackoverflow.com

PostgreSQL93でのレプリケーション確認方法

プライマリ側

SELECT * FROM pg_stat_replication

psql -x -c "SELECT * FROM pg_stat_replication"

-[ RECORD 1 ]----+------------------------------
pid              | 2167
usesysid         | 42700
usename          | repl_user
application_name | walreceiver
client_addr      | 10.0.2.102
client_hostname  |
client_port      | 33058
backend_start    | 2018-11-07 10:38:31.841085+09
state            | streaming
sent_location    | 12F8/8D0006C8
write_location   | 12F8/8D0006C8
flush_location   | 12F8/8D0006C8
replay_location  | 12F8/8D000400
sync_priority    | 0
sync_state       | async

重要なステータス

  • sync_state: 同期方法
    • sync: 非同期レプリケーション
    • async: 同期レプリケーション
  • state: スタンバイの状態。通常は streaming
  • sent_location: プライマリが送信済みのWALの位置
  • write_location: プライマリがバッファに書き込み済みのWALの位置
  • flush_location: プライマリがディスクに書き込み済みのWALの位置
  • replay_location: スタンバイがディスクに書き込み済みのWALの位置

〜_location がすべて一致していれば、遅延なくレプリケーションが行われている証拠

スタンバイ側

pg_last_xlog_receive_location()pg_stat_replication の位置と大差なければレプリケーションができている

psql -c "select pg_last_xlog_receive_location()"
 pg_last_xlog_receive_location
-------------------------------
 12F8/8D000E88
(1 row)

pg_last_xlog_receive_location は、 ストリーミングレプリケーションにより受信され、ディスクに書き込まれたトランザクションログの最後の位置

なお、PostgreSQL96からは pg_stat_wal_receiver で、pg_stat_replication のような情報が取れるらしいです

参考

バックグラウンドジョブおぼえがき

概要

job を用いて複数のコマンドを1つのシェルで平行して実行することができる

普通にコマンドを実行すると始まって、入力を受け付けるのが フォアグラウンドジョブ

入力を受け付けずに、CUIの後ろで実行されるのが バックグラウンドジョブ

バックグラウンドジョブを活用すると、時間のかかる処理を、1つのコンソールで並列で処理できて便利

バックグラウンドでジョブを実行する方法

& をつけると、最初からバックグラウンドで実行される

${コマンド} &

フォアグラウンドジョブをバックグラウンドに移動する方法

^z で現在実行中のジョブがバックグラウンドに移動

ただし、停止状態になるため、 bg ${job id} で再開する必要がある

バックグラウンドジョブの一覧を表示するコマンド

jobs

バックグラウンドジョブをフォアグラウンドに持ってくる方法

バックグラウンドジョブは、標準入力が必要になると停止状態になるので、 fg コマンドでフォアグラウンドに持ってくる必要がある

fg ${jobsで出てきたjob id}

(やや番外) ログアウトしてもコマンドを停止させない方法

nohup を先頭につける

  • 重い処理をリモートで実行するときに & と併用して、バックグラウンドジョブにして exit することが多い
nohup ${コマンド} &

MySQL でテーブルをロックせずに index を貼る方法いろいろ

indexを張った場合の処理の基本的な流れ

ALTER TABLE でindexを追加すると、indexを貼り終わるまでテーブルがロックされる

  • 内部的には テーブルをロック→テーブルをコピー→コピーしたテーブルにindexを貼る→元のテーブルと入れ替える→ロック解除 という処理が行われる

そのため、普通にindexを追加すると長時間DBが使い物にならなくなる

どうしたら良いの?

InnoDBの場合 online alter table という超スペシャルな機能があって、条件さえ満たしていればロックやテーブルコピーなしにindexが貼れる

MySQL :: MySQL 5.6 リファレンスマニュアル :: 14.11 InnoDB とオンライン DDL

online alter table の制約

MySQL 5.6 以前に作られた日時カラムを持つテーブルの場合、最低1回はコピーが必要

  • MySQL 5.6にて、日時カラムに浮動小数点が追加されたため

InnoDBじゃない場合は?

古来より、ロックなしに ALTER TABLE するためのオンラインDDLツールが作られており、それに頼るのが良い

pt-online-schema-change

昔からよく使われていた(と思われる)オンラインDDL

使用例も多く見つかる

ameblo.jp

gh-ost

Goで書かれている最近っぽいアーキテクチャのオンラインDDL

参考リンク

takatoshiono.hatenablog.com