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

2018-10-23

Нови възможности за разработчици в MySQL 8.0.13

Ах, каква седмица вече и още не е приключила! Първо, Oracle пуснаха Oracle XE 18c (както писах в Неделя), а вчера (22-ри Октомври) пристигна MySQL 8.0.13 заедно (както вече обичайно) с целия флот (Router, Shell, Workbench и C++/J/ODBC/NET/Python/Node.js Connectors). Бях нетърпелив да прочета журнала с промените и както посочената статия от блога на MySQL Server също подсказва има някои интересни нови възможности за дизайнери и разработчици. Тук отдолу е моя избор и няколко думи за надграждане от 8.0.12.

Стойностите по подразбиране в SQL вече могат да са също функция или израз

Вече е възможно да има стойности по подразбиране като функция или израз. Това е важна нова възможност. Преди само буквални стойности бяха позволени, което беше доста ограничаващо. Премахването на това ограничение означава, че вече е възможно:
  • да се създават UUID стойности по подразбиране (с използването на DEFAULT (uuid_to_bin(uuid())) например);
  • да се създават стойности по подразбиране за геометрични типове данни (с използването на DEFAULT (POINT(0,0)) или DEFAULT (ST_PointFromText('POINT(42.69751 23.32415)', 4326)) например);
  • да се създават стойности по подразбиране за JSON колони (с използването на DEFAULT (JSON_ARRAY()) или DEFAULT ('[]') например); и
  • други сложни стойности (като DEFAULT (CURRENT_DATE + INTERVAL 1 DAY) or DEFAULT (PI() * POW(r, 2)) например) с използването на функция или функции в израз.
Забележка: Моля, обърнете внимание на скобите обграждащи израза в DEFAULT (виж Handling of Explicit Defaults as of MySQL 8.0.13 в наръчника). MySQL Workbench 8.0.13 отново има някои проблеми с синтактичния разбор на новия синтаксис (виж екранната снима отдолу), така че отворих бъг 92900 и той вече беше потвърден:

MySQL Workbench 8.0.13 грешка с изрази по подразбиране


Пробвах новата функционалност със следното:

CREATE TABLE def_expr (
  id        INT           NOT NULL AUTO_INCREMENT,
  uuid_def  BINARY(16)    DEFAULT (uuid_to_bin(uuid())),
  geo_def   POINT         DEFAULT (Point(0,0)),
  geo_def2  GEOMETRY      DEFAULT (ST_PointFromText('POINT(42.69751 23.32415)', 4326)),
  json_def  JSON          DEFAULT (JSON_ARRAY()),
  json_def2 JSON          DEFAULT ('[]') /* this works too */,
  tomorrow  DATE          DEFAULT (CURDATE() + INTERVAL 1 DAY),
  radius    INT           DEFAULT (FLOOR(1 + (RAND() * 10))),
  area      DECIMAL(10,3) DEFAULT (ROUND(PI() * POW(radius, 2), 3)),

  PRIMARY KEY (id),
  UNIQUE INDEX id_UNIQUE (id ASC) VISIBLE
);



След това вмъкнах две пробни линии и получих следните резултати:

INSERT INTO def_expr VALUES (); /* x 2 */

SELECT id,
       bin_to_uuid(uuid_def) uuid_def,
       ST_AsText(geo_def)    geo_def,
       ST_AsText(geo_def2)   geo_def2,
       json_def, json_def2,
       tomorrow, radius, area
  FROM def_expr;


+----+--------------------------------------+------------+--------------------------+----------+-----------+------------+--------+---------+
| id | uuid_def                             | geo_def    | geo_def2                 | json_def | json_def2 | tomorrow   | radius | area    |
+----+--------------------------------------+------------+--------------------------+----------+-----------+------------+--------+---------+
|  1 | a2747ee0-d6ee-11e8-b02e-02004c4f4f50 | POINT(0 0) | POINT(42.69751 23.32415) | []       | []        | 2018-10-24 |      2 |  12.566 |
|  2 | a2ff920b-d6ee-11e8-b02e-02004c4f4f50 | POINT(0 0) | POINT(42.69751 23.32415) | []       | []        | 2018-10-24 |     10 | 314.159 |
+----+--------------------------------------+------------+--------------------------+----------+-----------+------------+--------+---------+
2 rows in set (0.0021 sec)


Яко, нали? Нетърпелив съм да го пробвам с проектите ми.

Функционални SQL индекси


Вече можете да имате функционални индекси (виж Functional Key Parts в наръчника), което означава, че индекса се изгражда от стойности на изрази, вместо стойности на колони или началната част на стойности на колони. С други думи можете да индексирате стойности, които не са съхранени в таблица, което смятам, че може да бъде доста мощно в определени случаи. В съставни индекси с няколко части на ключа можете да смесвате функционални и нефункционални (обикновени) части. Функционалните части на ключа са реализирани, чрез скрити виртуални породени колони (виж CREATE TABLE and Generated Columns в наръчника), които са налични от MySQL 5.7.6 (от 2015-03-09). Това също така значи, че функционалните части на ключа имат същите ограничения (т.е. детерминирани вградени функции и оператори са разрешени, но подзаявки, параметри, променливи, съхранени и потребителски функци не са разрешени).
За да пробвам новата функционалност се сетих, че IP адреси обичайно се съхраняват като текст в базите и после се четат и разбиват, но адреса може да се представи като целочислена стойност (без знак), което изисква само 4 байта. Така, че използвах следното:

CREATE TABLE func_index (
  id        INT        NOT NULL AUTO_INCREMENT,
  ipaddr4   INT UNSIGNED /* 4 bytes */,

  PRIMARY KEY (id),
  UNIQUE INDEX id_UNIQUE (id ASC) VISIBLE,
  INDEX func_idx ((INET_NTOA(ipaddr4)))
);

Забележка: Моля, обърнете внимание на скобите обграждащи израза. Без тях ще има код 1064 (синтактична грешка). Очаквано MySQL Workbench 8.0.13 не е готов за новия синтаксис, така че отворих бъг 92908 и той също вече беше потвърден.

MySQL Workbench 8.0.13 грешка с функционален индекс

След това вмъкнах една линия и пуснах обяснение на плана за изпълнение на двете SELECT заявки отдолу:

INSERT INTO func_index (ipaddr4) VALUES (INET_ATON('192.168.1.1'));

SELECT * FROM func_index WHERE ipaddr4 = INET_ATON('192.168.1.1');
SELECT * FROM func_index WHERE INET_NTOA(ipaddr4) = '192.168.1.1';

Първата ще доведе до пълно сканиране на таблицата, докато втората ще доведе до четене на функционалния индекс func_idx. За да може заявката да използва индекса е важно израза в WHERE клаузата да съвпада с този в дефиницията на индекса.

Възможност за забрана на създаването на таблици без първичен ключ

Вече има системна променлива sql_require_primary_key, която предотвратява създаването или промяната на таблици без първичен ключ ако е зададена. В този случай CREATE или ALTER зявки вече ще пропадат с код за грешка 3750 (виж също SQL състояние ER_TABLE_WITHOUT_PK).
Пробвах тази нова възможност задавайки глобалната променлива в сесия така:

SET GLOBAL sql_require_primary_key = ON;

но успях да създам таблица без първичен ключ. Трябва да проверя отново утре и евентуално да докладвам бъг. Задаването на променливата в my.ini и след рестартиране на сървъра работи както трябва:

SQL> CREATE TABLE tab_no_pk (test INT);
ERROR: 3750: Unable to create a table without PK, when system variable 'sql_require_primary_key' is set. Add a PK to the table or unset this variable to avoid this message. Note that tables without PK can cause performance problems in row-based replication, so please consult your DBA before changing this setting.

Вече ще си почина от разработчици незапознати с релационната теория :-)

Геометрична трансформация

Вече е възможно да се преобразува геометрия от една пространствена референтна система (SRS) към друга с вградената функция ST_Transform, която приема като втори аргумент целевата SRS. Нямам голям интерес към GIS, така че не съм я пробвал, но изглеждаше, че си струва да бъде спомената.

Няколко думи за надграждането (от 8.0.12)

Надграждането на Windows инсталацията ми беше безпроблемно с MySQL Installer за Windows. Обаче, имах проблем с Linux инсталацията ми, която съдържа повече бази данни. Сървъра не можеше да стартира и в журнала с грешки намерих грешки като следната:

2018-10-23T12:47:49.627732Z 1 [ERROR] [MY-013235] [Server] Error in parsing View 'db'.'aView' during upgrade. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'desc' at line 1

Отворих бъг 92898 за това и проблема вече беше обяснен от поддръжката с несъвместима промяна (виж SQL Syntax Notes от бележките към версията). Почти сигурен съм, че четох някъде за това, че ASC или DESC ключовите думи за GROUP BY клаузата са обявени за архаични и наистина не помня защо съм използвал такъв синтаксис, но ме свари неподготвен, така че се наложи да надградя заявката на изгледите.

Има доста повече в MySQL 8.0.13 и горещо ви препоръчвам да прегледате статията The MySQL 8.0.13 Maintenance Release is Generally Available и бележките към версията, след което да изследвате сами.

    2018-10-21

    Първи впечатления от Oracle Database XE 18c опитвайки се да я инсталирам на Fedora 28 и Oracle Linux 7

    Oracle пусна Oracle Database Express Edition (или по-известна като XE) на 19 Октомври 2018. Тази дата също така се пада и рождения ми ден, така че какъв страхотен подарък! Нека да вземем да отворим подаръка и да го пробваме!
    Чакането за Oracle XE 18c беше дълго като предишната версия (основана на 11g Release 2) се появи преди 7 години (на 24 Септември 2011) а версия основана на Oracle 12c никога не се появи. Използвах XE на Fedora откакто 11g се появи през 2011, но с новите версии на Fedora това стана невъзможно. Базата се държеше странно и не можеше да се ползва след рестарт, но така и не намерих време да разследвам в дълбочина тези проблеми. Така обмислях да пробвам Oracle Linux вместо това (виж Which OS is “the best” for Oracle? за експертно мнение).

    Fedora 28

    Понеже нямам достатъчно място във виртуалната машина изтеглих RPM-ите на сървър и пробвах да ги инсталирам от NFS дял следвайки инструкциите в Quick Start:

    [root@fedora ~]# yum -y localinstall /mnt/vm/oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm
    Last metadata expiration check: 2:01:29 ago on Sun 21 Oct 2018 11:07:06 AM EEST.
    Error:
     Problem: conflicting requests
      - nothing provides compat-libcap1 needed by oracle-database-preinstall-18c-1.0-1.el7.x86_64



    Хмм... Просто липсва необходимия пакет compat-libcap1, но защо не бива инсталиран автоматично?

    [root@fedora ~]# yum install compat-libcap1
    Last metadata expiration check: 1:24:06 ago on Sun 21 Oct 2018 11:07:06 AM EEST.
    No match for argument: compat-libcap1
    Error: Unable to find a match


    Това е странно, но Fedora не предоставя този пакет. Открих го в CentOS хранилището (праяка връзка за изтегляне) и след инсталиране на compat-libcap1 preinstall RPM-а се инсталира успешно. Обаче, инсталацията на базата пропадна:

    [root@fedora ~]# yum -y localinstall /mnt/vm/oracle-database-xe-18c-1.0-1.x86_64.rpm
    Last metadata expiration check: 2:16:29 ago on Sun 21 Oct 2018 11:07:06 AM EEST.
    Dependencies resolved.
    ==========================================================
     Package                Arch   Version Repository    Size
    ==========================================================
    Installing:
     oracle-database-xe-18c x86_64 1.0-1   @commandline 2.4 G

    Transaction Summary
    ==========================================================
    Install  1 Package

    Total size: 2.4 G
    Installed size: 5.2 G
    Downloading Packages:
    Running transaction check
    Transaction check succeeded.
    Running transaction test
    Error: Transaction check error:
      package oracle-database-xe-18c-1.0-1.x86_64 does not verify: no digest
      installing package oracle-database-xe-18c-1.0-1.x86_64 needs 2472MB on the / filesystem


    Error Summary
    -------------
    Disk Requirements:
       At least 2472MB more space needed on the / filesystem.


    Явно изискванията към дисковото пространство са се повишили, защото преди инсталирах XE 11gR2 на същата виртуална машина. Трябваше да уголемя диска и разширя дяла. Обаче, проблема Error: Transaction check error: package oracle-database-xe-18c-1.0-1.x86_64 does not verify: no digest остана, затова писах във форума (виж нишка 14969247).

    За да се справя с това използвах следната команда. Но за да проработи трябваше да инсталирам също така libnsl (т.е. dnf install libnsl) и увелича още веднъж дисковото пространство. Явно инсталацията на RPM-а изисква около 5,2 ГБ.

    [root@fedora ~]# rpm -i --nodigest /mnt/vm/oracle-database-xe-18c-1.0-1.x86_64.rpm
    warning: /mnt/vm/oracle-database-xe-18c-1.0-1.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID ec551f03: NOKEY
    [INFO] Executing post installation scripts...
    [INFO] Oracle home installed successfully and ready to be configured.
    To configure Oracle Database XE, optionally modify the parameters in '/etc/sysconfig/oracle-xe-18c.conf' and then execute '/etc/init.d/oracle-xe-18c configure' as root.


    Така идва време за конфигурация. За създаването на базата са необходими още 4,5 ГБ дисково пространство.

    [root@fedora ~]# /etc/init.d/oracle-xe-18c configure
    Specify a password to be used for database accounts. Oracle recommends that the password entered should be at least 8 characters in length, contain at least 1 uppercase character, 1 lower case character and 1 digit [0-9]. Note that the same password will be used for SYS, SYSTEM and PDBADMIN accounts:
    Confirm the password:
    Configuring Oracle Listener.
    Listener configuration succeeded.
    Configuring Oracle Database XE.
    [WARNING] [DBT-11209] Current available memory is less than the required available memory (796MB) for creating the database.
       CAUSE: Following nodes do not have required available memory :
     Node:fedora            Available memory:471.8672MB (483192.0KB)

    Enter SYS user password:
    *************
    Enter SYSTEM user password:
    *************
    Enter PDBADMIN User Password:
    **************
    Prepare for db operation
    7% complete
    Copying database files
    29% complete
    Creating and starting Oracle instance
    30% complete
    31% complete
    34% complete
    38% complete
    41% complete
    43% complete
    Completing Database Creation
    47% complete
    50% complete
    Creating Pluggable Databases
    54% complete
    71% complete
    Executing Post Configuration Actions
    93% complete
    Running Custom Scripts
    100% complete
    Database creation complete. For details check the logfiles at:
     /opt/oracle/cfgtoollogs/dbca/XE.
    Database Information:
    Global Database Name:XE
    System Identifier(SID):XE
    Look at the log file "/opt/oracle/cfgtoollogs/dbca/XE/XE.log" for further details.

    Connect to Oracle Database using one of the connect strings:
         Pluggable database: fedora:1539/XEPDB1
         Multitenant container database: fedora:1539
    Use https://localhost:5500/em to access Oracle Enterprise Manager for Oracle Database XE


    Забележка: Ако получите  Listener configuration failed. Check log '/opt/oracle/cfgtoollogs/netca/netca_configure_out.log' и в журналния файла присъства линията No valid IP Address returned for the host fedora просто задайте пълното име на машината заедно с домейна в /etc/hostname пуснете конфигурацията отново.

    Същата процедура е приложима към Fedora 29.

    Oracle Linux Server 7.5

    Инсталацията на preinstall RPM-а става гладко:


    [root@oracle ~]# yum -y localinstall /mnt/vm/oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm
    Loaded plugins: ulninfo
    Examining /mnt/vm/oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm: oracle-database-preinstall-18c-1.0-1.el7.x86_64
    Marking /mnt/vm/oracle-database-preinstall-18c-1.0-1.el7.x86_64.rpm to be installed
    Resolving Dependencies
    --> Running transaction check
    ---> Package oracle-database-preinstall-18c.x86_64 0:1.0-1.el6 will be installed
    ...
    --> Processing Dependency: compat-libcap1 for package: oracle-database-preinstall-18c-1.0-1.el6.x86_64
    ...
    Dependencies Resolved

    ====================================================================
     Package                         Arch   Version     Repository Size
    ====================================================================
    Installing:                                                  
     oracle-database-preinstall-18c  x86_64 1.0-1.el7   /oracle... 55 k
    Installing for dependencies:                                 
    ...                                                          
     compat-libcap1                  x86_64 1.10-7.el7  ol7_latest 17 k
    ...
    Install  1 Package (+37 Dependent packages)
    ...
    Installed:
      oracle-database-preinstall-18c.x86_64 0:1.0-1.el7

    Dependency Installed:
    compat-libcap1.x86_64 0:1.10-7.el7
    ...
    Complete!


    Зависимостта от compat-libcap1 беше лесно разрешена както и 36 други зависимости, защото инсталацията ми на Oracle Linux е нова и нямам много инсталирани пакети все още. Инсталацията на RPM-а с базата също стана без проблеми:

    [root@oracle ~]# yum -y localinstall /mnt/vm/oracle-database-xe-18c-1.0-1.x86_64.rpm
    Loaded plugins: ulninfo
    Examining /mnt/vm/oracle-database-xe-18c-1.0-1.x86_64.rpm: oracle-database-xe-18c-1.0-1.x86_64
    Marking /mnt/vm/oracle-database-xe-18c-1.0-1.x86_64.rpm to be installed
    Resolving Dependencies
    --> Running transaction check
    ---> Package oracle-database-xe-18c.x86_64 0:1.0-1 will be installed
    --> Finished Dependency Resolution

    Dependencies Resolved

    ========================================================
     Package                 Arch   Version Repository Size
    ========================================================
    Installing:
     oracle-database-xe-18c  x86_64 1.0-1   /oracle... 5.2 G

    Transaction Summary
    ========================================================
    Install  1 Package

    Total size: 5.2 G
    Installed size: 5.2 G
    Downloading packages:
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : oracle-database-xe-18c-1.0-1.x86_64  1/1
    [INFO] Executing post installation scripts...
    [INFO] Oracle home installed successfully and ready to be configured.
    To configure Oracle Database XE, optionally modify the parameters in '/etc/sysconfig/oracle-xe-18c.conf' and then execute '/etc/init.d/oracle-xe-18c configure' as root.
      Verifying  : oracle-database-xe-18c-1.0-1.x86_64  1/1

    Installed:
      oracle-database-xe-18c.x86_64 0:1.0-1

    Complete!


    И явно около 5.2 GB е мястото, което наистина е необходимо за самия софтуер, защото преди инсталацията имах горе долу толкова повече свободно пространство на дяла. Да се опитаме да конфигурираме базата:

    [root@oracle ~]# /etc/init.d/oracle-xe-18c configure
    The location '/opt/oracle' specified for database files has insufficient space.
    Database creation needs at least '4.5GB' disk space.
    Specify a different database file destination that has enough space in the configuration file '/etc/sysconfig/oracle-xe-18c.conf'.


    Аха... значи изискванията към дисковото пространство са горе долу същите като на Standard Edition on Linux. След преоразмеряване на диска и уголемяване на дяла конфигурацията минава успешно за около 10 минути:

    [root@oracle ~]# /etc/init.d/oracle-xe-18c configure
    Specify a password to be used for database accounts. Oracle recommends that the password entered should be at least 8 characters in length, contain at least 1 uppercase character, 1 lower case character and 1 digit [0-9]. Note that the same password will be used for SYS, SYSTEM and PDBADMIN accounts:
    Confirm the password:
    Configuring Oracle Listener.
    Listener configuration succeeded.
    Configuring Oracle Database XE.
    Enter SYS user password:
    *************
    Enter SYSTEM user password:
    ***************
    Enter PDBADMIN User Password:
    ***********
    Prepare for db operation
    7% complete
    Copying database files
    29% complete
    Creating and starting Oracle instance
    30% complete
    31% complete
    34% complete
    38% complete
    41% complete
    43% complete
    Completing Database Creation
    47% complete
    50% complete
    Creating Pluggable Databases
    54% complete
    71% complete
    Executing Post Configuration Actions
    93% complete
    Running Custom Scripts
    100% complete
    Database creation complete. For details check the logfiles at:
     /opt/oracle/cfgtoollogs/dbca/XE.
    Database Information:
    Global Database Name:XE
    System Identifier(SID):XE
    Look at the log file "/opt/oracle/cfgtoollogs/dbca/XE/XE.log" for further details.

    Connect to Oracle Database using one of the connect strings:
         Pluggable database: oracle.sotirov-bg.net/XEPDB1
         Multitenant container database: oracle.sotirov-bg.net
    Use https://localhost:5500/em to access Oracle Enterprise Manager for Oracle Database XE


    Дори след успешна инсталация и конфигурация има нужда от две ръчни стъпки:
    • Задаване на променливи на средата. За това просто добавих следното в /etc/profile:
    export ORACLE_HOME=/opt/oracle/product/18c/dbhomeXE
    export ORACLE_SID=XE
    pathmunge $ORACLE_HOME/bin after

    • Разрешаване стартирането на базата със системата. За това използвах скрипта предоставен по-подразбиране в /etc/init.d/oracle-xe-18c и пуснах следното:
    chkconfig --add oracle-xe-18c; chkconfig oracle-xe-18c on

    systemctl enable oracle-xe-18c
    • Разрешаване на достъп по мрежата. За това е нужно да се разреши стандартния порт на слушателя 1521 на защитната стена:
    firewall-cmd --permanent --zone=public --add-port=1521/tcp
    systemctl reload firewalld

    Време за връзка с базата:

    [root@oracle ~]# sqlplus sys/password@//localhost:1521/XE as sysdba

    SQL*Plus: Release 18.0.0.0.0 - Production on Sun Oct 21 19:16:35 2018
    Version 18.4.0.0.0

    Copyright (c) 1982, 2018, Oracle.  All rights reserved.

    Connected to:
    Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production
    Version 18.4.0.0.0

    SQL>


    Ура! Сега след като базата е инсталирана и достъпна е време да заредя малко данни и да почвам да експериментирам.