Как стать автором
Обновить
1
0

Пользователь

Отправить сообщение

Может кто-нибудь объяснить столь низкий спрос на фронтенд-разработчиков (системные аналитики x2 больше, девопсы и aqa обходят фронт)? Что происходит?

Зачем в обзоре SQL выделен в отдельный самостоятельный язык? Это же сопутствующая технология, которая используется всеми бэкенд-разработчиками и многими аналитиками. Но ни как не отдельный полноценный языковой стек.

@noanswer@smart_alexрекомендую ознакомиться с трудами А.П. Ксендзюка. Он провел глубокий анализ идей наследия Кастанеды, теорию и практику (систему психотехник). А также параллели с восточной и европейской философией, современной психологии.

ничего удивительного. Для аналитиков и бэкендеров в работе нужны разные компетенции СУБД. Для бэкендера выше перечисленные пункты из статьи - знать действительно важно. Транзакции, аномалии при конкурентых запросах, локи, дедлоки, как их избегать, какие индексы и для чего - все это важно понимать для бэкендера. Не понимая таких вещей можно написать код, который будет в принципе работать в дев-среде, но на проде при конкуретных запросах будут ловиться критические баги периодически, например ловить lost update. Или например, пришел на проект а там на БД уровень изоляции выставлен Repeatable Read - нужно понимать, что это, от этого зависит, как ты будешь писать код в некоторых кейсах. Т.е. все это не теоретические вопросы, а вполне себе практические важные вещи.
В статье еще не сказано про MVCC и vacuum - тоже важные штуки, которые нужно понимать.

до этого вы утверждали, что решение на локах не будет корректно работать в конкурентной среде:

Например потому, что решение выше работает всегда, а ваше — лишь иногда, по крайней мере, в том виде, как вы его представили.

Подсказка: этот метод может быть вызван в конкурентной среде в двух разных потоках одновременно.


так что я думаю, если отбросить эмоции и детское "сам дурак, а я умный", то и для вас эта дискуссия была полезная и вы узнали что-то новое )

я спрашивал, почему вы считаете, что атомарный апдейт дает гарантию предотвращения lost update?

ну вы аргументируйте, а не отвечайте типа сам дурак.
Почитайте про аномалию lost update в БД при конкурентных апдетах. И как ее решать.

так БД сама по себе не обеспечивает гарантию предотвращения например lost update, как в нашем примере - при конкурентных запросах могут потеряться клики. Вернее БД может это делать, но нужно переключить уровень изоляции на serializable, но тогда БД будет сильно тормозить при сколько-нибудь существенной нагрузке.
Тоже самое с транзакциями - ты сам должен оборачивать в транзакции последовательность операций, которые нужно выполнить атомарно.

при чем тут руби код? Без локов клики могут потеряться при конкурентных вызовах запросов, даже если написать запросы на чистом sql

таймаут по локам - это как раз превышение времени ожидания снятия лока, который повесила другая транзакция. Т.е. от времени выполнения зависит напрямую.

на счет валидации - тут да, она не нужна в данном примере, и это плюс.
Атомарный апдейт - как он поможет с гонками?

а почему вы взяли, что гонки не будет? Это про решение выше с where и про это? атомарность - это вообще не про это. Атомарность - либо выполнится все, либо ничего. А для гонок - как раз механизм локов, либо оптимистическая блокировка, где разруливать на уровне приложения надо. Ну либо включать serializable в БД, но тогда БД будет еле волочиться.

Т.е. все-таки получается мы приходим к тому, что локи могут помочь с race condition. Или нет? ))
Т.е. по вашей логике раз мы когда-то гипотетически можем упереть в таймаут по локам, то мы будем сразу отказывать от этого решения, и будем за место этого применять неидеоматичные костыли? отказываться от решения, которое как раз задумано для такого типа задач )

Конкретно в нашем примере еще нужно очень постараться добраться, чтобы начать ловить ошибки по таймату. У нас в примере короткая быстрая транзакция, в которой только один апдейт одной записи. Из своего опыта, словит ошибки таймаута по локу происходит в кейсах, когда в одной транзакции несколько тяжелых операций и там висит лок. А у нас апдейт только одной записи в транзакции. Если посыпались такие ошибки на коротких транзакциях, то это говорит либо, что настройки у БД неоптимальны, либо серьезно возросла нагрузка. Настолько, что уже и без локов постгресу/mysql поплохеет. Но в этом случае нужно уже по-другому решать вопрос.

почему мое решение не будет работать в конкурентной среде? Используется лок. На уровне БД будет блокировка `SELECT FOR UPDATE`.
Если два одновременно потока/запроса будут выполняться, то один из запросов повесит лок на строку, а второй увидев блокировку, будет ждать снятия блокировки. Как только первый запрос выполнится, он снимет блокировку. И после этого выполнится второй запрос. И это обеспечивается СУБД. Почему это не будет работать в конкурентной среде?

странное решение. Для такого тривиального случая очень неудачное решение, читается плохо. Почему бы не использовать обычный лок?

def update
  counter = Counter.find(params[:id])
  counter.with_lock do
    counter.increment!(:clicks)
  end
end

хорошая статья. В нагруженных проектах на RoR обычно еще необходимо масштабировать очереди sidekiq. Усугубляется ситуация еще тем, что обычный сайдкик (не Enterprise версия) не параллелится по ядрам, работают на рубишных тредах. Поэтому для масштабирования запускают несколько инстансов сайдкика на отдельных подах/виртуалках, которые ходят в один редис, в котором очереди. Также можно настраивать, чтобы отдельные инстансы сайдкика разграбали определенные наиболее нагруженные очереди. Если у вас в кубере все крутится, то причин этого не делать нет.

Должна быть разбивка по грейдам (джун/миддл/сеньор). Без этого показатели в среднем по палате малоинформативны.

Я понял вас, я думал, что вы выставили значение pool, но оно не применялось. Но тогда вы не с той стороны решаете проблему. Вам нужно просто установить адекватное значение pool в конфиге подключения ActiveRecord. По умолчанию стоит 5 - и это очень-очень мало для прода. Нужно выставлять значение pool в зависимости от кол-ва воркеров/тредов приложения. У вас же наверное используется application server, например puma. Соответственно максимальное возможное кол-во подключений к БД будет известно. Например у вас 4 воркера пумы и 8 тредов на каждый воркер. Тогда pool = 4*8=32. Если используется сайдкик, то нужно увеличить значение pool на кол-во тредов сайдкика. И тд (шедулерный rake-таски и тд). Вот статья https://devcenter.heroku.com/articles/concurrency-and-database-connections

Есть подозрение, что у вас старая версия AR используется. Попробовал на далеко не новой версии activerecord 6.1.7, все прекрасно работает без явного указания использовать connection_pool:

```ruby

require 'active_record'

require 'pg'

ActiveRecord::Base.establish_connection(

# ...

pool: 10,

)

class User < ActiveRecord::Base; end

threads = []

10.times do

threads << Thread.new do

begin

puts User.count

rescue ActiveRecord::ConnectionTimeoutError => e

puts 'could not obtain a connection from the pool'

end

end

end

threads.each { |thr| thr.join }


```

во многом это связано с тем, что RoR очень популярен в Штатах, особенно в стартапах из-за скорости разработки на рельсах. Много вакансий - это американские стартапы, которые формируют команду разработки в РФ и СНГ. Предлагают они выше рынка или в верхнем диапозоне местного рынка. Это естественно подогревает рынок.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность