Моят личен и професионален живот

2018-05-30

Първи опити с надграждане на място от MySQL 5.7 до MySQL 8.0

Писах преди, че надграждането на място не е възможно от MySQL 8.0.4 към 8.0.11, но то официално се поддържа между GA версите (но не и през MySQL Installer - виж #90619 и по-скоро #79315). Така че днес направих първите си опити за мигриране на моя MySQL 5.7 сървър до MySQL 8.0 чрез копиране на данните и конфигурацията в Slackware виртуална машина. Да започваме...
  • Първи опти:
2018-05-30T16:42:28.485076Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.11) starting as process 18078
2018-05-30T16:42:28.727435Z 1 [ERROR] [MY-012526] [InnoDB] InnoDB: Upgrade after a crash is not supported. This redo log was created with MySQL 5.7.22. Please follow the instructions at http://dev.mysql.com/doc/refman/8.0/en/upgrading.html
2018-05-30T16:42:28.727509Z 1 [ERROR] [MY-012930] [InnoDB] InnoDB: Plugin initialization aborted with error Generic error.
2018-05-30T16:42:29.228125Z 1 [ERROR] [MY-011013] [Server] Failed to initialize DD Storage Engine.
2018-05-30T16:42:29.228520Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
2018-05-30T16:42:29.228554Z 0 [ERROR] [MY-010119] [Server] Aborting
2018-05-30T16:42:29.235976Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.11)  Source distribution.


Е, наистина си опитах шансовете просто копирайки папката с данни на работещия MySQL 5.7 сървър :-)

Решение: Да се направи чисто копие на папката с данните при спрян сървър.
  • Втори опит:
2018-05-30T16:53:06.475573Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.11) starting as process 18236
2018-05-30T16:53:08.332393Z 0 [Warning] [MY-013129] [Server] A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-001287 - 'validate password plugin' is deprecated and will be removed in a future release. Please use validate_password component instead
InnoDB MEMCACHED: Memcached uses atomic increment
 InnoDB_Memcached: Unable to open table 'innodb_memcache/containers'
 InnoDB_Memcached: Please create config table'containers' in database 'innodb_memcache' by running 'innodb_memcached_config.sql. error Table not found'
Failed to initialize instance. Error code: 13
2018-05-30T16:53:13.256478Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2018-05-30T16:53:13.257272Z 0 [ERROR] [MY-010262] [Server] Can't start server: Bind on TCP/IP port: Address already in use
2018-05-30T16:53:13.257283Z 0 [ERROR] [MY-010257] [Server] Do you already have another mysqld server running on port: 3306 ?

2018-05-30T16:53:13.257298Z 0 [ERROR] [MY-010119] [Server] Aborting
 InnoDB_Memcached: Memcached plugin is still initializing. Can't shut down it.
2018-05-30T16:53:29.161133Z 0 [Warning] [MY-011068] [Server] The syntax 'validate password plugin' is deprecated and will be removed in a future release. Please use validate_password component instead.
2018-05-30T16:53:30.304586Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.11)  Source distribution.


Разбира се, имам друг MySQL 8.0 сървър слушащ на порт 3306, така че нека оправя конфигурацията.

Решение: Смяна на port в конфигурационния файл.
  • Трети опит:
2018-05-30T17:04:57.144549Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.11) starting as process 18571
2018-05-30T17:04:57.523116Z 0 [Warning] [MY-013129] [Server] A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-001287 - 'validate password plugin' is deprecated and will be removed in a future release. Please use validate_password component instead
2018-05-30T17:04:57.630947Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2018-05-30T17:04:57.633668Z 0 [ERROR] [MY-013129] [Server] A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-001146 - Table 'mysql.component' doesn't exist
2018-05-30T17:04:57.633699Z 0 [Warning] [MY-013129] [Server] A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-003543 - The mysql.component table is missing or has an incorrect definition.
2018-05-30T17:04:57.633776Z 0 [ERROR] [MY-011071] [Server] unknown option '--secure-auth'
2018-05-30T17:04:57.633787Z 0 [Warning] [MY-010952] [Server] The privilege system failed to initialize correctly. If you have upgraded your server, make sure you're executing mysql_upgrade to correct the issue.
2018-05-30T17:04:57.633840Z 0 [ERROR] [MY-010119] [Server] Aborting
2018-05-30T17:04:58.636827Z 0 [Warning] [MY-011068] [Server] The syntax 'validate password plugin' is deprecated and will be removed in a future release. Please use validate_password component instead.


Даа, речника на данните все още не е надграден, но за това ми трябва работещ сървър а има още и грешка за непозната конфигурационна директива.

Решение: Премахване на secure-auth директивата от конфигурационния файл, защото беше премахната в 8.0.3 (виж още бележките към версията).
  • Четвърти опит:
2018-05-30T17:06:21.153201Z 0 [ERROR] [MY-011071] [Server] unknown variable 'max_tmp_tables=64'

Решение: Също като отгоре. Премахване на max_tmp_tables директивата от конфигурационния файл.
  • Пети опит:
2018-05-30T17:10:36.750614Z 0 [ERROR] [MY-011071] [Server] unknown variable 'query_cache_type=1'

Дам, забравих, че кеша на заявките е премахнат също...

Решение: Премахване на query_cache_type и query_cache_size директивите от конфигурационния файл, тъй като Query Cache беше премахнат в MySQL 8.
  • Шести опит:
2018-05-30T17:11:18.941821Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.11) starting as process 18803
2018-05-30T17:11:19.333818Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2018-05-30T17:11:19.335972Z 0 [ERROR] [MY-013129] [Server] A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-001146 - Table 'mysql.component' doesn't exist
2018-05-30T17:11:19.336010Z 0 [Warning] [MY-013129] [Server] A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-003543 - The mysql.component table is missing or has an incorrect definition.
2018-05-30T17:11:19.348988Z 0 [Warning] [MY-010929] [Server] Storage engine 'MyISAM' does not support system tables. [mysql.user].
2018-05-30T17:11:19.349014Z 0 [Warning] [MY-010929] [Server] Storage engine 'MyISAM' does not support system tables. [mysql.db].
2018-05-30T17:11:19.349020Z 0 [Warning] [MY-010929] [Server] Storage engine 'MyISAM' does not support system tables. [mysql.tables_priv].
2018-05-30T17:11:19.349026Z 0 [Warning] [MY-010929] [Server] Storage engine 'MyISAM' does not support system tables. [mysql.columns_priv].
2018-05-30T17:11:19.349031Z 0 [Warning] [MY-010929] [Server] Storage engine 'MyISAM' does not support system tables. [mysql.procs_priv].
2018-05-30T17:11:19.349035Z 0 [Warning] [MY-010929] [Server] Storage engine 'MyISAM' does not support system tables. [mysql.proxies_priv].

2018-05-30T17:11:19.352944Z 0 [ERROR] [MY-013143] [Server] Column count of mysql.user is wrong. Expected 49, found 45. The table is probably corrupted
2018-05-30T17:11:19.352980Z 0 [Warning] [MY-010966] [Server] ACL table mysql.role_edges missing. Some operations may fail.
2018-05-30T17:11:19.352987Z 0 [Warning] [MY-010966] [Server] ACL table mysql.default_roles missing. Some operations may fail.
2018-05-30T17:11:19.352992Z 0 [Warning] [MY-010966] [Server] ACL table mysql.global_grants missing. Some operations may fail.
2018-05-30T17:11:19.352997Z 0 [Warning] [MY-010966] [Server] ACL table mysql.password_history missing. Some operations may fail.

2018-05-30T17:11:19.353420Z 0 [ERROR] [MY-010965] [Server] Missing system table mysql.global_grants; please run mysql_upgrade to create it.
2018-05-30T17:11:19.365069Z 0 [Warning] [MY-010727] [Server] System table 'func' is expected to be transactional.
2018-05-30T17:11:19.366847Z 0 [Warning] [MY-010405] [Repl] Info table is not ready to be used. Table 'mysql.slave_master_info' cannot be opened.

2018-05-30T17:11:19.366874Z 0 [ERROR] [MY-010422] [Repl] Error in checking mysql.slave_master_info repository info type of TABLE.
2018-05-30T17:11:19.368238Z 0 [ERROR] [MY-010415] [Repl] Error creating master info: Error checking repositories.
2018-05-30T17:11:19.368273Z 0 [ERROR] [MY-010426] [Repl] Slave: Failed to initialize the master info structure for channel ''; its record may still be present in 'mysql.slave_master_info' table, consider deleting it.

2018-05-30T17:11:19.368280Z 0 [ERROR] [MY-010529] [Repl] Failed to create or recover replication info repositories.
2018-05-30T17:11:19.373821Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.11'  socket: '/var/lib/mysql/mysqld57.sock'  port: 3316  Source distribution.


Успех! Сървъра вече работи, но очевидно има нужда от надгражане, защото има или липсващи системни таблица или такива още на MyISAM. Обаче, не трябва ли това да стане автоматично? Поне оставам с такова впечатления четейки стъпка 8 за In-Place Upgrade в наръчника. Както и да е, стъпка 9 е пускане на mysql_upgrade, така че след пускане на командата грешките в журнала изчезват.

Разбира се, просто си играех, но поне сега имам конфигурационен файл готов за 8.0 и проверих процедурата за надграждане за моя случай. Обаче, трябва да проверя също съвместимостта на приложенията си, така че истинското надграждане ще стане по-нататък.

P.S. Готин начин за проверка на проблеми с конфигурацията е описан в How to check MySQL Config files от Петър Зайцев.

2018-05-28

MariaDB 10.3 добавя още повече възможности за разработка от MySQL 8.0

Миналия петък (25-ти Май) MariaDB 10.3.7 беше пусната като стабилна (General Availability). Най-накрая успях да проверя бележките към версията и (не неочаквано) открих някои възможности, които все още ни липсват в MySQL (дори и в пуснатата преди малко повече от месец 8.0.11 GA за която писах). Искам да подчертая следващите забележителни промени свързани с разработка (от което се интересувам най-много):
  • System-versioned tables (също познато като AS OF);
  • Aggregate stored functions (CREATE AGGREGATE FUNCTION и FETCH GROUP NEXT ROW в цикли);
  • FOR loop (FOR ... DO ... END FOR израз и FOR ... LOOP ... END LOOP израз в sql_mode=ORACLE, виж MDEV-10581 и MDEV-12098);
  • Sequences (като алтернатива на AUTO INCREMENT за "повече контрол на това как се създават числата за идентификатори");
  • INTERSECT и EXCEPT операции за множества;
  • ROW тип данни (за променливи представляващи група от полета - т.е. редове или записи - в съхранени програми);
  • TYPE OF и ROW TYPE OF обвързани типове данни (за променливи представляващи колони или редове в съхранени програми);
  • DELETE и UPDATE изрази базирани на подзаявки по същата таблица;
  • Stored packages (с подобни на Oracle CREATE PACKAGE и CREATE PACKAGE BODY изрази в sql_mode=ORACLE).
Уау. Работили са здраво, това е сигурно. Ще трябва тепърва да пробвам всички тези нови възможности собственоръчно, но съм доста развълнуван да ги видя достъпни в "един от най-популярните сървъри за бази данни". За съжаление, нито една от тези не е достъпна в MySQL. Отдолу е моя списък на това което все още липсва в MySQL (и MariaDB):
Функционалност MariaDB MySQL Стандарт
SQL Модифициране на данни в таблица базирано на подзаявка по същата таблица 10.3.2 (2017-11-09) n/a
EXCEPT или MINUS и INTERSECT оператори за множества 10.3.0 (2017-04-16) n/a SQL:2003
Времеви заявки (AS OF) 10.3.4 (2018-01-18) n/a SQL:2011
DDL CHECK ограничения 10.2.1 (2016-07-04) n/a SQL:1999
Подялба на таблици с външни ключове n/a n/a
Времеви таблици (WITH SYSTEM VERSIONING) 10.3.4 (2018-01-18) n/a SQL:2011
CREATE OR REPLACE за таблици, тригери и съхранени програми 10.0.8 (2014-02-10), 10.1.4 (2015-04-13) и 10.1.3 (2015-03-02) n/a
Разрешаване/забраняване за тригери n/a n/a
Последователности 10.3.0 (2017-04-16) n/a SQL:2003
Работещо преименуване на схеми (RENAME {DATABASE | SCHEMA} израз) n/a n/a
Изгледи Съхраняване на точния израз на изгледа на сървъра n/a n/a n/a
Напълно обновими изгледи с INSTEAD OF тригери n/a n/a SQL:2008
Материализирани изгледи n/a n/a
Съхранени програми Аргументи с подразбираща се стойност n/a n/a
FOR цикъл 10.3.3 (2017-12-23) n/a
Анонимни блокове код (или съставни изрази извън програми) 10.1.1 (2014-10-17) n/a
Записи, типове данни свързани с колона или ред 10.3.0 (2017-04-16) n/a
Съхранени модули или пакети 10.3.5 (2018-02-26) n/a
Тригери на ниво израз или схема n/a n/a
Съоръжения за дебъгване n/a n/a n/a
Външни програми на JavaScript, Perl, PHP, и т.н. n/a n/a

Съвсем ясно е от горната таблица, че MySQL има повече сиви петна от MariaDB. Добавил съм също и съответния SQL стандарт където е приложимо, така че в тази връзка MariaDB има по-широка поддръжка на стандарта. Изглежда ми, че в последната стабилна версия на MariaDB са реализирани повече "подобни на Oracle" възможности, отколкото в MySQL който се разработва от Oracle.
Така че, заслужава ли си да се сменя базата? Вярвам, че ще продължа да ползвам както MySQL така и MariaDB (която е база по подразбиране във всички Linux дистрибуции) и причината за това е, че двете бази стават все по-различни с времето. Има възможности за разработка в MySQL (напр. JSON типа данни, Склада за документи), които не съществуват в MariaDB и обратното. Все още съм доста свикнал с ползването на MySQL Workbench за ежедневна работа с MySQL бази данни, но поддръжката за MariaDB в него чезне и освен ако MySQL не добави същите възможности, се съмнявам, че новите функционалности за разработка ще бъдат използваеми в Workbench, което засяга работата и производителността ми.

2018-05-15

MySQL Shell и автоматичното създаване на идентификтори за документи

Защо получавам грешка ERROR: 5115: Document is missing a required field в MySQL Shell 8.0.11 свързан към MySQL 5.7.22 сървър? Разгледайте следната сесия в която първо се свързвам към сървъра, създавам нова схема, след това колекция вътре в схемата и накрая се опитвам да създам документ без явно да предоставям идентификатор:

MySQL Shell 8.0.11

Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type '\help' or '\?' for help; '\quit' to exit.


MySQL JS> \connect root@server
Creating a session to 'root@
server'
Enter password: ************
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 1027578 (X protocol)
Server version: 5.7.22-log Source distribution
No default schema selected; type \use schema to set one.

MySQL [server+ ssl] JS> session.createSchema('test')
<schema:test>

MySQL [
server+ ssl] JS> \use test
Default schema `test` accessible through db.

MySQL [
server+ ssl/test] JS> per_coll = db.createCollection('persons')
<collection:persons>

MySQL [
server+ ssl/test] JS> per_coll.add({name:'Georgi'})
ERROR: 5115: Document is missing a required field

MySQL [
server+ ssl/test] JS> \py
Switching to Python mode...

MySQL [server+ ssl/test] Py> pcol = db.get_collection('persons')

MySQL [server+ ssl/test] Py> pcol.add({'name':'Georgi'})
ERROR: 5115: Document is missing a required field


В този случай MySQL Shell трябва да създаде идентификатор както е указано в наръчника (виж Наръчника за MySQL 5.7, глава 19.4.4.2 Add Documents), където е написано:
Each document requires an identifier field called _id. The value of the _id field must be unique among all documents in the same collection. If the document passed to the add() method does not contain the _id field, MySQL Shell automatically inserts a field into the document and sets the value to a generated universal unique identifier (UUID).
При свързване към MySQL 8.0 сървър няма такъв проблем:

MySQL Shell 8.0.11

Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type '\help' or '\?' for help; '\quit' to exit.


MySQL JS> \connect root@mysql8
Creating a session to 'root@mysql8'
Enter password: ************
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 6646 (X protocol)
Server version: 8.0.11 Source distribution
No default schema selected; type \use <schema> to set one.

MySQL [mysql8+ ssl] JS> session.createSchema('test')
<schema:test>

MySQL [mysql8+ ssl] JS> \use test
Default schema `test` accessible through db.

MySQL [mysql8+ ssl/test] JS> per_coll = db.createCollection('persons')
<collection:persons>

MySQL [mysql8+ ssl/test] JS> per_coll.add({name:'Georgi'})
Query OK, 1 item affected (0.2450 sec)


MySQL [192.168.79.46+ ssl/test2] JS> per_coll.find()
[
    {
        "_id": "00005adc69630000000000000002",
        "name": "Georgi"
    }
]
1 document in set (0.2035 sec)


Опитах също и с MySQL Shell 1.0 и отново няма проблем:

$ mysqlsh
MySQL Shell 1.0.11

Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type '\help' or '\?' for help; '\quit' to exit.

Currently in Python mode. Use \sql to switch to SQL mode and execute queries.
mysql-py> \connect root@localhost
Creating a Session to 'root@localhost'
Enter password:
Your MySQL connection id is 1028442 (X protocol)
Server version: 5.7.22-log Source distribution
No default schema selected; type \use <schema> to set one.
mysql-py> session.create_schema('test')
<schema:test>
mysql-py> \use test
Schema `test` accessible through db.
mysql-py> pcol = db.create_collection('persons')
mysql-py> pcol.add({'name':'Georgi'})
Query OK, 1 item affected (0.16 sec)
mysql-py> pcol.find()
[
    {
        "_id": "aa0960462c58e811b27610feed07afc3",
        "name": "Georgi"
    }
]
1 document in set (0.00 sec)


Публикацията MySQL Document Store Document IDs. на Dave Stokes е първия (и всъщност единствен) резултат в Google за грешката (при търсене за точно съвпадение с двойни кавички). Публикацията насочва към глава 5.1.1 Understanding Document IDs от X DevAPI User Guide, където четем:
X DevAPI relies on server based document ID generation, added in MySQL version 8.0.11, which results in sequentially increasing document IDs across all clients.
...
Whenever an _id field value is not present in an inserted document, the server generates an _id value.
Която изяснява проблема. Явно, MySQL Shell 8.0.11 очаква сървъра да създаде идентификатор (за колоната _id) без да взима в предвид дали той е версия 5.7 или 8.0, което за мен е бъг, който трябва да докладвам по-късно.

Обновяване 2018-05-16: Oracle провериха бъг доклада ми (виж bug 90876). Надявам се, че ще бъде оправен.

2018-05-01

Миграция към Git и GitHub

Преди няколко години реших да мигрирам всичките си лични проекти към разпределена система за контрол на версиите (РСКВ), но така и не намерих времето за това. В днешно време Git е де факто стандарт за контрол на версиите затова реших да мигрирам към Git и кача всичките си проекти в GitHub. Така че тази година постепенно ще мигрирам проектите си, започвайки с най-малко активните. Повечето от тях са все още на CVS, което прави миграцията по-сложна като се има в предвид, че CVS и Git са доста различни в много отношения, но също така защото за мен е важно да запазя историята на промените си (т.е. не искам просто да копирам кода и инициализирам ново Git хранилище вътре). Пожелайте ми успех и ми стискайте палци ;-)