Open fujitamasashi255 opened 1 year ago
https://dev.mysql.com/doc/refman/8.0/ja/performance-schema-data-locks-table.html
https://dev.mysql.com/doc/refman/8.0/ja/performance-schema-data-lock-waits-table.html
https://dev.mysql.com/doc/refman/8.0/ja/performance-schema-statement-tables.html
https://dev.mysql.com/doc/refman/8.0/ja/performance-schema-transaction-tables.html
class MySqlPerformanceLogger
QUERY = <<-SQL
SELECT * FROM sys.innodb_lock_waits
SQL
# 以下のようなものもあり
# select
# locks.OBJECT_NAME,
# locks.INDEX_NAME,
# locks.LOCK_TYPE,
# locks.LOCK_MODE,
# locks.LOCK_STATUS,
# locks.LOCK_DATA,
# events.LOCK_TIME,
# events.SQL_TEXT
# from
# performance_schema.data_locks locks
# join
# performance_schema.events_statements_history events
# on locks.event_id = events.event_id
# and locks.thread_id = events.thread_id
# ;
def initialize
logger = Logger.new($stdout)
end
def self.measure(&block)
t1 = Thread.new do
yield block
end
t2 = Thread.new do
5.times do |n|
puts <<-EOS
ーーーーーーーーーーーーーーー #{ n + 1 }回目 ーーーーーーーーーーーーーーーーーーーー
EOS
res = ActiveRecord::Base.connection.select_all(QUERY)
puts res.rows[0]
sleep 0.01
end
end
t1.join
t2.join
end
end
MySqlPerformanceLogger.measure do
ActiveRecord::Base.transaction do
puts "ユーザーをロック"
user = User.lock.find(1)
puts "ユーザーをupdate"
user.update(name: "masa")
puts "ロールバック"
raise ActiveRecord::Rollback
end
end
ーーーーーーーーーーーーーーー 1回目 ーーーーーーーーーーーーーーーーーーーー
ユーザーをロック
ーーーーーーーーーーーーーーー 2回目 ーーーーーーーーーーーーーーーーーーーー
ユーザーをupdate
ロールバック
ーーーーーーーーーーーーーーー 3回目 ーーーーーーーーーーーーーーーーーーーー
ーーーーーーーーーーーーーーー 4回目 ーーーーーーーーーーーーーーーーーーーー
ーーーーーーーーーーーーーーー 5回目 ーーーーーーーーーーーーーーーーーーーー
User.class_eval "after_rollback { ActiveRecord::Base.connection.select_all('select locks.OBJECT_NAME, locks.INDEX_NAME, locks.LOCK_TYPE, locks.LOCK_MODE, locks.LOCK_STATUS, locks.LOCK_DATA, events.LOCK_TIME, events.SQL_TEXT from performance_schema.data_locks locks join performance_schema.events_statements_history events on locks.event_id = events.event_id and locks.thread_id = events.thread_id;') } "
ActiveRecord::Base.transaction do puts "ユーザーをロック" user = User.lock.find(1)
puts "ユーザーをupdate" user.update(name: "masa")
puts "ロールバック" raise ActiveRecord::Rollback end
Docker rm volume $(docker volume ls -q) https://qiita.com/Ikumi/items/b319a12d7e2c9f7b904d
Docker system df https://zenn.dev/bon/articles/docker-nospace-error
docker system prune help docker system prune --volumes https://docs.docker.jp/config/pruning.html
Error response from daemon: cannot stop container: d76d6e2a5f8aed35a4462b11c591c210fe18dc11e38063305cbf636de85fa91e: tried to kill container, but did not receive an exit event https://qiita.com/hanlio/items/6bcb3667147f2d5633de
https://github.blog/jp/2021-01-06-commits-are-snapshots-not-diffs/
https://www.amazon.co.jp/Exception-handling-Java-comprehensive-exceptions/dp/B09BYBJ4ZD
https://www.amazon.co.jp/Advanced-Exception-Handling-Techniques-Computer/dp/3540374434
[第9回]効果のないインデックス---「性別」に付けても効果なし https://xtech.nikkei.com/it/article/COLUMN/20070919/282317/
理屈で考える、データベースのチューニング https://techblog.raccoon.ne.jp/archives/1601618994.html
Rails
cleanj-rails.org https://discourse.clean-rails.org/
concern, concering
バリデータクラス
もう絶対迷わないエラーレスポンスの作り方【RFC7807】 https://qiita.com/akkino_D-En/items/a54bdf5dadc2daba1ab4
RailsにおけるRESTfulなURL設計勉強会 千駄ヶ谷.rb #12 に参加してきた https://joker1007.hatenablog.com/entry/20120723/1343064276
Ruby の例外クラス https://docs.ruby-lang.org/ja/latest/library/_builtin.html
Railsの例外の一覧を得るワンライナー https://qiita.com/snaka/items/78008ecd7e65e34c75d7
コールバック
Terraform を使用するためのベスト プラクティス https://cloud.google.com/docs/terraform/best-practices-for-terraform?hl=ja
システム運用アンチパターン ウェブオペレーション https://kakakakakku.hatenablog.com/entry/2023/10/30/090954
事前にデータ投入をした MySQL Docker イメージを作る場合は /docker-entrypoint-initdb.d を活用すると便利
ecsgo https://system.blog.uuum.jp/entry/2023/05/29/115452
ruby: 定数探索
ドキュメント:https://docs.datadoghq.com/ja/
https://docs.datadoghq.com/ja/logs/
{repo_FQDN}/compare/branch1...branch2
https://qiita.com/fantasista_21jp/items/9419ca4ab3bb8e1ee4c5
class MyClass extend ActiveModel::Callbacks define_model_callbacks :hello
def hello _run_hello_callbacks do puts "へろー" end end
before_hello :say
def say puts "せい!" end end
MyClass.new.hello
ーーーーー
class MyCallback
def before_hello(caller) puts "#{caller.class.name}" end end
class MyClass extend ActiveModel::Callbacks define_model_callbacks :hello
def hello _run_hello_callbacks do puts "へろー" end end
before_hello MyCallback.new end
MyClass.new.hello
abstract
extend ActiveModel::Callbacks
↓
include ActiveSupport::Callbacks
def define_model_callbacks(*callbacks)
# ===================================================
# define_model_callbacks(*callbacks) を実行
# (1)(2)が実行されて、メソッドが定義される
callbacks.each do |callback|
define_callbacks(callback, options) #...(1)_run_callbacks などが定義される
types.each do |type|
send("_define_#{type}_model_callback", self, callback) #...(2)before_hoge などが定義される(around, afterも)
end
end
# ===================================================
# (1) define_callbacks(callback, options) を実行
# ここから ActiveSupport::Callback
def define_callbacks(*names)
options = names.extract_options!
names.each do |name|
name = name.to_sym
([self] + self.descendants).each do |target|
target.set_callbacks name, CallbackChain.new(name, options)
end
module_eval <<-RUBY, __FILE__, __LINE__ + 1
def _run_#{name}_callbacks(&block)
run_callbacks #{name.inspect}, &block
end
def self._#{name}_callbacks
get_callbacks(#{name.inspect})
end
def self._#{name}_callbacks=(value)
set_callbacks(#{name.inspect}, value)
end
def _#{name}_callbacks
__callbacks[#{name.inspect}]
end
RUBY
end
end
# ===================================================
# (2) send("_define_before_model_callback", self, callback) を実行
# before_hoge(*args, **options, &block) が定義される
# ActiveModel::Callback
klass.define_singleton_method("before_#{callback}") do |*args, **options, &block|
options.assert_valid_keys(:if, :unless, :prepend)
set_callback(:"#{callback}", :before, *args, options, &block)
end
# ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
# before_hoge(*args, **options, &block) を実行
set_callback(:"#{callback}", :before, *args, options, &block)
↓
# ここから ActiveSupport::Callback
def set_callback(name, *filter_list, &block)
type, filters, options = normalize_callback_params(filter_list, block)
self_chain = get_callbacks name
mapped = filters.map do |filter|
Callback.build(self_chain, filter, type, options)
end
__update_callbacks(name) do |target, chain| # ...(a)
options[:prepend] ? chain.prepend(*mapped) : chain.append(*mapped)
target.set_callbacks name, chain # ...(b)
end
end
↓
# (a) __update_callbacks
# This is used internally to append, prepend and skip callbacks to the CallbackChain.
def __update_callbacks(name) # :nodoc:
self.descendants.prepend(self).reverse_each do |target|
chain = target.get_callbacks name
yield target, chain.dup
end
end
# (b) set_callbacks
def set_callbacks(name, callbacks) # :nodoc:
unless singleton_class.method_defined?(:__callbacks, false)
self.__callbacks = __callbacks.dup
end
self.__callbacks[name.to_sym] = callbacks
self.__callbacks
end
description
# module ActiveSupport
# module Callbacks
# extend Concern
# included do
# extend ActiveSupport::DescendantsTracker
# class_attribute :__callbacks, instance_writer: false, default: {}
# end
# CALLBACK_FILTER_TYPES = [:before, :after, :around]
#
# def run_callbacks
#
# private
#
# module Filters
# class Before
# class After
# class Callback
# module Conditionals
# module CallTemplate
# class CallbackSequence
# class CallbackChain
# module ClassMethods
# def set_callback
# def skip_callback
# def reset_callbacks
# def define_callbacks
#
# protected
#
# def get_callbacks
# def set_callbacks
def run_callbacks(kind)
callbacks = __callbacks[kind.to_sym] # kind は save, create など
if callbacks.empty?
yield if block_given?
else
env = Filters::Environment.new(self, false, nil)
next_sequence = callbacks.compile
# Common case: no 'around' callbacks defined
if next_sequence.final?
next_sequence.invoke_before(env)
env.value = !env.halted && (!block_given? || yield)
next_sequence.invoke_after(env)
env.value
else
invoke_sequence = Proc.new do
skipped = nil
while true
current = next_sequence
current.invoke_before(env)
if current.final?
env.value = !env.halted && (!block_given? || yield)
elsif current.skip?(env)
(skipped ||= []) << current
next_sequence = next_sequence.nested
next
else
next_sequence = next_sequence.nested
begin
target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
target.send(method, *arguments, &block)
ensure
next_sequence = current
end
end
current.invoke_after(env)
skipped.pop.invoke_after(env) while skipped&.first
break env.value
end
end
invoke_sequence.call
end
end
end
https://qiita.com/advent-calendar/2023/reading
https://techracho.bpsinc.jp/hachi8833/2023_11_09/116843
debug: docker compose build --no-cache --progress=plain
https://zenn.dev/y_mrok/books/ansible-no-tsukaikata/viewer/chapter1
https://mysql.sql55.com/sql/mysql-create-table-select.php#2
amazon aurora:
モデリング
Web API
AR
ActiveStorage
ステートの伝達に係る責務がステートの直接の使用者以外にも発生することです。図では、上からステートを受け取ってそのまま下に流しているコンポーネントたちがこれに相当します。
まず、useState + バケツリレーはパフォーマンス上不利になる可能性があります。使用者までの途中のコンポーネントも含めて多くのコンポーネントが実際にpropsとしてステートを受け取るということは、(たとえReact.memoなどで再レンダリングを抑制していたとしても)ステートが変化した際にはそれらのコンポーネントが再レンダリングされることになります。これにより、実際に必要なよりも多くのコンポーネントがレンダリングされることになります。
また、リファクタリングの過程でステートの型や名前(propsの型や名前名前)が変わることも考えられます。その際、そのステートの型や名前をインターフェースに含んだコンポーネントが多ければそれだけ多くのコンポーネントを変更しなければなりません。これはいわゆる凝集度が低くなってしまっていることを表しています。
以上のことから、パフォーマンスやコードのメンテナンス性を重視する場合は、useState + バケツリレーは推奨されません。
インターフェース(コンポーネントが受け取るprops)の観点で見ると、もはやこのステートはコンポーネントのpropsに現れません。途中のコンポーネントはもちろんのこと、使用者であるコンポーネントもステートをpropsではなくuseContextで受け取ります。このことから、ステートを使用することはもはやコンポーネントの責務ではなく、コンポーネントの内部処理の一部であると見なされます。
言い方を変えれば、context由来のステートは一種の外部ソースと見なされるということです。
つまり、contextから必要なステートを得るコンポーネントは、インターフェース上はたとえば外部のサーバーから情報をfetchするコンポーネントと似た振る舞いをするということです。問題点としては、このようにコンポーネントの内部実装の一環として外部ソースを取得する場合、テストのしやすさにやや難があることが挙げられます。
このことが気に入らない場合は、いわゆる「containerコンポーネントとpresentationalコンポーネント」のような概念を持ち出すことである程度解決できます。この場合、containerコンポーネントはどこからともなく(実際にはcontextから)ステートを持ってくるだけの薄いコンポーネントとなり、presentationalコンポーネントはcontainerコンポーネントからpropsで渡されたステートを描画するという責務を持つことになります。このように責務を分割することでテストが少しやりやすくなります。
パフォーマンスの観点からは、useContextのほうがuseState + バケツリレーよりは有利です。なぜなら、useContextを使うことで、ステートが変わった際には本当にそのステートを使用しているコンポーネントのみが再レンダリングされるようになるからです。コンポーネントツリーの頂点と使用者の間にある中間コンポーネントは、useContextを使っていなければ再レンダリングされません1。
しかし、コンポーネント間で共有されるステートが複雑化してくると、不満が出てくるでしょう。グローバルに使用されるステートが複数種類ある場合、それぞれで使用者も異なります。その場合、ステートの種類に応じて別々のProviderを用意しなければいけません。
まとめると、useState + useContextでグローバルなステート管理をする場合は、たくさんのコンテキストを管理しなければならないかパフォーマンスの低下かどちらかを受け入れなければならないということです。
CSSとコンポーネント設計に対する考察 classNameを任意に渡せるようなコンポーネントは「classNameを通じて自由にスタイルを拡張できる」という責務を持つことになるが、このような責務は非常に難易度の高く、特に、後方互換性のある形でこの責務を全うし続けるのはほぼ不可能。 → classNameをやめて、適切に責務をインターフェースとして実装する。
https://zenn.dev/ogakuzuko/scraps/1fd6da285612ce
React では、副作用は通常、イベントハンドラの中に属します。イベントハンドラは、ボタンがクリックされたといった何らかのアクションが実行されたときに React が実行する関数です。イベントハンドラは、コンポーネントの「内側」で定義されているものではありますが、レンダーの「最中」に実行されるわけではありません! つまり、イベントハンドラは純粋である必要はありません。
いろいろ探してもあなたの副作用を書くのに適切なイベントハンドラがどうしても見つからない場合は、コンポーネントから返された JSX に useEffect 呼び出しを付加することで副作用を付随させることも可能です。これにより React に、その関数をレンダーの後(その時点なら副作用が許されます)で呼ぶように指示できます。ただしこれは最終手段であるべきです。
https://ja.react.dev/learn/render-and-commit
あなたがレンダーをトリガした後、React はコンポーネントを呼び出して画面に表示する内容を把握します。「レンダー」とは、React がコンポーネントを呼び出すことです。
初回レンダー時、React はルート (root) コンポーネントを呼び出します。 次回以降のレンダーでは、state の更新によってレンダーがトリガされた関数コンポーネントを、React が呼び出します。 このプロセスは再帰的に発生します。更新されたコンポーネントが他のコンポーネントを返す場合、次にそのコンポーネントを React がレンダーし、そのコンポーネントも何かコンポーネントを返す場合、そのコンポーネントも次にレンダーし、といった具合に続きます。このプロセスは、ネストされたコンポーネントがなくなり、React が画面に表示されるべき内容を知り尽くすまで続きます。
更新されたコンポーネントがツリー内で非常に高い位置にある場合、その内部にネストされたすべてのコンポーネントを再レンダーするというデフォルトの挙動は、パフォーマンスにとって理想的ではありません。パフォーマンスの問題に遭遇した場合、パフォーマンスセクションで述べられているいくつかのオプトインによる解決方法があります。早まった最適化をしてしまってはいけません!
https://developer.mozilla.org/ja/docs/Learn/Accessibility/HTML
https://uxdesign.cc/everything-you-need-to-know-about-design-systems-54b109851969
パフォーマンススキーマテーブル
https://dev.mysql.com/doc/refman/8.0/ja/performance-schema-table-descriptions.html
以下、第4回 MySQLチューニング(3) パフォーマンススキーマ より引用
計器(インストゥルメント)とは
パフォーマンススキーマは性能統計情報を記録するストレージエンジンの一種として実装されており、performance_schemaスキーマのテーブルに格納された処理のレイテンシ(ピコ秒単位)やデータのバイト数、ソースでの位置、オブジェクトのデータなどに対してSQLでアクセス可能です。MySQLサーバのソースコード中にある “instrumentation point”(または “instrument” と表現される)にて「イベント」毎の処理時間や処理データ量などを計測および表示します。
パフォーマンススキーマの階層構造
パフォーマンススキーマのテーブル名や格納されている値の“Instruments”名は階層構造の各レベルに対応しています。
パフォーマンススキーマのデータ格納テーブルの名称
テーブル名の末尾が
SYSスキーマ
パフォーマンススキーマは非常に細かな粒度で情報が取得できるものの、データベース管理者やアプリケーション開発者にとっては細かすぎる場合もあります。そこでMySQLではパフォーマンススキーマやインフォメーションスキーマのデータに対して、よりシンプルなビューの集合であるSYSスキーマを用意し、性能問題の検出や診断などのタスクをより支援できるように改善しています。