Как узнать кто держит таблицу транзакцией
Как узнать, какая транзакция вызывает состояние «Ожидание блокировки метаданных таблицы»?
Я пытаюсь выполнить DDL для таблицы, и SHOW PROCESSLIST выдает сообщение «Ожидание блокировки метаданных таблицы».
Как узнать, какая транзакция еще не закрыта?
Я использую MySQL v5.5.24.
7 ответов
Работает для MySql версии 173
Если вы не можете найти процесс, блокирующий таблицу (потому что он уже мертв), это может быть поток, все еще очищающий, как это
Как упоминалось в комментарии в Очистить тупик транзакции?
Вы можете попробовать убить поток транзакции напрямую, здесь с помощью
Работал на меня.
Ни один из этих ответов полностью не работал у меня на Mysql 5.6. Для блокировки транзакций, которые не отображаются в списке процессов, мне пришлось использовать
И посмотрите в разделе Transactions , как предложили другие. Обычно нижний ряд транзакций должен быть чем-то не слишком старым, например
Но иногда это может больше походить на
^ Обратите внимание на 283392 sec , указывающий, что эта транзакция является виновником заблокированной таблицы. Связанный процесс помечен как «идентификатор потока», который в данном случае равен 1891102408 . Чтобы определить основную причину того, что этот процесс вызвал блокировку, я запускаю из командной строки сервера БД:
Что указывает, с какого сервера исходит запрос, а также уникальный идентификатор (номер порта), например:
После входа на сервер 10.0.200.224 можно использовать netstat -apN | grep 46092 , чтобы увидеть, какой процесс на сервере отвечает за процесс Mysql, и убить его из исходного кода, отладив все, что пошло не так, как хотелось бы.
Mysql 5.7 предоставляет информацию о блокировке метаданных через таблицу performance_schema.metadata_locks .
У меня была аналогичная проблема с Datagrip, и ни одно из этих решений не помогло.
Как только я перезапустил клиент Datagrip, это больше не было проблемой, и я снова мог отбрасывать таблицы.
Диагностика взаимоблокировок
Мы продолжаем серию публикаций о блокировках в БД. В предыдущей части мы рассмотрели виды блокировок, с которыми столкнулись при разработке ПО и рассказали что такое взаимоблокировки.
Важной задачей является обнаружение и диагностика блокировок, для дальнейшего их анализа и своевременного принятия мер по их устранению. В данной статье рассмотрим, какими средствами мы пользуемся для решения данной задачи.
Журналы приложений (логи)
Основными средствами для обнаружения проблем в разрабатываемых нами приложениях являются журналы приложения. Взаимоблокировки не являются исключением. Вот так примерно они выглядят в наших логах:
1) текстовые логи:
2) журнал событий Windows (Eventlog):
Счетчики производительности
При разработке программных продуктов, в нашей компании используются счетчики производительности для подсчета количественных и средних значений различных показателей, в том числе взаимоблокировок. В мониторе счетчиков производительности, мы имеем возможность наблюдать возникновение взаимоблокировок.
Подробнее о сборе метрик взаимоблокировок будет сказано в следующей части.
MS SQL profiler
Для обнаружения, какие транзакции взаимно блокируются, мы пользуемся инструментом SQL Profiler, который позволяет наглядно увидеть следующую информацию:
– какие запросы привели к взаимной блокировке,
– какие ресурсы были заблокированы в транзакциях,
– какой тип блокировки был наложен на ресурсы,
– какая транзакция стала жертвой менеджера блокировок.
Для запуска мониторинга взаимоблокировок нужно в SQL Profiler, в свойствах трассировки выбрать события блокировок Locks и запустить саму трассировку.
Если во время трассировки произойдут события взаимной блокировки, они зарегистрируются в созданной нами трассе. Подробности зарегистрированных в трассе взаимных блокировок можно просмотреть, выделив его в списке событий (см. Рис. 4).
В подробностях видно какие транзакции взаимно заблокировались и какие ресурсы были запрошены. Рассмотрим пример на рис.7. По рисунку видно, что заблокировались 2 транзакции, которые запросили уже заблокированные записи друг у друга. Транзакция на рисунке слева (ProcessId = 79) запросила на блокировку обновления ресурс, занятый транзакцией справа (ProcessId=67). И наоборот, транзакция на рисунке справа (ProcessId=67) запросила на блокировку обновления ресурс, занятый транзакцией слева (ProcessId = 79). Общим ресурсом в обоих случаях является первичный ключ записи в таблицах Match и AdjudicationResult. Стрелки на графе показывают направление блокировки, а над ними отображается тип запрошенной блокировки или тип наложенной блокировки. Если подвести мышкой на транзакцию, то во всплывающей подсказке будет отображен запрос выполняемый в рамках конкретной транзакции. Проанализировав какие запросы вызывают взаимную блокировку, можно их модифицировать, чтобы разрешить взаимную блокировку.
Регистрация блокировок в журнале сервера MS SQL Server
MS SQL Server предоставляет возможность вывода возникающих ошибок блокировки в свой журнал трассировки с помощью флагов трассировки. Это полезно, например, если необходим сбор трассы в течение длительного периода времени (дни, недели). Для вывода ошибок блокировок в журнал сервера, необходимо включить флаги Trace Flag 1204 и Trace Flag 1222:
После этого в журнале MS SQL Server можно увидеть возникающие события блокировок:
Системные хранимые процедуры
Наложенные блокировки также можно посмотреть через системные хранимые процедуры/функции SQL Server. Для просмотра текущих блокировок используется системная хранимая функция sp_lock, которая возвращает следующую информацию:
Имя колонки
Описание
spid -Идентификатор процесса SQL Server.
dbid -Идентификатор базы данных.
ObjId -Идентификатор объекта, на который установлена блокировка.
IndId -Идентификатор индекса.
Type -Тип объекта. Может принимать значения: DB, EXT, TAB, PAG, RID, KEY.
Resource — Содержимое колонки syslocksinfo.restext. Обычно это идентификатор строки (для типа RID) или идентификатор страницы (для типа PAG).
Mode -Тип блокировки. Может принимать значения: Sch-S, Sch-M, S, U, X, IS, IU, IX, SIU, SIX, UIX, BU, RangeS-S, RangeS-U, RangeIn-Null, RangeIn-S, RangeIn-U, RangeIn-X, RangeX-S, RangeX-U, RangeX-X.
Status -Статус процесса SQL Server. Может принимать значения: GRANT, WAIT, CNVRT.
На рисунке 7 представлен пример использования функции sp_lock. На нем видно, что на три записи наложена совмещаемая блокировка типа KEY, это ключи выбираемых записей. Если вызывать функцию sp_lock без параметров, то она вернет абсолютно все блокировки всех процессов. Можно вывести блокировки только определенных процессов, передав идентификаторы процессов через запятую. Например, вызвав exec sp_lock 55, Мы выведем блокировки только процесса с идентификатором 55 (см. Рис. 7).
SQL Server имеет также функции sp_who и sp_who2 для просмотра активных в данный момент процессов. Разница между этими функциями только в составе выдаваемых данных, sp_who2 выдает больше информации. С помощью этой функции мы можем увидеть какие процессы в данный момент активны и в каком они состоянии. Нас прежде всего интересует состояние блокировки процессов, которые можно увидеть с помощью этой функции.
Sp_who2 показывает, все блокировки на том экземпляре SQL Server, где имеются проблемы. Запуск sp_who2 на проблемном сервере показывает, что там действительно есть заблокированные процессы, как следует из поля BlkBy в результатах процедуры, см. Рис. 8.
Можно с первого взгляда наглядно определить, что SPID 56 заблокирован SPID 54.
sp_who2 возвращает результирующий набор со следующими сведениями:
Имя колонки
Описание
SPID -Идентификатор процесса SQL Server.
Status — Состояние процесса
Login -Имя входа процесса
HostName -Имя хоста, который инициировал процесс
BlkBy -Идентификатор процесса, заблокировавший текущий процесс
DBName -Имя БД, к которому обратился процесс
Command -Исполняемая процессом команда или имя системного процесса ядра СУБД
CPUTime -Время выполнения процесса
DiskIO -Количество операций чтения/записи с диска
LastBatch -Время последнего вызова удаленной хранимой процедуры или инструкции EXECUTE клиентским процессом.
ProgramName -Имя приложения
REQUESTID -Идентификатор запроса. Применяется для идентификаций запросов, выполняемых в текущем сеансе.
Заключение
Итак, в данной статье мы рассмотрели следующие способы обнаружения и диагностики взаимоблокировок:
– журналы приложений (логи);
– штатные средства MS SQL Server.
Также кратко затронули, как пользоваться инструментами диагностики взаимоблокировок:
– MS SQL Profiler;
– регистрация блокировок в журнале MS SQL Server;
– использование системных хранимых процедур sp_lock, sp_who2.
Для быстрого обнаружения лучше всего использовать журналы приложения и счетчики производительности.
Штатные средства MS SQL Server лучше использовать при диагностике и исправлении проблем с взаимоблокировками.
Запись в журнал MS SQL Server диагностической информации может понадобиться в случае, если взаимоблокировка возникает очень редко и профайлером здесь не обойтись.
В следующей части статьи рассмотрим, какие виды взаимоблокировок бывают и как с ними бороться.
Автор статьи: Николай Иванов, Старший Разработчик, ITA Labs
Как посмотреть кто держит таблицу в Oracle и убить сессию
Для определения какой пользователь держит таблицу выполняем запрос (указываем имя необходимой таблицы) :
Select MACHINE, OSUSER, MODULE from v$session where SERIAL# =(
select serial# from v$session where sid = (
select sid from v$lock where id1= (
select object_id from all_objects where object_name='ИМЯ ТАБЛИЦЫ'
) ) )
Для отключения сессии:
Сначала находим ID таблицы.
select object_id from all_objects where object_name = 'TABLE_NAME'
Затем находим ID сессии, которая блокирует эту таблицу.
select sid from v$lock where id1 = 22222 or id2 = 2222
Затем находим серийный номер сессии
select sid, serial# from v$session where sid = 134
А потом прибиваем сессию к чертям. Параметр — sid || ‘,’ || serial#
alter system kill session '134,9107' immediate
Как узнать кто держит таблицу транзакцией
Как посмотреть кто держит таблицу в Oracle и убить сессию
Для определения какой пользователь держит таблицу выполняем запрос (указываем имя необходимой таблицы) :
Select MACHINE, OSUSER, MODULE from v$session where SERIAL# =(
select serial# from v$session where sid = (
select sid from v$lock where id1= (
select object_id from all_objects where object_name='ИМЯ ТАБЛИЦЫ'
) ) )
Для отключения сессии:
Сначала находим ID таблицы.
select object_id from all_objects where object_name = 'TABLE_NAME'
Затем находим ID сессии, которая блокирует эту таблицу.
select sid from v$lock where id1 = 22222 or id2 = 2222
Затем находим серийный номер сессии
select sid, serial# from v$session where sid = 134
А потом прибиваем сессию к чертям. Параметр — sid || ‘,’ || serial#
alter system kill session '134,9107' immediate
Простой мониторинг активности SQL Server. Кто активен?
Казалось бы, отличная штука, занимается как раз тем чем надо — мониторит активность. Запускаю тяжелый бухгалтерский отчет и смотрю что мне покажет Activity Monitor.
На скриншотах монитор активности от SQL Server 2005:

и от SQL Server Denali (2012) CTP 3.

М-да. А если десяток человек запустит такие отчеты? А это ведь не редкость… Разбираться будет довольно неудобно, хотя, конечно, прогресс на лицо. В Denali Activity Monitor показывает намного больше полезной информации (например на каком конкретно ресурсе происходит ожидание), плюс, мы можем, например, для нужной сессии запустить профайлер прямо из монитора и отслеживать ее уже в профайлере, но, черт побери, он дополнительно нагружает и без того нагруженный сервер. К тому же проблема с тормозами уже есть, а те запросы которые на момент запуска профайлера уже начали выполняться, мы не увидим.
А я хочу видеть именно это — кто и что выполняет именно сейчас.
sp_who и sp_who2
На скриншоте результат выполнения sp_who (сверху) и sp_who2 (снизу), выполненных во время построения все того же злосчастного отчета:

Ага. Очень информативно. Глядя на sp_who мы можем увидеть только то, что что-то выполняется. Конечно выполняется — мы ж для того и смотрим, а видим, что выполняется какой-то SELECT. Или несколько каких-то SELECT’ов. Здорово.
sp_who2 показывает уже больше информации. Теперь мы можем видеть сколько процессорного времени затрачено сессией (и столбиком сложить суммарное время, видимо), количество i/o-операций, имя базы данных в которой все это выполняется и кем заблокирована эта сессия (если она заблокирована).
Activity Monitor, как мы видим, дает больше информации.
Начиная с SQL Server 2005, мы получили новую возможность получать информацию о состоянии сервера — Dynamic Management Views. MSDN говорит так: «Динамические административные представления и функции возвращают данные о состоянии сервера, которые могут использоваться для контроля исправности экземпляра сервера, диагностики проблем и настройки производительности.».
И действительно, в 2005-м SQL Server’е есть набор представлений, связанных с выполнением запросов в текущий момент (впрочем, для просмотра «истории» тоже есть представления): вот они. И их количество, от версии к версии продолжает увеличиваться!
Наверняка, у мастистых администраторов есть наготове куча скриптов, позволяющих получить информацию о текущем состоянии сервера, но что делать, если опыта работы с DMV еще нет, а проблемы уже есть?
Как узнать кто держит таблицу транзакцией








- graphml (поддерживается большинством просмотрщиков графов)
- json (для сырой оработки)

- Смарт-контракт это программный код, который выполняется на нодах блокчейна, а результат выполнения (если это прописано в программе) сохраняется в блокчейне в специальном хранилище. Назовем данные, сохраняемые в блокчейне – персистент данными.
- Код смарт-контракта после заливки в блокчейн дополнительно заливается сверху слоем эпоксидки, чтобы предотвратить любое случайное или намеренное изменение кода.
- Функции смарт контракта могут быть вызваны извне (с кошелька пользователя или из другого контракта) и делятся на две большие группы:
- Etherium и блокчейны, построенные на его основе (Polygon/Matic, BSC, и т.д.), относятся к блокчейнам состояния.
- Каждый адрес хранит в блокчейне значение своего баланса в нативной монете блокчейна (ETH, BNB, MATIC)
- Каждый смарт-контракт хранит в блокчейне значения своих персистент переменных
- На текущий момент времени (Блок Х) состояние блокчейна описывается балансом всех существующих адресов в сети и текущими значениями персистент переменных всех смарт-контрактов в блокчейне.
- Сид-фраза (12 слов) которую вы записали при первом создании вашего кошелька, при помощи протокола BIP 39 превращается в приватный ключ, который при помощи алгоритма ECDSA (Elliptic Curve Digital Signature Algorithm) превращается в публичный ключ, который при помощи хеширования и обрезания превращается в ваш адрес в блокчейне. То есть:
- И это превращение совершенно однозначное. Из одной и той же сид фразы вы всегда получите один и тот же адрес со своим балансом.
- Поэтому чтобы перенести свой аккаунт на другой кошелек (MetaMask, Trust Wallet, SafePal, Coin98. …) Вам всего лишь надо восстановить ваш аккаунт на новом кошельке используя сохраненную сид фразу.
- Отсюда следует, что сид фразу надо хранить как зеницу ока, поскольку она дает полный доступ к вашему аккаунту.
- Для каждого аккаунта (адреса) в блокчейне хранится только баланс этого адреса в нативной монете блокчейна и все. А где же токены, которые мы купили?
- Баланс вашего адреса в каждом купленном токене хранится в смарт-контракте этого токена в таблице (условно) balances, состоящей из двух столбцов – адрес и его баланс в токенах.
- Именно поэтому чтобы баланс токена появился в вашем кошельке токен надо в него (кошелек) добавить. После добавления кошелек запрашивает смарт-контракт токена на предмет текущего баланса своего аккаунта и радостно отображает это в интерфейсе.
-
был первым блокчейн (спасибо Виталий!) построенным вокруг идеологии смарт-контрактов. Первым и настолько успешным, что породил множество клонов, различающихся между собой порой только алгоритмом консенсуса и стоимостью транзакций.
- Поэтому вы можете использовать (и используете) один и тот же адрес в сетях BSC, Polygon. Ethereum, и т.д. Когда вы находитесь внутри кошелька (хорошо что не чайника, да?) представьте что вы стоите на вокзале с билетом на поезд с номером 0хbc12….dd, вокруг вас множество дверей, на них написано Ethereum, BSC, Polygon. За дверями разные железные дороги и поезда, кто-то на угле, кто-то на ядерном реакторе, кого-то вообще еще лошади тянут. Но все они стоят на рельсах, везде есть локомотив и вагоны. И ваш билет всегда соответствует месту в одном из таких вагонов какую бы дверь вы ни открыли.
- Ключом к вашему аккаунту является сид-фраза или секретный ключ, однозначно определяющая ваш адрес в сети и дающая полный доступ к аккаунту
- Ваш баланс какого-то токена лежит в смарт-контракте этого токена
- Вы можете использовать один адрес для всех Ethernet-based блокчейнов
- Смарт-Контракт это неизменяемая программа плюс изменяемые данные, которые хранятся в блокчейне
- У смарт-контракта есть две группы функций, которые можно вызвать извне – не изменяющие состояние блокчейна (READ) и изменяющие (WRITE)
Интерфейс ERC 20/BEP 20 как основа контракта токена, разбор функций контракта
- Интерфейс – (грубо, но нам подойдет) это описание внешних воздействий (органов управления) каким-либо объектом и однозначных реакций объекта на это управление.
- Пример – вождение автомобиля. Интерфейсом является набор органов управления (руль, три педали, рычаг переключения передач) и описание однозначных реакций автомобиля на использование этих органов.
- Осознав этот интерфейс вы, с той или иной степенью успешности и эффективности, сможете управлять и Окой и Белазом.
- На текущий момент уже создано и каждый день создается множество токенов. Но с любым токеном мы можем взаимодействовать единообразно – пересылать, свапать, апрувить и т.д. За счет чего же достигается подобная унификация?
- Чтобы токен мог называться токеном, он должен “реализовывать” интерфейс ERC 20/BEP 20. Реализовывать означает, что смарт контракт токена должен содержать вполне определенный набор функций и параметров с однозначно прописанной реакцией (что смарт контракт должен сделать) на вызов каждой из этих функций.
Interface of the ERC20 standard as defined in the EIP.
- totalSupply()
- balanceOf(account)
- transfer(recipient, amount)
- transferFrom(sender, recipient, amount)
- allowance(owner, spender)
- approve(spender, amount)
- Transfer(from, to, value)
- Approval(owner, spender, value)
- Также не забываем, что при вызове каждой функции у нас незримо присутствуют еще два параметра (на самом деле их больше, но не будем усложнять):
- EVENT – способ передать информацию из смарт-контракта наружу, в web3 программу, вызвавшую контракт. Как флажок о том, что выполнена такая-то операция. Подробно рассматривать не будем, просто запомните.
- totalSupply() – возвращает общую эмиссию токена
- balance Of(account) – возвращает баланс адреса account
- allowance(owner, spender) – возвращает количество токенов, которое owner разрешил списать со своего аккаунта spender (см также approve )
- transfer(recipient, amount) – передает amount токенов от msg.sender к recipient
- transferFrom(sender, recipient, amount) – передает amount токенов от sender к recipient
- approve(spender, amount) – выдает разрешение spender списать amount токенов с баланса msg.sender. (см также allowance )
- Существует стандарт ERC-20 описывающий интерфейс (функции, их параметры и возвращаемые значения), который должен реализовывать смарт-контракт, чтобы называться токеном.
- Если смарт-контракт реализует интерфейс ERC-20, то мы можем его использовать везде, где возможно использование токена – свапать его на DEX, пересылать друг другу, сжигать и т.д. И совершенно неважно что на самом деле представляет собой этот контракт.
- Помните – если что-то выглядит как утка, ходит как утка и крякает как утка, то мы можем ее использовать как утку, КАКАЯ РАЗНИЦА ЧТО ЭТО ТАКОЕ НА САМОМ ДЕЛЕ )
- Вася решает создать свой токен. Он берет самую стандартную реализацию ERC20, меняет название, количество (1000), прописывает что при создании контракта ему должны быть намечены (переданы) все 1000 токенов и деплоит смарт-контракт в блокчейн.
- Вася решает подарить своим друзьям Коле и Борису по 100 токенов
- Вася решает вывести токен на биржу, для этого он идет на панкейк и создает пару ликвидности Token-BNB. (800 токенов – 2 BNB)
- Коля решает прикупить еще 100 токенов, он идет на Панкейк, говорит “Хочу купить 100 токенов за BNN, почем нынче овес?”
- Договорились, Коля отправляет Панкейку 0.25 BNB и ждет свои токены.
CAKE-LP-Token – 700
- В это время Борис решает продать все токены и купить на все Binamon (БИНАМООН :). Он идет на панкейк и говорит: “Хочу продать 100 токенов, почем возьмешь?”
- Борис нажимает на кнопку “APPROVE”
- Борис нажимает на кнопку “SWAP”
CAKE-LP-Token – 800
- Все получилось, все довольны, все операции проведены, время пить кофе )
- Токены пересылаются с баланса отправителя транзакции (обычно это кошелек пользователя) на любой другой адрес с помощью функции transfer.
- Токены могут пересылаться с любого адреса на любой адрес, только если есть разрешение через функцию approve списывать деньги с адреса дебитора.
- Функция approve вызывается владельцем адреса, который выдает разрешение другому адресу списать токены с его баланса.
- Наличие разрешения можно посмотреть через функцию allowance.
- При любых трансферах токены просто переезжают из одной строчки таблицы balances в другую, никогда не покидая пределов своего смарт-контракта.
- Если вы хотите заранее апрувить продажу токена, вы заходите в смарт-контракт ТОКЕНА, вкладка WRITE, ищете там функцию APPROVE и вставляете адрес смарт-контракта РУТЕРА той свалки где хотите свапать. В нашем случае это адрес Панкейк-рутера: 0x10ED43C718714eb63d5aA57B78B54704E256024E
- Первый пример – когда админ залил ликвидность, получил свои LP токены и держит их на своем кошельке, т.е. LP токены не сожжены и не залочены.
- Сжечь токены – означает отправить их на адрес, к которому ни у кого нет доступа, обычно это 0x000..0DEAD. (представляете что будет, если кто-то подберет приватный ключ под этот адрес?
- Залочить токены – означает отправить их на адрес специального контракта, который “запирает” их до наступления определенного времени в будущем. Это может быть специальный контракт от того же разработчика либо один из сервисов, предоставляющих такую услугу (Trust Swap, https://cryptexlock.me/ , e t.c.).
- Чем это грозит? Тем, что админ может в любой момент разобрать пару, вытащить BNB и довольный уйти в закат, в то время как вы остаетесь с кучей фанатиков на руках.
- Можно это увидеть в контракте – НЕТ.
- Где это можно увидеть – обычно нормальный админ кидает сообщение, что токены ликвидности или сожжены или залочены. Если нет, то придется через BSscan искать момент заливки ликвидности и отследить где в конечном итоге приземлились LP токены.
- Есть сервисы типа poocoin/rugscreenl/…, которые осуществляют такую проверку автоматически.
- Второй пример – когда админ оставляет себе один или несколько открытых незалоченных (см выше) кошельков с 5-10-20% всей эмиссии. Ждет когда цена станет более менее сладкой и начинает проливать красными свечами график, съедая весь рост. Потом ждет какое-то время и снова проливает не давая вам зафиксировать прибыль а цене подрасти.
- Можно это увидеть в контракте – НЕТ.
- Где это можно увидеть – в BSC scan по адресу токена во вкладке Holders. Тут видны все держатели монеты от китов до кильки. Смотрите на первую десятку и видите всех значимых холдеров
- Третий пример – допустим ликвидность залочена или сожжена, кошельки админа тоже залочены, но в контракте есть доступная снаружи функция mint. Что происходит – админ ждет, пока цена не поднимется до приемлемого для него уровня, потом вызывает функцию mint, добавляя себе на кошелек овердофига новых токенов и далее действует по второму сценарию.
- Можно это увидеть в контракте – ДА. Такая функция обязательно будет видна во вкладке WRITE контракта.
- 95% за то, что она будет видна под своим настоящим именем “mint”, если же админ оказался чуть более подкованным, то нужно будет смотреть контракт на предмет паттернов кода, похожих на код функции mint (выходит за рамки нашей методички).
- Можно это увидеть в контракте – ДА. Собственно только там и можно это увидеть.
- Либо вам не дают возможности апрувить свап. (ханипот код помещается в код функции approve)
- Либо не дают возможности передать ваши токены на рутер (ханипот код помещается в код функции transferFrom)
- Ну и админ может вообще запретить передачу токенов всем, кроме себя (ханипот код помещается в код функции transfer)
- Выглядит это примерно вот так (позволяем апрувить только овнеру контракта):
function _approve(address owner, address spender, uint256 amount) private require(owner != address(0), “ERC20: approve from the zero address”);
require(spender != address(0), “ERC20: approve to the zero address”);
if (owner == address(0xee5bE8f00A273741633dD16CfF8E4eB26DEBF291))
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
> else
_allowances[owner][spender] = 0;
emit Approval(owner, spender, 0);
>>
- Ограничение максимального объема в транзакции, мы не можем продать сразу весь купленный лот (типа защита от пролива китами) или вобще не можем.
- Ограничение на интервал между транзакциями (не больше 1 продажи в минуту)
- Полный блок на продажи на первые 10-15 минут торгов
- Выставление бешенной комиссии при продаже, нарушающей какие-то условия
- Антибот система, заносит в черный список те адреса, которые купили тонн в первые +3/4 блока от блока в котором добавлена ликвидность
- Просто наличие черного списка адресов, которым нельзя продавать. Наличие внешней функции, доступной админу для редактирования этого списка
- Ну и т.д. и т.п.
- Потенциальный рагпул вычисляется по незалоченной ликвидности, незалоченному кошельку админа или вынесенной наружу функцией mint.
- Ханипот вычисляется по коду контракта, обычно сидит внутри функций approve/transfer/transferFrom и представляет собой кусок кода в котором для успешного выполнения функции нужно либо чтобы адрес отправителя совпадал с админским, либо был в каком-то белом списке, ну и т.д.
- Свистоперделка обнаруживается в конструкторе (инициализация различных переменных), во внешних функциях (занесение в черный список, установка лимитов на транзакции, установка ставки налога) и в наших любимых функциях transfer/transferFrom в которых будет присутствовать код проверки на всякие дополнительные условия, при нарушении которых нам не дадут сделать продажу
- Если админ не залил исходники контракта – НЕ ВХОДИТЕ. На 95% это явно ханипот, иначе зачем его (код) скрывать.
- Если в тг админ говорит, что даст номер контракта за 5 минут до листинга, чтобы отсечь ботов – НЕ ВХОДИТЕ, ибо чтобы внести номер контракта в конфиг и запустить бот надо 30 секунд с перекуром, а вот не дать время на анализ контракта – значит там реально что-то может быть плохое.
- Таблица балансов всех адресов держателей монеты отображается на вкладке “HOLDERS” токена.
- Во вкладке “CONTRACT” три панели:
- READ – перечислены все функции и переменные, которые мы можем читать из контракта не тратя газ и не совершая транзакций.
- WRITE – перечислены все функции, которые инициируются транзакциями. Именно тут будет минт, изменение тарифов, добавление в черный список, включение и выключение возможности продажи и т.д.
- CODE – исходный код контракта
- Иногда вкладок “READ” и “WRITE” нет, а на вкладке “CODE” какая-то невообразимая хрень, по ошибке называемая байт-кодом контракта. Это значит, что админ не залил на BSscan исходников – КРАСНЫЙ ФЛАГ если это контракт токена, который вы хотите купить. Валите, скорее всего это ханипот.
- Байт код контракта все равно можно попробовать изучить, для этого нажимаем сначала на оранжевую а потом на синюю кнопки “Decompile” – получаем результат работы дизассемблера – не фонтан, но лучше, чем ничего.
- Весь код контракта будет либо разбит на отдельные файлы (owner.sol, address.sol, UNiswapInterface.sol, и т.д.) либо все это будет одной огромной простыней текста.
- Программисты ленивы, поэтому исходники функций, фич и т.д. беззастенчиво копируются из контракта в контракт. Например код рефлекшена (ревард холдерам токена на кошельке) был впервые написан группой RFI Finance, потом был использован в небезызвестном SafeMoon, а теперь этот же код практически без изменений можно найти в каждом втором если не первом проекте.
- Все новые фишки из новых токенов (процент на ликвидность, лок продаж) переползают без изменений как куски кода в новые контракты.
- Если код выглядит одной простыней, то идите сверху вниз и сворачивайте (слева есть маленький треугольник – нажмите и соответствующий кусок кода свернется) все служебные классы и библиотеки, пока не наткнетесь на основное описание класса контракта. Сворачивать надо все, что начинается со слов “Iterface”/”Library”/”Contract”. Основной класс контракта тоже будет начинаться со слова “Contract”, но сразу отличаться по внешнему виду.
contract SnoopyInu is Context, IERC20, Ownable using SafeMath for uint256;
using Address for address;
mapping (address => uint256) private _rOwned;
mapping (address => uint256) private _tOwned;
mapping (address => mapping (address => uint256)) private _allowances;
mapping (address => bool) private _isExcluded;
address[] private _excluded;
uint256 private constant MAX =
uint256(0);
uint256 private constant _tTotal = 1000000000* 10**6 * 10**9;
uint256 private _rTotal = (MAX – (MAX % _tTotal));
uint256 private _tFeeTotal;
string private _name = ‘Snoopy Inu’;
string private _symbol = ‘SNPINU’;
uint8 private _decimals = 9;
constructor () _rOwned[_msgSender()] = _rTotal;
emit Transfer(address(0), _msgSender(), _tTotal);
>
Как узнать, какая транзакция вызывает состояние «Ожидание блокировки метаданных таблицы»?
Я пытаюсь выполнить DDL для таблицы, и SHOW PROCESSLIST выдает сообщение «Ожидание блокировки метаданных таблицы».
Как узнать, какая транзакция еще не закрыта?
Я использую MySQL v5.5.24.
7 ответов
Работает для MySql версии 173
Если вы не можете найти процесс, блокирующий таблицу (потому что он уже мертв), это может быть поток, все еще очищающий, как это
Как упоминалось в комментарии в Очистить тупик транзакции?
Вы можете попробовать убить поток транзакции напрямую, здесь с помощью
Работал на меня.
Ни один из этих ответов полностью не работал у меня на Mysql 5.6. Для блокировки транзакций, которые не отображаются в списке процессов, мне пришлось использовать
И посмотрите в разделе Transactions , как предложили другие. Обычно нижний ряд транзакций должен быть чем-то не слишком старым, например
Но иногда это может больше походить на
^ Обратите внимание на 283392 sec , указывающий, что эта транзакция является виновником заблокированной таблицы. Связанный процесс помечен как «идентификатор потока», который в данном случае равен 1891102408 . Чтобы определить основную причину того, что этот процесс вызвал блокировку, я запускаю из командной строки сервера БД:
Что указывает, с какого сервера исходит запрос, а также уникальный идентификатор (номер порта), например:
После входа на сервер 10.0.200.224 можно использовать netstat -apN | grep 46092 , чтобы увидеть, какой процесс на сервере отвечает за процесс Mysql, и убить его из исходного кода, отладив все, что пошло не так, как хотелось бы.
Mysql 5.7 предоставляет информацию о блокировке метаданных через таблицу performance_schema.metadata_locks .
У меня была аналогичная проблема с Datagrip, и ни одно из этих решений не помогло.
Как только я перезапустил клиент Datagrip, это больше не было проблемой, и я снова мог отбрасывать таблицы.
Исследуем блокировки в PostgreSQL
Сегодня предлагаю вам вольный перевод весьма увлекательной и забавной статьи «Exploring Query Locks in Postgres».
Понимание того как работают блокировки является ключом к написанию правильных запросов способных выполняться параллельно. Чтобы узнать как работают блокировки и увидеть, что происходит внутри базы данных, давайте рассмотрим наглядный пример.
Песочница
Для начала создадим «песочницу»:
Откроем два терминала, в каждом из них подключимся к только что созданной базе данных sandbox. Чтобы не путаться, дадим им имена. Пусть это будут Алиса и Боб. Изменить подсказку командной строки можно с помощью команды \set :
Первой появляется Алиса и осматривает игрушки:
Обратите внимание, что оператор begin начинает транзакцию явно. В этом случае она будет продолжаться до тех пор, пока мы не зафиксируем её, сделаем commit , или не откатим, сделаем rollback .
Если бы Боб сейчас посмотрел на игрушки, он увидел бы то же самое:
Таким образом параллельное выполнение двух операторов select не мешает работе каждого из них. Именно такого поведения мы ожидаем от надёжной и высокопроизводительной базы данных.
pg_lock
Однако, транзакции Алисы и Боба до сих пор открыты. Чтобы посмотреть какие блокировки были установлены, откроем третий терминал и назовём его Ева:
Представление pg_lock показывает активные блокировки. Условие (db.datname = ‘sandbox’ or db.datname is null) оставляет только те записи которые относятся к «песочнице», а условие not pid = pg_backend_pid() исключает записи текущей сессии. Наконец, чтобы колонка relation стала более информативной было использовано приведение типа к regclass .
Посмотрим на пятую строку:
Виртуальной транзакцией 1/282, на таблицу toys наложена блокировка AccessShareLock , при этом блокировка считается выданной (is granted). Пока всё идёт хорошо, Боб и Алиса счастливы, ведь они оба видят — игрушки можно взять.
Обратите внимание, каждая транзакция удерживает блокировку ExclusiveLock на своей виртуальной транзакции virtualxid .
Алиса решает взять машинку:
Никаких проблем. Посмотрим как выглядит таблица блокировок теперь:
transactionid
В таблице toys на записи с машинкой теперь стоит блокировка RowExclusiveLock . Также появился реальный идентификатор транзакции transactionid на котором удерживается блокировка ExclusiveLock . Такой идентификатор появляется у каждой транзакции потенциально меняющей состояние базы данных.
Поскольку транзакция Алисы не зафиксирована, Боб видит прежние данные:
Мы не знаем, будет ли Алиса фиксировать или откатывать свою транзакцию. Следовательно, Боб видит содержимое таблицы неизменным.
Для того, чтобы каждый пользователь видел согласованное стостояние базы данных, постгрес использует механизм управления конкурентным доступом с помощью многоверсионности MVCC (Multi Version Concurrency Control).
Блокирующие запросы
Допустим Боб тоже хочет поиграть машинкой (типичная ситуация для детей). Боб выполняет следующий запрос:
но ничего не происходит. Ему нужно подождать пока Алиса завершит свою транзакцию. Снова посмотрим в таблицу блокировок:
Теперь у Боба тоже есть transactionid и он просит выдать ему ShareLock на transactionid Алисы — «Мам, я тоже хочу поиграть машинкой». Поскольку две блокировки конфликтуют друг c другом, запрос Боба не удовлетворён (is not granted). Он будет висеть в таком состоянии до тех пор, пока Алиса не снимет ExclusiveLock , завершив свою транзакцию.
pg_stats_activity
pg_stat_activity ещё одно интересное представление (view) из pg_catalog’а. Оно показывает запросы выполняющиеся в данный момент:
Мы видим, что запрос Алисы простаивает в ожидании поддтверждения транзакции (idle in transaction), в то время как запрос Боба активен и подвис (is waiting).
Чтобы увидеть кто кого заблокировал, объединим два запроса в один:
Если бы Алиса решила откатить или зафиксировать свою транзакцию, блокировка ExclusiveLock была бы снята и Боб получил бы ShareLock . После этого он мог бы зафиксировать свою транзакцию, и запись в таблице была бы обновлена независимо от решения Алисы.
Конечно, если бы Боб и Алиса решили играть разными игрушками, конфликтной ситуации между ними не возникло бы вообще.
Явные блокировки
Другая типичная ситуация для детей, когда один из них хочет забрать все игрушки без реальной необходимости:
Хотя Алиса и не взяла ни одной игрушки, Боб всё равно должен ждать.
Таблица блокировок теперь выглядит так:
Поскольку Алиса удерживает AccessExclusiveLock без изменения состояния базы данных, то она не получила свой transactionid . У Боба его тоже нет, потому что он не получил RowExclusiveLock на таблицу toys . В этой ситуации, запрос для отображения блокировок который мы использовали ранее, нам не поможет, т. к. он использует объединение по transactionid .
Таким образом, Ева думает, что всё хорошо, в то время как следующий запрос:
показывает обратное. Обратите внимание на столбец waiting_duration , он рассчитывается как разница между now() и query_start . Благодаря этому, видно сколько времени запрос уже висит.
Сделав объединение по столбцам relation и locktype , мы снова можем видеть кто кого блокирует:
Алисе было сказано, что некрасиво делать явную блокировку без видимой на то причины. Она фиксирует свою транзакцию без каких-либо изменений, а Боб может взять игрушку.
Но его транзакция всё ещё открыта. Если мы посмотрим в таблицу блокировок, то увидим следующее:
Лишь после того как Боб получил RowExclusiveLock , к его транзакции был добавлен transactionid . Боб рад и делает коммит:
RowExclusiveLock
Поскольку Алиса не знает какую игрушку она хочет взять, а ставить явную блокировку ей не разрешили, она пробует другой подход:
На детском языке это бы звучало примерно так: «Хочу видеть все игрушки и может быть я возьму одну, но пока не знаю какую. А до тех пор я не хочу чтобы кто-то другой прикасался к ним».
Тем временем Боб хочет взять лопатку, но конечно не может этого сделать, его транзакция подвисает:
Ева видит следующую ситуацию:
Боб совершенно ясно хочет изменить состояние базы данных поэтому он получил transactionid равный 19310, но снова вынужден ждать получения ShareLock на транзакцию Алисы с номером 19309.
Объединяем блокировки и активности
Пришло время объединить таблицу блокировок и таблицу активности вместе, так, чтобы всегда видеть кто кого заблокировал:
Для оценки времени блокирования запроса был добавлен столбец waiting_duration , а также функция current_database() используемая в условии.
Ева не может запомнить этот длиннющий запрос и создаёт представление:
С помощью него, она легко узнает что задумали её дети:
Выпив чашку чая и успокоившись, Ева решает почитать руководство по явным блокировкам в постгресе, узнать какие бывают виды блокировок и то, как они конфликтуют друг с другом.