Календарні функції в MySQL і MariaDB

Як показує практика, безліч систем з використанням календарів зазвичай будується у вигляді статичних таблиць, в яких перераховані дати і їх відповідність робочим, вихідним, святковим дням. Зазвичай проблеми починаються коли система працює без втручання програмістів досить довго і заповнений календар просто закінчується. Для чергового проекту я вирішив трохи оптимізувати дану ситуацію і написав календар, який створюється або перераховується автоматично, наприклад за вбудованим таймером.
Читати далі →

Інтеграція PostgreSQL з іншими СУБД: робимо запити в MySQL

Нерідко буває так, що у великому проекті в силу тих чи інших причин, найчастіше історичних, хоча буває по-всякому — його частини можуть використовувати різні СУБД для зберігання і пошуку критично важливих даних. У числі іншого, цьому сприяє різноманітності конкуренція і розвиток технологій, але, так чи інакше, взаємодія між СУБД описує стандарт SQL/MED 2003 (Management of External Data), який вводить визначення Foreign Data Wrappers (FDW) і Datalink.
Перша частина стандарту пропонує засоби для читання даних як набору реляційних таблиць під управлінням одного чи кількох зовнішніх джерел; FDW також може представляти можливість використовувати SQL-інтерфейс для доступу до SQL даними, таким, як файли або, наприклад, список листів в поштовій скриньці.
Друга частина, Datalink, дозволяє управляти віддаленим SQL-сервером.
Ці дві частини були реалізовані ще в PostgreSQL 9.1 і називаються FDW і dblink відповідно. FDW в PostgreSQL зроблений максимально гнучко, що дозволяє розробляти wrapper'и для великої кількості зовнішніх джерел. В даний час мені відомі такі FDW, як PostgreSQL, Oracle, SQL Server, MySQL, Cassandra, Redis, RethinkDB, Ldap, а також FDW до файлів типу CSV, JSON, XML і т. п.
У нашій статті ми поговоримо про те, як налаштувати підключення PostgreSQL до MySQL і ефективно виконувати отримані запити.

Читати далі →

Масштабуючи до 100 мільйонів: архітектура, обумовлена рівнем сервісу

Це третя частина циклу «Масштабування Wix до 100 мільйонів користувачів». Вступ і другий пост.

Wix починався з одного сервера, який забезпечував весь функціонал: реєстрацію користувачів, редагування веб-сайтів, обслуговування опублікованих веб-сайтів і завантаження зображень. У свій час цей єдиний сервер був правильним рішенням, оскільки він дозволив нам швидко рости і застосовувати гнучкі методи розробки. Проте до 2008 року почалися періодично повторювані проблеми з розгортанням, які вели до незапланованих простоїв як в створенні нових сайтів, так і в обслуговуванні вже створених.

Розгортання нової версії нашої системи в деяких випадках вимагало зміни схеми MySQL. Оскільки Hibernate не прощає розбіжностей між очікуваною їм схемою і реальною схемою бази даних (БД), ми використовували загальну практику розгортання програмного забезпечення: планова двогодинна зупинка в період найменшого трафіку (опівночі в США на вихідних). За час цієї планової зупинки ми повинні були зупинити сервіс, вимкнути сервер, внести зміни у схему MySQL, розгорнути нову версію і перезапустити сервер.

Ця планова двогодинна зупинка часто перетворювалася в щось більш складне з-за проблем, які могли траплятися при розгортанні. У деяких випадках внесення змін в схему MySQL займало помітно більше часу, ніж планувалося (зміна великих таблиць, перебудова індексів, скасування обмежень на міграцію даних тощо). Іноді після зміни схеми і спроби перезавантажити сервер він не запускався з-за якихось непередбачених проблем з розгортанням, конфігурацією чи схемою, які не давали йому працювати. А в деяких випадках нова версія нашого програмного забезпечення виявлялася непрацездатною, тому для відновлення сервісу нам доводилося знову міняти схему MySQL (щоб привести її у відповідність з попередньою версією) і знову розгортати попередню версію системи.

Читати далі →

Протокол Handlersocket в деталях

Всім здрастуйте. Вирішив опублікувати російську версію своєї статті «HandlerSocket protocol explained», опублікованої за адресою http://wk-photo.ru/en/events/view/handlersocket-protocol-explained/.

image

Отже, ви йшли-йшли і прийшли до HandlerSocket. Чистий мед. Це диявольськи швидкий вуду. А використовуваний протокол реально простий, як дві копійки. Ну і якщо вже начистоту, кому важливі деталі протоколу, якщо все одно буде використовуватися якась бібліотека, яка про все подбає? Якщо, незважаючи ні на що, ви все-таки хочете знати, що за неонка там всередині, можете нагуглити цю сторінку. Кілька годин — і ви експерт. Ну або ви хочете все і за 15 хвилин. Тоді ласкаво поржалувати під кат!


Читати далі →

Партицирование і біль MySQL

Днями довелося робити партицирование. У таблицю кожен день буде додаватися мільйон записів і очікується, що ці записи будуть братися для надання різних звітів і графіків.

Відразу скажу, що робив це не перший раз, до цього успішно робив партицирование у сайту на бітрікс приблизно ось таким чином:

Крок 1. Прибираємо AUTO INCREMENT з таблиці b_iblock_element.
ALTER TABLE b_iblock_element MODIFY ID INT(11) NOT NULL
Крок 2. Видаляємо PRIMARY key з таблиці.
ALTER TABLE b_iblock_element DROP PRIMARY KEY
Крок 3. Створюємо новий PRIMARY KEY, який буде містити минулий ключ і IBLOCK_ID, по якому йде розбивка на partition'и.
ALTER TABLE b_iblock_element ADD CONSTRAINT id_iblock_id PRIMARY KEY (ID,IBLOCK_ID)
Крок 4. Повертаємо AUTO INCREMENT.
ALTER TABLE b_iblock_element MODIFY ID INT(11) NOT NULL AUTO_INCREMENT
Крок 5. Нарешті то робимо розбиттям на 10 частин.
ALTER TABLE b_iblock_element PARTITION BY HASH(IBLOCK_ID) PARTITIONS 10;


Все досить просто. Функція по якій йде розбивка може містити ключі, але всі ці ключі повинні бути в PRIMARY KEY.

Тепер же мені належало розбити іншу таблицю, і хотілося б її розбити відразу по 2 полями: за типом і дату. Причому дату хотілося розбити по місяцях і дані зберігати не більше року.

Читати далі →

Реалізація Blacklist в Asterisk з допомогою БД на MySQL

Якщо ви не використовуєте вже готовий дистрибутив Asterisk як наприклад FreePBX і у вас немає до нього web GUI то завдання додавання номерів в Blacklist зводиться до роботи з AstDB. З цим в принципі все просто. Але база даних Blacklist Asterisk загальна і якщо нам необхідно розмежувати список заблокованих номерів з абонентам то в такому випадку краще вдатися до допомоги зовнішньої БД.

Читати далі →

Spring MVC 3, Аннтоции Hibernate, MySQL. Туторіал по інтеграції

Не так давно я почав вивчати фреймворк Spring і зрозумів, що кількість матеріалу російською мовою обмежено буквально парою стоять статей. По швидкому пробігши, я захотів зробити щось більш цікаве, але отак одразу взяти не вдалося. Довелося погуглити з приводу кількох питань щодо взаємодії Spring і Hibernate. Несподівано я натрапив на блог досить цікавого розробника Mark Serrano aka krams. Тепер разом з вами я хотів би розпочати цикл статей-переказів, а так само своє навчання у світі Spring.

Приступимо…

Читати далі →

Кілька цікавих особливостей MySQL

У не дуже далекому минулому мені довелося трохи покопатися у вихідному коді MySQL, і розібратися в деяких аспектах його роботи. В ході роботи лопаткою, і эксперимнтов, я натрапив на кілька дуже цікавих особливостей, частина з яких просто забавна, а у випадку деяких буває дуже цікаво зрозуміти, чим керувався програміст, який приймав рішення зробити саме так.

Почнемо з такого цікавого типу, як ENUM.

mysql> CREATE TABLE enums(a ENUM('c', 'a', 'b'), INT b, KEY(a));
Query OK, 0 rows affected (0.36 sec)

mysql> INSERT INTO enums VALUES('a', 1), ('b', 1), ('c', 1);
Query OK, 3 rows affected (0.05 sec)
Records: 3 Duplicates: 0 Warnings: 0


Отже, в нас є таблиця, що в ній є два стовпці. У першого, a, тип ENUM, у другого, b, INT. В таблиці три рядки, у всіх трьох значення b 1. Цікаво, чому дорівнюють мінімальний і максимальний елементи в стовпці a?

mysql> SELECT MIN(a), MAX(a) FROM enums;
+--------+--------+
| MIN(a) | MAX(a) |
+--------+--------+
| c | b |
+--------+--------+
1 row in set (0.00 sec)


Здається дивним, було б розумно, якби найменшим був 'a', а найбільшим — 'c'.
А що якщо вибрати мінімум і максимум тільки серед тих рядків, де b = 1? Тобто, серед всіх рядків?

mysql> SELECT MIN(a), MAX(a) FROM enums WHERE b = 1;
+--------+--------+
| MIN(a) | MAX(a) |
+--------+--------+
| a | c |
+--------+--------+
1 row in set (0.00 sec)


Ось так ми змусили MySQL змінити свою думку про те, як порівнювати поля в ENUM, просто додавши предикат.
Розгадка такої поведінки полягає в тому, що в першому випадку MySQL використовує індекс, а в другому ні. Це, звичайно, не пояснює, чому MySQL порівнює ENUMы по-різному для сортування в індексі, що і при звичайному порівнянні.

Другий приклад простіше і лаконічніше:

mysql> (SELECT * FROM moo LIMIT 1) LIMIT 2;
+------+
| a |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.00 sec)


Коли я показав цей запит свого колеги, який займається розробкою програми SQL, його питання було не «чому цей запит повертає два рядки», а «як треба написати SQL парсер так, щоб такий запит був валідним, без того, щоб написати правило, спеціально дозволяє такий запит».

Цікаво, що далеко не будь-SELECT в дужках спрацює, зокрема, UNION в дужках — це синтаксична помилка:

mysql> (SELECT * FROM moo UNION ALL SELECT * FROM hru) LIMIT 2;
ERROR 1064 (42000): You have an error in your SQL syntax; check that the manual corresponds to your MySQL server version for the right syntax to use near 'UNION ALL SELECT * FROM hru) LIMIT 2' at line 1


Ще кілька цікавих прикладів під катом
Читати далі →

Тестування продуктивності форков Mysql на реальних даних

Введення

Назріло апгрейд системи web сервера, на якому з 2007 року крутився сайт інтернет-магазину на самописному движку mysql 5.1 + perl + apache + nginx.

Як правило, при зростанні відвідуваності все стало впиратися в базу даних. Став вибирати нову базу даних, сумісну з поточною. Вибирав з Mysql 5.5, Mysql 5.6, MariaDB 10, Percona Sever 5.6.

Після тривалого вивчення бенчмарків стало зрозуміло, що потрібно тестувати продуктивність на реальних даних. По-перше, в більшості випадків порівнювали InnoDB і XtraDB, по-друге — тестували в основному шалені навантаження на монстр-серверах, цікаві мені показники знаходилися на вузькій ділянці графіка, де зазвичай нічого не було зрозуміло.

Читати далі →