Monthly Archives: Май 2020

Введение в интерфейс Мemcached для MySQL InnoDB

В предыдущих статьях серии:

В MySQL 5.6 появилось memcache-совместимое хранилище ключ-значение на базе движка Innodb.

InnoDB Memcache Daemon предоставляет вам стабильность innodb для данных вида ключ-значение, доступ к которым может быть организован через более быстрый и оптимизированный протокол memcached. При использовании данного протокола будут пропущены: парсинг запроса, его оптимизация и остальные части обработки, которые не требуются.

С помощью mysqlnd_memcache, вы можете прозрачно направлять ваши запросы к такому memcache-совместимому интерфейсу.

Установка

Стандартные пакеты MySQL 5.6, которые поставляются Ubuntu (Trusty), не включают в себя плагин memcache. Для использования этого плагина вам потребуется установить его из официальных apt-репозиториев MySQL-я (для Debian 7.x Wheezy, Ubuntu 12.04 Precise и Ubuntu 14.04 Trusty).

После того как вы установили MySQL 5.6 (или выше), необходимо войти в MySQL под суперпользователем и выполнить следующее:

SOURCE /usr/share/mysql/innodb_memcached_config.sql;
INSTALL PLUGIN daemon_memcached SONAME "libmemcached.so";

Скрипт innodb_memcached_config.sql делает несколько вещей, и первое, что он делает — это создаёт базу данных innodb_memcache, которая содержит три таблицы:

  1. cache_policies: в этой таблице хранятся правила, как выполняются команды GET, SET, DELETE и FLUSH.
  2. containers: эта таблица содержит список ваших таблиц, к которым возможен доступ с помощью memcache
  3. config_options — в этой таблице хранятся настройки memcache, а именно — разделитель многоколоночных значений — separator (по умолчанию вертикальная черта “|”) и разделитель обращения к таблицам table_map_delimiter (по умолчанию точка “.”)

Второе, что выполняет скрипт — загружает сам плагин и запускает memcache демона внутри MySQL.

Теперь всё готово, чтобы использовать этот плагин.

Создание memcache хранилища

Так как движок memcache устанавливает некоторые требования к таблицам, то не каждая innodb таблица может быть автоматически использована в качестве такого хранилища. Для использования вы должны настроить так называемую коллекцию.

Каждая коллекция имеет название, которое используется для обращения к ней через memcache, а также содержит ряд столбцов:

  • name: название для обращения к коллекции через memcache
  • db_schema: название базы данных
  • db_table: название таблицы
  • key_columns: название столбца, содержащего ключ (пусть вас не смущает множественное число, это один столбец)
  • value_columns: названия столбцов, указанные через запятую, которые содержат значение. В memcache-значении все значения этих столбцов будут разделены вертикальной чертой (как указано в таблице config_options)
  • flags: какие флаги memcache установить
  • cas_column: название столбца для CAS-значения, устанавливаемого memcache-ем
  • expire_time_column: название столбца, в котором хранится время «протухания» (в секундах) или 0 если не «протухает» никогда
  • unique_idx_name_on_key: название индекса, который накладывает ограничение UNIQUE на столбец ключа. Если столбец ключа является первичным ключом, укажите PRIMARY

Для того чтобы организовать наше хранилище, мы создадим новую базу данных kv_data и таблицу kv_store в ней:

CREATE DATABASE kv_data;
USE kv_data;

CREATE TABLE kv_store (
    `key` VARCHAR(255),
    `value` VARCHAR(1024),
    `flags` INT, 
    `cas` BIGINT UNSIGNED, 
    `exp` INT,
    primary key(`key`)
) ENGINE = INNODB;

Далее, мы сообщим плагину о нашем хранилище, создав контейнер:

INSERT INTO innodb_memcache.containers(
    name, 
    db_schema, 
    db_table, 
    key_columns, 
    value_columns, 
    flags, 
    cas_column,
    expire_time_column,
    unique_idx_name_on_key
) VALUES (
    'kv_data',
    'kv_data',
    'kv_store',
    'key',
    'value',
    'flags',
    'cas',
    'exp',
    'PRIMARY'
);

После того как вы это сделали, вам нужно немного подождать, чтобы это вступило в силу или перезапустить MySQL.

Использование memcache интерфейса

Теперь, когда у вас запущен и работает memcache интерфейс innodb, вы можете вставлять (insert) данные также как в обычную таблицу БД или, конечно же, посредством протокола memcache, — что можно осуществить с помощью telnet-а.

При использовании протокола memcache — по умолчанию и минимальное — количество операций перед тем, как данные будут сброшены в innodb, является 32, как указано в настройке daemon_memcached_w_batch_size. Это означает, что данные становятся видны в MySQL каждые 32 операции. Такова плата за производительность. Исключением из правил является использование binlog-репликации, в том случае, если она постоянно установлена в 1.

Для того чтобы MySQL изменения были сразу доступны через memcache, вы должны выполнить:

SET TRANSACTION ISOLATION TO READ-UNCOMMITTED;

Для использования memcache интерфейса с помощью telnet, используйте его следующим образом:

$ telnet localhost 11211

telnet> set test.key 0 0 11
Hello World
STORED

telnet> get test.key
VALUE test.key 0 11
Hello World
END

Использование нескольких коллекций

По умолчанию данные сохраняются либо в коллекции под названием default или, если она не существует, в первую коллекцию в таблице коллекций.

Для доступа к данным другой коллекции у вас есть два варианта:

Первый наиболее близок к MySQL-евскому оператору USE. Вы просто обращаетесь к самой коллекции и далее любые запросы оперируют с этой коллекцией, пока она не будет изменена на другую.

Перед именем коллекции, для отличия от ключей, ставится префикс — два знака @:

telnet> get @@kv_data
VALUE @@kv_data 0 16
kv_data/kv_store
END

Второй — это использовать полное имя. В этом случае как раз вступает в игру table_map_delimeter, посредством чего мы просто ставим перед коллекцией префикс @@collection и после table_map_delimeter. Таким образом, обращение к test.key становится  @@kv_data.test.key

telnet> get @@kv_data.test.key
VALUE @@kv_data.test.key 0 11
Hello World
END

Я рекомендую всегда использовать такой синтаксис, т. к. вы можете случайно сменить коллекцию в каком-нибудь вызванном участке кода без возврата к предыдущей коллекции.

Использование плагина mysqlnd_memcache

Теперь вы можете просто обращаться к вашим данным через интерфейс memcache, используя PHP расширение memcached или memcache (memcached extension, memcache extension). В том числе, вы можете настроить ваш обработчик сессий использовать этот подход. А также вы можете использовать обычные SQL запросы. Однако, с плагином mysqlnd_memcache вы можете прозрачно перенаправлять SQL запросы на memcache интерфейс, когда это необходимо.

По умолчанию запросы сопоставляются с регулярным выражением, указанном в константе MYSQLND_MEMCACHE_DEFAULT_REGEXP:

/^\s*SELECT\s*(.+?)\s*FROM\s*`?([a-z0-9_]+)`?\s*WHERE\s*`?([a-z0-9_]+)`?\s*=\s*(?(?=["'])["']([^"']*)["']|([0-9e\.]*))\s*$/is

Если запрос соответствует, далее плагин проверяет, что в настройках коллекции перечисленны только поля из таблицы и что в секции WHERE только одно условие с простым сравнением по ключу.

Для нашего примера этому условию будет соответствовать вот такой запрос:

SELECT `value` FROM kv_store WHERE `key` = 'test.key';

Однако ни один из таких не будет:

SELECT * FROM kv_store WHERE `key` = 'test.key';
SELECT `value` FROM kv_store WHERE `key` = `test.key` AND value LIKE '%foo%';
SELECT `key` FROM kv_store WHERE value LIKE '%foo%';

Такие запросы могут быть выполнены с помощью механизмов одного из расширений: mysql, mysqli или pdo, и будут перехвачены незаметно для вас.

Плагин mysqlnd_memcache не обрабатывает запросы на запись.

Несмотря на это ограничение, его использование может определённо улучшить ваш код (тем, что вам не требуется реализовывать обращение к memcache/memcached API) и получить большой выигрыш в производительности при незначительных изменениях.

Запись, Репликация и пул Memcache

Memcached известен своей простой настройкой пула memcached-ов для балансировки нагрузки и отказоустойчивости, но как обстоят дела с memcache-интерфейсом для InnoDB? В некотором роде похожий обработчик присутствует в MySQL репликации, тем, что каждый слейв может быть использован как сервер Memcache-а в режиме только-для-чтения, впрочем, те же правила для разделения чтения и записи применимы и при работе с Memcache-ем.

Вы должны убедиться, что вы используете только плагин mysqlnd_memcache для доступа к вашему пулу и связать его с плагином mysqlnd_ms для организации разделения чтения и записи. Однако это означает, что вы упустите возможность воспользоваться высоко производительным иинтерфейсом Memcache-а на запись.

Так как нет способа указать memcache(d) расширению, что сервера используются в режиме только-на-чтение, то невозможно использовать стандартную топологию репликации master+slaves в качестве пула memcached-ов.

Заключение

Memcached интерфейс для InnoDB — это намного более быстрый способ использования MySQL для простых хранилищ ключ-значение, но при этом имеет все преимущества великолепного движка InnoDB.

Хотя он и не является настолько быстрым, как сам memcached, он позволяет вам устранить “ещё один шарнир” в вашей инфраструктуре, при этом являясь простой заменой для memcached.

Кроме того, были некоторые радикальные улучшения производительности memcached движка для innodb в предстоящем релизе MySQL 5.7 в особенности для больших мультиядерных систем.

В следующей статье этой серии мы рассмотрим кеширование запросов для дальнейшего повышения производительности.

Источник: https://phpprofi.ru/blogs/post/27

Включение Slow Query Log без перезапуска MySQL

Порой при работе приложений, работающих с бд, возникает падение производительности, в качестве одного из вариантов может быть убогий неоптимизированый запрос, выполняемый дольше чем планировалось. Для отслеживания данных запросов придумали Slow Query Log, состоит журнал из SQL выражений, времени начала запроса, общего времени выполнения, времени блокировки и прочей полезной информации.
Включать данный лог можно на ходу, не перезапуская сервер, единственное что необходимо — доступ на запись для процесса от имени которого будет создан лог-файл.

Логинимся...
mysql -u root -p
Устанавливаем месторасположение лог-файла
mysql> SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
Определям что считать медленным запросом, по-умлочанию 10 секунд, с версии 5.1.21 можно выставить 0, что позволяет собирать все запросы
mysql> SET GLOBAL long_query_time = 5;
Ну и осталось включить
mysql> SET GLOBAL slow_query_log = 'ON';
Еще можно включить логирование запросов неимеющих индексов
mysql> SET GLOBAL log_queries_not_using_indexes = 'ON';

Данные значения будут сохранены до следующей перезагрузки mysql, если необходимо чтобы оно сохрянялось следует добавить в my.cnf

[mysqld]
…
slow_query_log = ON
slow_query_log = /var/log/mysql/slow.log
long_query_time = 5
log_queries_not_using_indexes = ON

Для того что бы узнать текущие значения:

mysql> SHOW GLOBAL VARIABLES LIKE 'slow\_%';
+------------------------------------+-------------------------+
| Variable_name                      | Value                   |
+------------------------------------+-------------------------+
| slow_launch_time                   | 2                       |
| slow_query_log                     | ON                      |
| slow_query_log_file                | /var/log/mysql/slow.log |
| slow_query_log_timestamp_always    | OFF                     |
| slow_query_log_timestamp_precision | second                  |
| slow_query_log_use_global_control  |                         |
+------------------------------------+-------------------------+

mysql> SHOW GLOBAL VARIABLES LIKE 'long_query_time';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 5.000000  |
+-----------------+-----------+

mysql> SHOW GLOBAL VARIABLES LIKE 'log_queries_not_using_indexes';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| log_queries_not_using_indexes | ON    |
+-------------------------------+-------+

Для более детального анализа лучше собирать все запросы, указывая long_query_time = 0, и желательно хотя бы за сутки, а после прогнать их через pt-query-digest из percona-toolkit, который приведет логи к более читаемому виду.

Источник: https://h1d3.org/posts/vkliuchenie-slow-query-log-bez-perezapuska-mysql.html

Как добавить «резиновый» SplashScreen в XE7

Как известно, в XE7 упростили возможность добавления заставки (SplashScreen) для нашего приложения. В этой заметке я расскажу как добавлять «статичную» и «резиновую» заставки. Данная заметка будет интересна тем, кто не умеет читать по-английски или просто не читает справку по студии. По большей части, эта заметка является вольным переводом справочного материала, с некоторыми добавлениями от меня.

Update (14.10.14): Добавил ссылку на архив с примером.
Update (14.10.14): Добавил дополнение к правилу №3 
Update (16.10.14) Добавил информацию о «резиновой» заставке на весь экран (FullScreen)

Общие правила для двух типов заставок.
  1. Картинки добавлять необходимо через меню «Project > Options > Application» вкладка «Artwork». Перед этим, не забудьте выбрать платформу.
  2. Добавляемые картинки должны быть строго определённого разрешения. Это «426×320», «470×320», «640×480», «960×720».
  3. Картинки должны быть в формате «png»
  4. Далее пункты разделяются….

 

Статичная заставка.
Мы можем задать режим отображения картинки (disabled, clamp, repeat, mirror), подробности в Android API
Можем указать «Splash gravity», как отображать картинку, если её размер меньше чем размер экрана.
 
Резиновая заставка.
Данный метод очень хорошо подходит в ситуации, когда вы хотите выводить логотип компании на фоне, цвет которого отличается от чёрного и без растягивания самого логотипа.
 
Чтобы сделать заставку, при которой ваш логотип на картинке будет всегда статичным, а всё остальное будет растягиваться необходимо, создать 9-patch изображения. Данные изображения содержат служебную информацию в четырёх дополнительных пикселях.
 
Изображения содержат информацию о блоках отображения картинки. Это блок масштабирования и блок контента.
  • Блок масштабирования – определяет области изображения, которые будут растягиваться.
  • Блок контента – определяет область изображения, где будет отображаться контент (в нашем случае форма, об этом чуть позже). 

 

Правило №0. Два пикселя (слева и сверху) – говорят о том, какая часть изображения будет растягиваться. Два пикселя (снизу и справа) – определяют область контента.
Правило №1. Всегда готовим картинки с разрешением меньше необходимого на 1 пиксель с каждой стороны. Пример: Нужно добавить 426×320, значит, создаём картинку 424×318.
Правило №2. Пиксели, определяющие блоки, закрашиваются чёрным цветом.
Правило №3. (В нашем случае.) Область контента всегда должна иметь размеры всей картинки. Иначе, в результате неправильной разметки области контента форма будет неправильно отрисовываться. Будьте внимательны с этим правилом, я уже успел попасться на нём.
Дополнение в правилу №3: Если использовать вторую утилиту (об этом ниже), то область контента — это синяя область, а растягиваемая область — это зелёная область.
 
Рассмотрим пример из справки. Картинка в чёрном цвете, но нам сейчас это не важно.
 

Из этого примера следует, что:

  1. Stretchable Area – области изображения, которые будут растягиваться. В данном случае будет растягиваться всё, кроме логотипа (пламени/огня).  
  2. Padding Box – стороны закрашены полностью, а значит область контента равна размеру изображения (Правило №3)

Как это лучше понять, возьмём каждую сторону и мысленно проведём горизонтальные и вертикальные линии от начала и конца каждой чёрной линии. Выглядеть это будет примерно так (белые линии):

Теперь посмотрим утилиты, которые специально разработаны для создания картинок с расширением «.9.png». 
  1. Встроенная утилита «draw9patch», находится тут «C:\Users\Public\Documents\Embarcadero\Studio\15.0\PlatformSDKs\adt-bundle-windows-x86-20131030\sdk\tools\lib». Позволяет открывать png картинки, вручную закрашивать нужные области и сохранять с расширением «.9.png».
  2. Утилита, написанная сторонним разработчиком, пользователем HabraHabr’а. Страничка с описанием утилиты: http://habrahabr.ru/company/alee/blog/136667/. Утилита позволяет разметить области (зелёные (растягиваемые) и синие (контент)), не закрашивая при этом вручную пиксели, всё происходит автоматически. Сохраняет картинки с расширением «.9.png».

 

Я использую вторую утилиту и всем советую её, т.к. очень удобно и быстро.
 
Значит, что мы делаем:
  1. Создаём картинки размерами на 2 пикселя меньше (по ширине и высоте) чем требует студия и сохраняем в png формате
  2. Открываем эти картинки в любой утилите или вообще всё делаем в фотошопе.
  3. Размечаем области и сохраняем с расширением «.9.png»
  4. Добавляем картинки в проект (этот шаг рассмотрен ниже, более подробно)
Добавление «.9.png» картинок в проект:
  1. Заходим в меню «Project > Options > Application»
  2. Выбираем платформу «All configurations – Android platform»
  3. Во вкладке «Artwork», прописываем пути до картинок с расширением «.9.png»
  4. Проверяем галочку «Include splash image», она должна быть установлена
  5. Собираем проект, в «Project Manager» выбираем «Android» и жмём «Build»
  6. Идём в меню «Project > Deployment», выбираем платформу «Debug configuration – Android platform»
  7. Снимаем галочку с файла «splash_image_def.xml»
  8. Далее есть два способа добавления/использования наших новых картинок
Способ №1.
Не забываем снять галочку с файла «splash_image_def.xml».
В «Deployment Manager» находим все наши картинки и меняем имя в столбце «Remote Name», с имени «splash_image.png» на «splash_image_def.9.png» для каждой картинки.
Всё, компилим проект и радуемся.
 
Способ №2.
Этот способ связан с созданием своего файла «splash_image_def.xml».
 
Не забываем снять галочку со стандартного файла «splash_image_def.xml».
Меняем имена картинок в столбце «Remote Name», с имени «splash_image.png» на «splash_image.9.png» для каждой картинки.
Создаём в любом текстовом редакторе (например: Notepad++) файл с именем «splash_image_def.xml» и содержанием:
<?xml version="1.0" encoding="utf-8"?>
<nine-patch
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/splash_image"
android:dither="true"/>
 
Сохраняем в папке с проектом.
Заходим в «Deployment Manager» и добавляем этот файл. В столбце «Remote Name» прописываем имя «splash_image_def.xml» и в столбце «Remote Path» прописываем путь «res\drawable\».
Всё, компилим проект и радуемся.


Update (16.10.14 17:03) Заставка на весь экран (без статус бара)
Выяснилось, что сплешскрин в Delphi XE7 сделан по способу, который я описывал для версии XE5. (XE5: Добавляем Splash Screen в приложение для Android)
Если вы хотите чтобы сплешскрин растягивался на весь экран, т.е. статус бар не было видно, то следующая инструкция для вас:
1) Создаём файл «styles.xml» и прописываем в нём
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="@android:style/Theme.NoTitleBar">
<item name="android:windowBackground">@drawable/splash_image_def</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>
Сохраняем в папке/подпапке с проектом.
2) Заходим в меню «Project > Deployment», снимаем галочку со стандартного файла «styles.xml».
3) Добавляем (деплоим) наш файл «styles.xml», в столбце «Remote Path» прописываем путь «res\values\»
4) Компилим наш проект и наслаждаемся заставкой на весь экран.


Итог: Теперь вы умеете создавать резиновые заставки.

Исходный код: Скачать с Google Drive
Копия второй утилиты: Скачать с Google Drive


Материал на английском языке:
http://docwiki.embarcadero.com/RADStudio/XE7/en/Application_Options#Splash_Images
 
Источник: https://delphifmandroid.blogspot.com/2014/10/splashscreen-xe7.html
P.S. Оказалось все гораздо проще.
Нужно просто заменить в файле splash_image_def.xml, который находится в Android64/Release строчку:
android:drawable="@android:color/black
на 
android:drawable="@android:color/white