Skip to main content

Introdução


Vamos aprender a trabalhar com manipulação de dados em um banco de dados, esse documento não visa tornar nenhuma pessoa um dba, apenas mostra conceitos de como trabalhar com Database, fazer migração, criação de tabelas, etc.


MySql vs MariaDB


O MariaDb é licenciado pela GPL, enquanto que o MySql tem dupla licença. Cada um lida com pools de threads de maneira diferente. O MariaDB por ser open source se torna melhor na maioria dos casos.


Os passos a seguir servem tanto para MySql quanto para o MariaDB, já que mariadb é um fork do MySql.



O que é SQL?


O SQL é a linguagem usada para geração, manipulação e recuperação de dados dentro de um banco de dados relacional. O SQL é dividido em algumas categorias:

  • Schema Statement

    São instruções usadas para criar objetos de bando de dados (montar a base ou esqueleto da tabela), aqui entram a criações de tabelas, índices, restrições e muito mais.

  • Data Statement

    São instruções usadas para criar, manipular e recuperar dados armazenados no banco.

  • Transaction Statement

    São instruções usadas para iniciar, encerrar e desfazer transações.



Instruções de dados SQL


O SQL possui 4 instruções de dados, sendo: insert, update, delete e select.



Insert


A instrução insert é usada para inserir dados numa tabela, é através dessa instrução que vamos adicionando dados na tabela.


O insert tem a seguinte estrutura:

# Estrutura:
INSERT INTO tabela (colunas)
VALUES (valores)


#### Exemplo ####

## Listando a estrutura da tabela:
mysql> desc employees;
+------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| birth_date | date | NO | | NULL | |
| first_name | varchar(14) | NO | | NULL | |
| last_name | varchar(16) | NO | | NULL | |
| gender | enum('M','F') | NO | | NULL | |
| hire_date | date | NO | | NULL | |
+------------+---------------+------+-----+---------+-------+
6 rows in set (0.002 sec)


## Listando os 2 ultimos valores:
mysql> select * from
-> (select * from employees ORDER BY emp_no DESC LIMIT 2)
-> sub ORDER BY emp_no ASC;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 499998 | 1956-09-05 | Patricia | Breugel | M | 1993-10-13 |
| 499999 | 1958-05-01 | Sachin | Tsukuda | M | 1997-11-30 |
+--------+------------+------------+-----------+--------+------------+
2 rows in set (0.001 sec)


# Inserindo Dados:
INSERT INTO employees (emp_no, birth_date, first_name, last_name, gender, hire_date)
VALUES ('500000', '1996-09-05', 'Joao', 'Nogueira', 'M', '2021-01-05');
Query OK, 1 row affected (0.009 sec)


## Listando os 2 ultimos valores:
mysql> select * from
-> (select * from employees ORDER BY emp_no DESC LIMIT 2)
-> sub ORDER BY emp_no ASC;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 499999 | 1958-05-01 | Sachin | Tsukuda | M | 1997-11-30 |
| 500000 | 1996-09-05 | Joao | Nogueira | M | 2021-01-05 |
+--------+------------+------------+-----------+--------+------------+
2 rows in set (0.001 sec)


Update


Caso seja necessário fazer alguma alteração nas informações que já estejam na tabela, usamos a instrução update, com isso vamos mudar apenas o sobrenome do funcionário que adicionamos:

# Atualizando o sobrenome:
mysql> UPDATE employees
-> SET last_name = 'Nogueira Junior'
-> WHERE emp_no = '500000' AND first_name = 'Joao';
Query OK, 1 row affected (0.011 sec)
Rows matched: 1 Changed: 1 Warnings: 0


## Listando os 2 ultimos valores:
mysql> select * from
-> (select * from employees ORDER BY emp_no DESC LIMIT 2)
-> sub ORDER BY emp_no ASC;
+--------+------------+------------+-----------------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------------+--------+------------+
| 499999 | 1958-05-01 | Sachin | Tsukuda | M | 1997-11-30 |
| 500000 | 1996-09-05 | Joao | Nogueira Junior | M | 2021-01-05 |
+--------+------------+------------+-----------------+--------+------------+
2 rows in set (0.001 sec)


Delete


A instrução delete é usada para deletar um dado da tabela, vamos deletar o funcionário que acabamos de adicionar:

# Deletando:
mysql> DELETE from employees
-> WHERE emp_no = '500000' AND first_name = 'Joao';
Query OK, 1 row affected (0.010 sec)


## Listando os 2 ultimos valores:
mysql> select * from
-> (select * from employees ORDER BY emp_no DESC LIMIT 2)
-> sub ORDER BY emp_no ASC;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 499998 | 1956-09-05 | Patricia | Breugel | M | 1993-10-13 |
| 499999 | 1958-05-01 | Sachin | Tsukuda | M | 1997-11-30 |
+--------+------------+------------+-----------+--------+------------+
2 rows in set (0.001 sec)


Select


A instrução select já vem sendo usada, sua função é exibir informações que estejam nas tabelas.



O que é um banco de dados?


Um banco de dados é apenas um conjunto de informações relacionadas umas com as outras.



Tipos de chaves de um banco de dados


No banco de dados, mais precisamente nas tabelas, trabalhamos com alguns tipos de chaves.



Chave primária


É uma dado que identifica de forma única na tabela uma informação, normalmente usamos algo contendo a informação id, como account_id, user_id e por ai vai.

As colunas de uma primária nunca devem ter seus valores alterados após a atribuição inicial.

Para definir uma chave primária, usamos o exemplo abaixo:

CONSTRAINT <NOME> PRIMARY KEY (<COLUNA>)

NOME é o nome que vamos dar e COLUNA é qual a coluna vai ser responsável por ser chave primária.

EX: CONSTRAINT pk_pessoa PRIMARY KEY pessoa_id



Chave composta


É uma chave primária, mas consiste em duas ou mais colunas.



Chave estrangeira


São informações de uma tabela que levam para outras tabelas, são como chaves primárias de uma tabela dentro de outra tabela, e com essa informação podemos mapear os dados dentre várias tabelas.

Para definir uma chave estrangeira, usamos o exemplo abaixo:

CONSTRAINT <NOME> FOREIGN KEY (<COLUNA>)

Uma tabela com uma chave entrangeira só vai poder adicionar uma informação na tabela se uma referencia não existir na tabela que estamos pegando a COLUNA.



Tipos de dados


Tanto no SQL quanto em linguagens de programação, existem tipos de dados, ou tipos de variáveis como é mais comumente chamado, cada tipo permite uma aplicação diferente.



Dados do tipo caractere


Os dados do tipo caractere podem ser armazenados como strings de tamanho fixo ou variável, a diferença é:

  • Strings de tamanho fixo

    São sempre preenchidas a direita com espaços e sempre consomem a mesma quantidade de bytes para armazenar.

  • Strings de tamanho variável

    Nem sempre consomem a mesma quantidade de bytes para armazenar e não são preenchidas a direita com espaços.


Existem dois tipos de variáveis para caracteres, são eles:

  • CHAR

    Possui o valor máximo de colunas sendo 255 bytes. Indicado quando se sabe o tamanho da string que vai ser armazenado como abreviação de estado (SP, MG, RJ etc).

  • VARCHAR

    Possui o valor máximo de colunas sendo 65.535 bytes, é muito indicado para armazenar e-mails, documentos XML e etc. Indicado quando não se sabe o tamaho da string.


Segue um exemplo de como definir os dados acima:

VARCHAR(40)
CHAR(15)

No exemplo acima, os valores são a quantidade máxima de caracteres que serão armazenados, com a diferença que no char(15), caso seja armazenado apenas 1 caractere, serão reservados mais 14 espaços vazios, enquanto que no varchar será alocado apenas 1 espaço para o caractere armazenado.



Conjunto de caracteres


Aqui entram o tipo de caractere que poderá ser armazenado no sentido de linguagem, pois existem muitos idiomas e podemos configurar qual tipo de caractere vai ser armazenado (seria como configurar qual idioma será reconhecido ou algo do tipo).

# Listar os caracteres reconhecidos pelo banco:

MariaDB [(none)]> show character set;
+----------+-----------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+-----------------------------+---------------------+--------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| hp8 | HP West European | hp8_english_ci | 1 |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 |
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| swe7 | 7bit Swedish | swe7_swedish_ci | 1 |
| ascii | US ASCII | ascii_general_ci | 1 |
| ujis | EUC-JP Japanese | ujis_japanese_ci | 3 |
| sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 |
| hebrew | ISO 8859-8 Hebrew | hebrew_general_ci | 1 |
| tis620 | TIS620 Thai | tis620_thai_ci | 1 |
| euckr | EUC-KR Korean | euckr_korean_ci | 2 |
| koi8u | KOI8-U Ukrainian | koi8u_general_ci | 1 |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 |
| greek | ISO 8859-7 Greek | greek_general_ci | 1 |
| cp1250 | Windows Central European | cp1250_general_ci | 1 |
| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | 1 |
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |
| cp866 | DOS Russian | cp866_general_ci | 1 |
| keybcs2 | DOS Kamenicky Czech-Slovak | keybcs2_general_ci | 1 |
| macce | Mac Central European | macce_general_ci | 1 |
| macroman | Mac West European | macroman_general_ci | 1 |
| cp852 | DOS Central European | cp852_general_ci | 1 |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci | 4 |
| cp1251 | Windows Cyrillic | cp1251_general_ci | 1 |
| utf16 | UTF-16 Unicode | utf16_general_ci | 4 |
| utf16le | UTF-16LE Unicode | utf16le_general_ci | 4 |
| cp1256 | Windows Arabic | cp1256_general_ci | 1 |
| cp1257 | Windows Baltic | cp1257_general_ci | 1 |
| utf32 | UTF-32 Unicode | utf32_general_ci | 4 |
| binary | Binary pseudo charset | binary | 1 |
| geostd8 | GEOSTD8 Georgian | geostd8_general_ci | 1 |
| cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2 |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | 3 |
+----------+-----------------------------+---------------------+--------+
40 rows in set (0.002 sec)


# Listar o charset dos bancos criados dentro do SQL:
MariaDB [(none)]> SELECT SCHEMA_NAME 'database', default_character_set_name 'charset',
-> DEFAULT_COLLATION_NAME 'collation' FROM information_schema.SCHEMATA;
+--------------------+---------+--------------------+
| database | charset | collation |
+--------------------+---------+--------------------+
| information_schema | utf8 | utf8_general_ci |
| mysql | utf8mb4 | utf8mb4_general_ci |
| performance_schema | utf8 | utf8_general_ci |
| foreign_sales | utf8 | utf8_general_ci |
| employees | utf8mb4 | utf8mb4_general_ci |
+--------------------+---------+--------------------+
5 rows in set (0.005 sec)


# Listar todas as colunas de uma tabela (e ver o charset 'Collation'):
mysql> SHOW FULL COLUMNS FROM departments;
+-----------+-------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-----------+-------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| dept_no | char(4) | utf8mb4_general_ci | NO | PRI | NULL | | select,insert,update,references | |
| dept_name | varchar(40) | utf8mb4_general_ci | NO | UNI | NULL | | select,insert,update,references | |
+-----------+-------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
2 rows in set (0.004 sec)

Durante a criação de uma tabela, podemos específicar o charset de uma coluna com o exemplo abaixo:

varchar(10) character set utf8mb4

Para definir isso para todo o banco de dados, você pode colocar no arquivo de configuração, na sessão [mysqld] ou através do comando create database foreign_sales character set utf8mb4.



Dados de Texto


É usado quando o varchar não da mais conta, pois com o tipo texto, podemos exceder o limite de 64KB do varchar, existem alguns tipos de texto, são eles:

Tipo de textoNumero máximo de bytes
Tinytext255
Text65.535
Mediumtext16.777.215
Longtext4.294.967.295


Dados numéricos


Os dados do tipo numérico não se classificam apenas pela quantidade de informações que podem guardar, mas o tipo de números que podem guardar (se tem pontuação ou não).


Existem 2 tipos de dados principais que vamos querer guardar, são eles:

  • Int

    São números inteiros, ou seja, não aceitam casas decimais.

    Para números do tipo Int podemos marcar eles como sendo unsigned, isso indica ao servidor que os dados armazenados serão maiores ou iguais a 0.

  • Float

    Esse tipo de dado permite o uso de casas decimais, como 10.35.

  • Boolean

    Similar ao mesmo tipo em programação, seu estado se define a True (verdadeiro) ou False (falso), mas nesse caso, utiliza números para essa simbologia, como 1 ou 0.


O valores do tipo Int possuem vários tipos, onde cada tipo armazena uma grande quantidade de valores:

TipoEscopo com sinalEscopo sem Sinal
Tinyint-128 a 1270 a 255
Smallint-32.768 a 32.7670 a 65.535
Mediumint-8.388.608 a 8.388.6070 a 16.777.215
Int-2.147.483.648 a 2.147.483.647a 0 4.294.967.295
Bigint-9.223.372.036.854.775.808 a 9.223.372.036.854.775.8070 a 18.446.744.073.709.551.615

Definindo valores:

# Criando dados do tipo INT, o número 3 indica apenas que alguns aplicativos que consultarem o banco vão exibir apenas 3 dígitos, mas podem ser armazenados muito mais que 3 dígitos. 
int(3)

# Permitindo no máximo 4 digitos, dois a esquerda e dois a direita da vírgula:
float(4,2)

# Mesmo que o int, mas armazena uma grande quantidade de valores.
BIGINT


Dados temporais


Trata-se de dados como a hora e data do sistema. Existem alguns tipos como podemos ver abaixo:

TipoFormato
DateAAA-MM-DD
DatetimeAAA-MM-DD HH:MI:SS
TimestampAAA-MM-DD HH:MI:SS
YearAAA
TimeHH:MI:SS
Linux TimestampNNNNNNNNN

Pode-se usar os comandos abaixo para obter os valores mostrado na coluna Exemplos:

# Listando o Timestamp do Linux:
MariaDB [(none)]> SELECT UNIX_TIMESTAMP();
+------------------+
| UNIX_TIMESTAMP() |
+------------------+
| 1641399860 |
+------------------+
1 row in set (0.000 sec)


# Listando o timestamp atual:
MariaDB [(none)]> SELECT CURRENT_TIMESTAMP;
+---------------------+
| CURRENT_TIMESTAMP |
+---------------------+
| 2022-01-05 16:23:00 |
+---------------------+
1 row in set (0.001 sec)


# Listando o time atual:
MariaDB [(none)]> SELECT CURRENT_TIME;
+--------------+
| CURRENT_TIME |
+--------------+
| 16:25:12 |
+--------------+
1 row in set (0.000 sec)


# Listando o date atual:
MariaDB [(none)]> SELECT CURRENT_DATE;
+--------------+
| CURRENT_DATE |
+--------------+
| 2022-01-05 |
+--------------+
1 row in set (0.000 sec)


Instalação


Vamos instalar o MySQL, um sistema de banco de dados relacional..

## Para instalar o MySQL:
$ apt-get install mysql-server

## Para instalar o MariaDB:
$ apt-get install mariadb-server
# ou "yum install mariadb-server" caso esteja utilizando um sistema baseado em RedHat

## Configuração básica e primordial do MySQL:
$ sudo mysql_secure_installation

Set root password? [Y/n] n
Remove anonymous users? [Y/n] n
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] n
Reload privilege tables now? [Y/n] Y
# Estas foram as opções que eu escolhi para tornar o uso o mais fácil possível. Se quiser definir senhas e outras configurações, fique a vontade.

As perguntas feitas acima são:

1 - O Script nos apresenta o Validate Password Componnent, um componente do MySQL usado para validar senhas, verificando se as senhas são seguras.

2 - Você deve definir a força da senha, entre: 0 = low, 1 = medium e 3 = strong. Depois de escolher a força da senha, você deve definir uma senha.

3 - O script quer saber se deseja continuar com a senha fornecida.

4 - Informa que o MySQL tem um usuário anônimo, permitindo que qualquer pessoa consiga logar e que isso é apenas para teste, e pergunta se desejamos remover esse usuário.

5 - É informado que o root deve logar apenas em localhost (conectado localmente na máquina) e pergunta se desejamos remover o acesso root via rede.

6 - Pergunta se desejamos recarregar as tabelas de privilégio para certificar das mudanças imediatamente.



Instalar um Banco de Dados de Exemplo


Para facilitar os estudos, vamos fazer o download e importar para o banco uma base de dados e tabelas já criadas que podemos encontrar no GitHub.

# Baixa o db:
wget https://github.com/datacharmer/test_db/archive/master.zip

# Descompacte:
unzip master.zip

# Entre na pasta:
cd test_db-master

# Importe o db:
mysql -u root < employees.sql

# Listando os databases sem entrar no mysql (mariadb):
$ sudo mysqlshow
+--------------------+
| Databases |
+--------------------+
| employees |
| information_schema |
| mysql |
| performance_schema |
+--------------------+


Passos iniciais com o banco


# Acessando o db:
$ sudo mysql -u root
## Caso tenha colocado senha, coloque a opção '-p':
$ sudo mysql -u root -p

# Entre no banco chamado emplyees:
MariaDB [(none)]> use employees;
Database changed

# Liste as tabelas existentes dentro do nosso banco de dados:
mysql> show tables;
+----------------------+
| Tables_in_employees |
+----------------------+
| current_dept_emp |
| departments |
| dept_emp |
| dept_emp_latest_date |
| dept_manager |
| employees |
| salaries |
| titles |
+----------------------+
8 rows in set (0.001 sec)

# Liste a estrutura da tabela, vamos ver informações contidas nas colunas de uma tabela:
mysql> describe departments;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| dept_no | char(4) | NO | PRI | NULL | |
| dept_name | varchar(40) | NO | UNI | NULL | |
+-----------+-------------+------+-----+---------+-------+
2 rows in set (0.003 sec)

# Liste algumas informações:
mysql> select dept_no,dept_name from departments;
+---------+--------------------+
| dept_no | dept_name |
+---------+--------------------+
| d009 | Customer Service |
| d005 | Development |
| d002 | Finance |
| d003 | Human Resources |
| d001 | Marketing |
| d004 | Production |
| d006 | Quality Management |
| d008 | Research |
| d007 | Sales |
+---------+--------------------+
9 rows in set (0.002 sec)
# Estrutura: select <CAMPOS> from <TABELA>;
# Você pode mudar colocar um '*' no lugar de <CAMPOS>, assim ele vai mostrar todas as tabelas.


Replicação


Master/Slave - Assíncrona

A replicacao mais simples é chamado de master/slave.


O slave vai ler o master e pedir para sincronizar, esse tipo de conexao é chamada de assincrona, isso significa que caso o Slave fique fora do ar, ou a conexao caia, quando subir ele sincroniza de novo e baixa somente o que mudou.


  • SBR (Statement Base Replication)

    É uma replicacao baseada em comando, ou seja, 'e gravado o comando em si no log binario, e quando o slave ler isso, ele vai executar o mesmo comando.


  • RBR (Row Base Replication)

    É uma replicacao baseada em linha, ou seja, 'e criado um registro e esse registro 'e gravado no binlog, o slave copia o registro do binlog para o relaylog.


  • MBR (Mixed Base Replication)

    Replicacao de base mista, o servidor vai decidir qual passo acima ser'a melhor, baseado em transacoes seguras ou inseguras.



Slave/Master - Assíncrono


Um Slave possui varios Masters e sincroniza com os bancos de dados de todos os masters, criando um sistemas de backup onde todo os bancos de todos os Masters ficam centralizalidos em apenas uma máquina.


PS.: Apenas os bancos de dados escolhidos são sincronizados.



Master/Slave - Semi-sincrono (via plugin)


Só habilita a escrita no banco do Master quando ao menos 1 Slave confirmar que está sincronizado, se nenhum dos Slave que temos confirmar, a escrita vai ficar pendente até dar erro por timeout ou até um Slave confirmar a sincronização.



Master/Master - Assíncrono


Um Master replica para outro Master, ainda temos os Masters criando o binlog em ambos os masters, e ao mesmo tempo, os masters lendo o relaylog, isso porque eles são Master e Slave ao mesmo tempo.


----------- -----------
| | | |
| Master 1 | | Master 2 |
| BinLog | | BinLog |
| | <-----------> | |
| Slave | | Slave |
| RelayLog | | RelayLog |
| | | |
----------- -----------

Vamos ver um exemplo da configuração em dois servidores:

- Server 1 (/etc/mysql/mysql.conf.d/mysqld.cnf)

server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
log_bin_index = /var/log/mysql/mysql-bin.log.index
relay_log = /var/log/mysql/mysql-relay-bin
relay_log_index = /var/log/mysql/mysql-relay-bin.index
binlog_do_db = banco
expire_logs_days = 10
max_binlog_size = 500M
log_slave_updates = 1
auto-increment-increment = 2
auto-increment-offset = 1


- Server 2 (/etc/mysql/mysql.conf.d/mysqld.cnf)

server-id = 2
log_bin = /var/log/mysql/mysql-bin.log
log_bin_index = /var/log/mysql/mysql-bin.log.index
relay_log = /var/log/mysql/mysql-relay-bin
relay_log_index = /var/log/mysql/mysql-relay-bin.index
binlog_do_db = banco
expire_logs_days = 10
max_binlog_size = 500M
log_slave_updates = 1
auto-increment-increment = 2
auto-increment-offset = 2

Explicando algumas opções:

  • auto-increment-increment

    O incremento normalmente é de 1 em 1, nesse caso, vamos incrementar o incremento, basicamente o incremento passa a ser de 2 em 2:

    auto-increment-increment = 2


  • auto-increment-offset

    Basicamente é o ID do primeiro registro, nesse caso será 1, mas no server 2 será 2:

    auto-increment-offset = 1

Dessa forma, nunca teremos um registro em um servidor que tenha o mesmo id em outro, criando complicações e problemas no banco.

Server 1             Server 2

registro1 = id1 registro1 = id2
registro2 = id3 registro2 = id4
registro3 = id5 registro3 = id6

  • binlog_do_db

    Diz qual o banco de dados vamos replicar.


Criar um usuário com os seguintes privilégios:

Server 1> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'IP-Server2' IDENTIFIED BY 'SENHA';
Server 1> FLUSH TABLES WITH READ LOCK;
Server 1> SHOW MASTER STATUS;
## anotar master_log_file e master_log_pos

Server 2> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'IP-Server1' IDENTIFIED BY 'SENHA';
Server 2> FLUSH TABLES WITH READ LOCK;
Server 2> SHOW MASTER STATUS;
## anotar master_log_file e master_log_pos

Se nao funcionar:
# Server 1> create user 'repl'@'192.168.121.159' IDENTIFIED BY "wfepowponwpog";
# Server 1> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.121.159';

# Informar no master 2 que ele é slave do master1:
Server 2> STOP SLAVE;
Server 2> CHANGE MASTER TO master_host='IP-server1', master_user='repl', master_password='xxx', master_log_file='mysql-bin.xxx', master_log_pos=xxx;
Server 2> START SLAVE;

# Informar no master 1 que ele é slave do master2:
Server 1> STOP SLAVE;
Server 1> CHANGE MASTER TO master_host='IP-server2', master_user='repl', master_password='senha', master_log_file='mysql-bin.xxx', master_log_pos=xxx;
Server 1> START SLAVE;

____________________________________________________________________________________________________
master1 = 192.168.121.159
master2 = 192.168.121.89
____________________________________________________________________________________________________
EXEMPLO DO SERVER 1
____________________________________________________________________________________________________
Server 1> create user 'repl'@'192.168.121.89' IDENTIFIED WITH mysql_native_password BY "wfepowponwpog";
Server 1> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.121.89';
Server 1> FLUSH TABLES WITH READ LOCK;
Server 1> SHOW MASTER STATUS;
## anotar master_log_file e master_log_pos
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 726 | banco | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)


# Informar no master 1 que ele é slave do master2:
Server 1> STOP REPLICA;
Server 1> CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.168.121.89', SOURCE_USER='repl', SOURCE_PASSWORD='wfepowponwpog', SOURCE_LOG_FILE='mysql-bin.000001', SOURCE_LOG_POS=0;
Server 1> START REPLICA;

SHOW REPLICA STATUS \G
____________________________________________________________________________________________________
EXEMPLO DO SERVER 2
____________________________________________________________________________________________________
Server 2> create user 'repl'@'192.168.121.159' IDENTIFIED WITH mysql_native_password BY "wfepowponwpog";
Server 2> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.121.159';
Server 2> FLUSH TABLES WITH READ LOCK;
Server 2> SHOW MASTER STATUS;
## anotar master_log_file e master_log_pos
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 698 | banco | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

# Informar no master 2 que ele é slave do master1:
Server 2> STOP REPLICA;
Server 2> CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.168.121.159', SOURCE_USER='repl', SOURCE_PASSWORD='wfepowponwpog', SOURCE_LOG_FILE='mysql-bin.000001', SOURCE_LOG_POS=0;
Server 2> START REPLICA;

SHOW REPLICA STATUS \G


Replicacao de dados (Group replication)


Temos vários Masters dentro de um grupo, quando algum Master desse grupo recebe uma escrita, o grupo precisa dizer se isso é válido ou não.



Replicacao de dados (InnoDB Cluster)


Ainda temos um grupo de servers, vamos ter um servidor com o MysQL Router, ele vai decidir qual servidor do grupo vai ser a instância primária, e com isso vai redirecionar as requisições para ela, muito boa para ter uma alta disponibilidade, a conexão do cliente é feita com o MysQL Router e não com servidor onde está o banco de dados.



Arquivos gerados pelo MySQL


Para isso, vamos analisar o conteúdo da pasta do mysql em /var/lib/mysql, que é a pasta padrão que o MySQL usa para manter os diversos arquivos.

ArquivosDescrição
auto.cnfSe não existir, vai ser criado sempre que o servidor do mysql for iniciado.
Se já existir, vai ser lido, nele temos o UUID do MySQL, usado principalmente em replicação (nao deve ser apagado).
binlog*São logs do MySQL que contém além de tudo as transações e muitos outros logs (É muito usado para replicação).
Em alguns crashs o server pode ler esses arquivos para se recuperar. Aqui podemos escolher 3 formatos de registros:

- raw
Mostra a linha do mysql que foi alterada.

- Statement
Mostra o comando que foi usado para fazer a alteração.

- Mixed
Usa os dois formatos acima.
*.pemCertificado usado pelo Mysql no SSL.
*.errContém os erros do mysql.
ib_buffe_poolGrava ponteiros, mapas para subir o server mais rapidamente.
ib_logfileContém instruções que alteram o SQL, assim caso tenha algum crash, o sistema consegue se recuperar.
ibdataOnde os dados são propriamente gravados, relacionado ao Table Space.
ibtmpMesma coisa acima, mas para tabelas temporárias que não são necessárias para o funcionamento do mysql.
mysql.ibdÉ um table space que grava bastante informação, antigamente ficava no arquivo 'mysql'.
undo_*Responsável pelo controle de transação, commit, rollback, pode ser colocado em outro disco.
''#innodb_temp'É um diretório usado em conjunto com o ibtmp para criação de tabela temporária.
mysqlÉ um diretório.

- general_log.csm
São logs gerais.

- slow_log
Grava tudo que demore, como uma consulta, uma alteração no banco.
performance_schemaContém informações do server, como erros, stages etc.


MySQL Router


O MySQL Router é muito usado para alta disponibilidade e escalabilidade, roteando o tráfego do in/out do banco de dados para outros servidores mysql.



MySql Schema


Vamos ver algumas informações sobre o Schema do MySQL.


Data Dictionaries Tables


Guarda informações de Objetos como: Tabelas, Colunas, indices etc. Antigamente era guardado em arquivos.


Uma forma de ver as tabelas aqui é usando o comando select * from INFORMATION_SCHEMA.<TABELA>;, vamos ver algumas dessas tabelas abaixo:

TabelaDescrição
CatalogsContém informações de catálogos (é o dicionário de dados).
character_setsContém informações sobre os conjuntos de caracteres disponíveis.
check_constraintsContém informações sobre restrições definidas em tabelas (somente no mysql >=8.0.16).
collationsContém informações sobre agrupamentos para cada conjunto de caracteres.
column_statisticsEstatísticas do histograma para valores de colunas.
column_type_elementsContém informações sobre os tipos usados pelas colunas.
columnsContém informações sobre colunas em tabelas.
dd_propertiesTabela que identifica propriedades do dicionário de dados, como sua versão.
eventsContém informações sobre eventos do agendador de eventos.
foreign_keysContém informações sobre chaves estrangeiras.
foreign_key_column_usageContém informações sobre chaves estrangeiras.
index_partitionsContém informações sobre partições usadas por índices.
index_statsUsado para armazenar estatísticas de índices dinâmico gerado quando o ANALYZE TABLE é executado.
indexesContém informações sobre índices de tables.
innodb_ddl_logArmazena logs DDL para operações DDL contra falhas.
parameter_type_elementsContém informações sobre procedumentos e funções armazenados.
parametersContém informações sobre procedimentos e funções armazenadas.
resources_groupsContém informações sobre grupos de recursos.
routinesContém informações sobre procedimento e funções armazenadas.
schemataContém informações sobre esquemas.
tablesContém informações sobre tabelas em bancos de dados.

Grant System Tables


Contém os dados dos usuários e suas permissões e previlégios.


Uma forma de ver as tabelas aqui é usando o comando select * from mysql.<TABELA>;, vamos ver algumas dessas tabelas abaixo:

TabelaDescrição
userConta de usuários, privilégios globais e outros.
global_grantsAtribuição de provilégios globais dinâmicos aos usuários
table_privPrivilégios a nível de tabela
column_privPrivilégios a nível de coluna
default_rolesLista os perfis padrão a serem ativados em um usuário (atua como grupos, onde vamos dar o privilégio para o grupo)

Privilégios estático são nativos do MySQL como: select, insert, update, delete. Já os dinâmicos aparecem com a adição de algum plugin, e essa permissão está relacionada a esse componente que não está no MySQL por padrão.


Object Information System Tables


Contém os dados sobre Store Procedure, componentes, funções, plugins e etc.



Log System Tables


Contém os dados sobre os Logs de consulta.


Uma forma de ver as tabelas aqui é usando o comando select * from mysql.<TABELA>;, vamos ver algumas dessas tabelas abaixo:

TabelaDescrição
slow_logContém tabelas de log de consulta mais lenta (podemos programar consultas que demorem X tempo serão gravadas aqui
general_logTabela de log de consulta geral


Replication System Tables


Usado para operações de replicação.



Optimizer System Tables


Usado para otimizar as consultas.




MYSQLD


Vamos ver algumas opções que podemos usar no arquivo de configuração do servidor do MySQL, seu caminho por padrão fica em /etc/mysql/mysql.conf.d/mysqld.cnf.

OpçãoDescriçãoExemplo
basedirCaminho do mysql (onde está instalado).basedir = /etc/mysql
datadirCaminho onde ficarão os arquivos, geralmente é a pasta 'data'.datadir = /var/lib/mysql
tempdirLocal onde ficarão os arquivos temporários.tmpdir = /tmp
lc-messagesLinguagem usada, principalmente em informações no console.lc_messages = pt_BR
default-time-zoneIndica qual o timezone será usado para marcar as datas e horas no servidor MySQL, por padrão é usado do sistema.default-time-zone = "-3:00"
portÉ a porta usada para comunicação com o MysQL, usado quando o cliente vai se conectar com o servidor.port = 3306


Bonus


Algumas funções no SQL não precisam específicar o FROM, mas existem outras que necessitam de um from, nesses casos, podemos usar a tabela chamada dual.

# Exibindo a data/hora do banco:
MariaDB [(none)]> select now();
+---------------------+
| now() |
+---------------------+
| 2022-01-05 13:30:00 |
+---------------------+
1 row in set (0.001 sec)

# Usando o from:
MariaDB [(none)]> select now() from dual;
+---------------------+
| now() |
+---------------------+
| 2022-01-05 13:30:27 |
+---------------------+
1 row in set (0.001 sec)


Para restringir caracteres numa coluna onde deva ser M ou F, usamos assim:

genero CHAR(1) CHECK (genero IN ('M','F'))

Nesse caso usamos a check constraint, outra forma de fazer isso é usando enum, como a seguir:

genero ENUM('M','F')


Alguns Erros


Para o erro Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection siga o passo abaixo:

# Remoto
ALTER USER 'USERNAME'@'IP' IDENTIFIED WITH mysql_native_password BY 'SENHA';

# Local:
ALTER USER 'USERNAME'@'localhost' IDENTIFIED WITH mysql_native_password BY 'SENHA';


# Limitando a saída:
mysql> select dept_no,dept_name from departments limit 3;
+---------+------------------+
| dept_no | dept_name |
+---------+------------------+
| d009 | Customer Service |
| d005 | Development |
| d002 | Finance |
+---------+------------------+
3 rows in set (0.002 sec)

# Contando a quantidade de registros dentro de uma tabela:
mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
| 300024 |
+----------+
1 row in set (0.078 sec)
# Isso significa que temos mais de 300k de linhas nessa tabela.

# Criando um filtro com WHERE, listando apenas funcionarios contratados depois dos anos 2k:
mysql> select * from employees where hire_date > "2000-01-01 limit 10";
+--------+------------+------------+------------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+------------+--------+------------+
| 47291 | 1960-09-09 | Ulf | Flexer | M | 2000-01-12 |
| 60134 | 1964-04-21 | Seshu | Rathonyi | F | 2000-01-02 |
| 72329 | 1953-02-09 | Randi | Luit | F | 2000-01-02 |
| 205048 | 1960-09-12 | Ennio | Alblas | F | 2000-01-06 |
| 222965 | 1959-08-07 | Volkmar | Perko | F | 2000-01-13 |
| 226633 | 1958-06-10 | Xuejun | Benzmuller | F | 2000-01-04 |
| 227544 | 1954-11-17 | Shahab | Demeyer | M | 2000-01-08 |
| 422990 | 1953-04-09 | Jaana | Verspoor | F | 2000-01-11 |
| 424445 | 1953-04-27 | Jeong | Boreale | M | 2000-01-03 |
| 428377 | 1957-05-09 | Yucai | Gerlach | M | 2000-01-23 |
| 463807 | 1964-06-12 | Bikash | Covnot | M | 2000-01-28 |
| 499553 | 1954-05-06 | Hideyuki | Delgrande | F | 2000-01-22 |
+--------+------------+------------+------------+--------+------------+
12 rows in set, 1 warning (0.121 sec)

# Funcionarios contratados depois dos anos 2k e que sejam mulheres:
mysql> select * from employees where hire_date > "2000-01-01" AND gender="F";
+--------+------------+------------+------------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+------------+--------+------------+
| 60134 | 1964-04-21 | Seshu | Rathonyi | F | 2000-01-02 |
| 72329 | 1953-02-09 | Randi | Luit | F | 2000-01-02 |
| 205048 | 1960-09-12 | Ennio | Alblas | F | 2000-01-06 |
| 222965 | 1959-08-07 | Volkmar | Perko | F | 2000-01-13 |
| 226633 | 1958-06-10 | Xuejun | Benzmuller | F | 2000-01-04 |
| 422990 | 1953-04-09 | Jaana | Verspoor | F | 2000-01-11 |
| 499553 | 1954-05-06 | Hideyuki | Delgrande | F | 2000-01-22 |
+--------+------------+------------+------------+--------+------------+
7 rows in set (0.118 sec)

# Mesma coisa acima, mas aqui, vamos listar apenas as pessoas que começam com a letra 'S':
mysql> select * from employees where hire_date > "2000-01-01" and first_name like "S%";
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 60134 | 1964-04-21 | Seshu | Rathonyi | F | 2000-01-02 |
| 227544 | 1954-11-17 | Shahab | Demeyer | M | 2000-01-08 |
+--------+------------+------------+-----------+--------+------------+
2 rows in set (0.109 sec)

# Mesma coisa acima, mas aqui, vamos listar apenas as pessoas que começam com a letra 'S' ou 'P':
mysql> select * from employees where hire_date > "2000-01-01" and (first_name like "S%" OR first_name like "P%");



<br />

<br />

## Instruções de Schema SQL

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

alter table TABELA MODIFY COLUNA parametros