Data is as important as talent, strategy, and sales, and is often central to a business's success. In fact, data is typically considered a company's most important asset. We are now in a data-driven society, and the sheer volume of useful data is growing astronomically. Protecting and managing this data provides your organization with a base for data analysis that can lead to a competitive advantage … or just plain survival.
While you may not be involved in the data analytics side of your company, as a system administrator, you are on the data management side. Whatever data your establishment decides to keep and scrutinize, it is up to you to make sure your fellow employees have fast and appropriate access to it through your administration of the database servers.
We've looked at a lot of text files so far in this book, and they are useful for many different purposes such as storing configuration information, boot messages, Bash scripts, and so on. However, when you have complex data that needs to be stored, processed, and analyzed, simple text files don't work well. Text files are often referred to as flat files, because only basic relationships can exist between the data they contain.
Databases were created to fill the need for complex connections between individual data items. While data is the focus, there are other pieces that make up a database management system (DBMS). A DBMS typically consists of the following parts:
Back in the 1970s, a database management system architecture, called a relational DBMS (RDBMS), was first conceived. This still-popular model organizes data into three levels:
In the apple tree table, each apple tree sold by the company would have its own record. A table record is a collection of fields about the same item. So, in our apple tree table, each type of apple tree sold would have its own record, identified by the item number. This item number is a primary key. Primary keys are used to uniquely identify each record within a table.
It's helpful to see a pictorial view of a database table. Sticking with our fruit-trees-for-sale application, a representation of the database's apple tree table is shown snipped in Figure 21.1.
In the representation, each row is a record in the table, which is why sometimes database table records are called rows. Each column within the apple tree table is a field, which are why fields are sometimes called columns. Notice that some fields for the records contain the same data, while others do not. For example, item numbers 3247
and 3248
share all the same data in their record fields, except for their primary key (Item #
) and TreeSize
—one record has standard (Std
) in that field, and one contains Dwarf
. A record in a table is a single occurrence of all the values in the record's data fields.
Fields can be different types of data. Table 21.1 shows these standard database data types for an RDBMS.
TABLE 21.1: RDBMS Data Types
DATA TYPE | DESCRIPTION |
---|---|
bool |
Boolean value representing either true or false |
char( n ) |
Character string of a fixed n characters in length |
date |
Date expressed in YYYY
-
MM
-
DD format |
datetime |
Date and time expressed in YYYY
-
MM
-
DD HH
:
MM
:
SS format |
float |
Floating-point number |
int |
Integer number |
text |
Character string of a variable length |
varchar( n ) |
Character string of a variable n or fewer characters in length |
These data types are slightly different depending on which RDMBS you use. Also, they may add a few additional types of data.
Created in the 1970s, Structured Query Language (SQL) was declared a standard by the American National Standards Institute (ANSI) in the mid-1980s. Pronounced sequel, this language is still used to communicate with databases using an RDBMS, and the standard has continued to evolve, making it stronger and more flexible.
What's exciting about SQL is that when you learn the language's syntax, you can use it on nearly all relational databases with few modifications. So, when you have a Linux RDBMS installed on your system, you'll have a place to learn and practice using SQL.
SQL consists of specific instruction commands that are crafted into statements to interface with the database. SQL commands are typically grouped into four different categories (though some special SQL commands fall outside of these categorizations):
We'll only be using a few basic commands in this chapter that fall into the DDL and DML categories as well as a few that don't fall into any of these groupings. Table 21.2 describes the commands.
TABLE 21.2: A Few Basic SQL Commands
COMMAND | CATEGORY | DESCRIPTION |
---|---|---|
CREATE |
DDL | Creates a table, database, or user account |
DESCRIBE |
n/a | Lists a table's field definitions |
DROP |
DDL | Deletes a table, a database, or a user account |
GRANT |
DDL | Grants access to the selected item for the designated user account |
INSERT |
DML | Adds new data records to a table |
SELECT |
DML | Queries data in a table |
SHOW |
n/a | Displays the selected item |
UPDATE |
DML | Modifies current data records in a table |
USE |
n/a | Selects a database to use |
Notice that the commands are in uppercase. This is typical of most SQL commands. Be aware that with some RDBMSs, you can use either lowercase or uppercase, but good form dictates using only uppercase for SQL commands.
Access to the data that resides in the database is managed by the database engine. When an application wants to view or modify data, it has to go through the database engine to do so, as portrayed in Figure 21.2.
The database engine in some DBMSs continues to run in the background as a daemon on Linux. Daemons, covered in Chapter 10, “Booting Linux,” are programs that continue to run in the background, offering a specific service. In the case of a DBMS, that service is access to data managed by the database engine.
One nice aspect about this structure is that the application doesn't have to reside on the same computer system as the database engine. Various instances of the app could run on different systems, sending requests to the database engine on the primary database server similar to what is shown in Figure 21.3.
The Linux RDBMSs we're going to focus on in this chapter include MySQL, MariaDB, and PostgreSQL. They each are relational and use a SQL interface.
Released in 1996, MySQL is one of the more popular RDBMSs used for web servers on Linux. The LAMP (Linux system, Apache web server, MySQL database server, and PHP programming language) platform can be found in Linux servers around the world still today.
MySQL was revolutionary at the time of its release, because it used indexing data to speed up data queries. The MySQL developers didn't start out trying to compete with commercial databases. Instead, they just wanted to create a simple but fast database system. So, the fancy RDBMS features were left out, and speed was the focus. Because of this development emphasis, MySQL quickly became the standard RDBMS used in many high-profile Internet web applications.
Over time, while continuing to maintain the emphasis on speedy data queries, additional RDBMS features were added, which strengthened MySQL's popularity. MySQL can run on many different platforms besides Linux, can scale its processing into multiple CPUs, provides security at the user and host levels, supports many different human languages, and so on.
Installing MariaDB is fairly simple. You need super user privileges, of course, and the correct package name: mariadb-server
. (Installing packages was covered in Chapter 3 “Installing and Maintaining Software in Ubuntu,” and Chapter 5, “Installing and Maintaining Software in Red Hat.”)
Here is a snipped example of installing MariaDB on Ubuntu, after updating the system's package information:
$ sudo apt update
[sudo] password for sysadmin:
[…]
Fetched 4124 kB in 22s (187 kB/s)
Reading package lists… Done
Building dependency tree
Reading state information… Done
[…]
$
$ sudo apt install mariadb-server
Reading package lists… Done
Building dependency tree
Reading state information… Done
[…]
The following NEW packages will be installed:
[…]
mariadb-common mariadb-server mariadb-server-10.3 mar[…]
mysql-common socat
[…]
Need to get 21.1 MB of archives.
After this operation, 173 MB of additional disk space will
be used.
Do you want to continue? [Y/n] Y
[…]
Fetched 21.1 MB in 39s (536 kB/s)
Preconfiguring packages …
Selecting previously unselected package mysql-common.
[…]
Unpacking mariadb-server-10.3 (1:10.3.25-0ubuntu0.20.04.1)
[…]
Setting up mariadb-server-10.3 (1:10.3.25-0ubuntu0.20.04.1)
[…]
$ dpkg -s mariadb-server | grep Status
Status: install ok installed
Installing MariaDB on a Red Hat–based distribution is also fairly straightforward. Here is a snipped example of an installation on CentOS using the root
account:
# dnf install mariadb-server
[…]
Last metadata expiration check: […].
Dependencies resolved.
[…]
Installing:
mariadb-server […]
mariadb […]
mariadb-common […]
[…]
Installing weak dependencies:
mariadb-backup […]
[…]
Install 54 Packages
Total download size: 43 M
Installed size: 191 M
Is this ok [y/N]: y
Downloading Packages:
(1/54): mariadb-common-[…]
[…]
(7/54): mariadb-server-utils[…]
[…]
Total 1.6 MB/s | 43 MB 00:27
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
[…]
Installed products updated.
Installed:
mariadb-[…]
mariadb-backup[…]
mariadb-common[…]
[…]
Complete!
#
# dnf list installed mariadb-server
Installed Packages
mariadb-server.x86_64 […]
#
Even though some distribution's installation process sets the MariaDB service to start when the system boots, it's a good idea to go ahead and enable it yourself. Also start the service as shown in this snipped example on CentOS using the root
account:
# systemctl status mariadb
mariadb.service - MariaDB 10.3 database server
Loaded: loaded […] disabled; vendor pr>
Active: inactive (dead)
Docs: man:mysqld(8)
https://mariadb.com/kb/en/library/systemd/
#
# systemctl enable mariadb
Created symlink /etc/systemd/system/mysql.service /usr/lib/systemd/system/mariadb.service.
Created symlink /etc/systemd/system/mysqld.service →
/usr/lib/systemd/system/mariadb.service.
Created symlink /etc/systemd/system/
multi-user.target.wants/mariadb.service →
/usr/lib/systemd/system/mariadb.service.
#
# systemctl start mariadb
#
# systemctl status mariadb
mariadb.service - MariaDB 10.3 database server
Loaded: loaded […] enabled; vendor pre>
Active: active (running) since […] 42s ago
Docs: man:mysqld(8)
https://mariadb.com/kb/en/library/systemd/
[…]
Main PID: 27112 (mysqld)
Status: "Taking your SQL requests now…"
Tasks: 30 (limit: 11479)
Memory: 84.7M
CGroup: /system.slice/mariadb.service
⌙27112 /usr/libexec/mysqld --basedir=/usr
[…]
lines 1-23)
#
The MariaDB server is now enabled to start when the system boots. Also, it is currently active. After you've accomplished installing the server and enabling it, MariaDB is ready to start managing your data.
If you are running a Red Hat–based Linux system, the process for installation is different enough from Ubuntu that it is worth your time to try it for yourself.
You access and manage data within the MariaDB server through database user accounts. By default, a special all-powerful account called root
(sound familiar?) is installed as an account in the RDBMS. However, since this account has full access to everything in MariaDB, it is considered a poor security practice to use it for user-level access and management of data.
It's best to create a single database account for every user account that needs access. This good security practice allows you to limit a user's access to a particular application's database and protect other managed MariaDB databases from accidental or intentional disturbance.
When you've newly installed a MariaDB server, you will need to either log into the root
system account or use sudo
to gain super user privileges to interface with MariaDB and create the first user account. The command to access the SQL interface to MariaDB is mysql
. When you are in the interface, your prompt will look like this: MariaDB [(none)]>
. This is one difference between MySQL and MariaDB. For MySQL, the prompt looks like this: MySQL [(none)]>
.
To create your first user account, you may want the system's hostname, which can be obtained a variety of ways, including through the hostname
command. The hostname can be used within the database account username.
It's a good practice to use the same username for the database account as the Linux system account's username. The SQL interface syntax to create a database user account is as follows:
CREATE USER username@hostname IDENTIFIED BY 'password';
Notice that at the end of the SQL syntax line, there is a semicolon (;
). This lets the SQL interface know that you have completed entering the syntax for this statement. That small, but important, piece of SQL syntax is easy for those who are new to SQL to miss!
An example of creating a first MariaDB database user account on an Ubuntu system using sudo
to gain super user privileges is shown here:
$ hostname
ubuntu-server
$
$ sudo mysql
[sudo] password for sysadmin:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 42
Server version: 10.3.25-MariaDB-0ubuntu0.20.04.1 Ubuntu 20.04
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab
and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current
input statement.
MariaDB [(none)]> CREATE USER 'sysadmin@ubuntu-server'
-> IDENTIFIED BY 'Project42Password';
Query OK, 0 rows affected (0.037 sec)
MariaDB [(none)]>
You don't have to put the user account name and hostname in single quotation marks, but it's needed in this case because of the dash (-
) in the hostname. Notice that you can put the SQL statement on two lines. That's because the interface doesn't care about line returns produced by the Enter key like the Bash shell does. Instead, the SQL interface is watching for a semicolon to end the statement.
After you've created a user account, you can view it as shown here:
MariaDB [(none)]> SELECT user FROM mysql.user;
+------------------------+
| user |
+------------------------+
| sysadmin@ubuntu-server |
| root |
+------------------------+
2 rows in set (0.000 sec)
MariaDB [(none)]> exit
Bye
$
Notice that the exit
command (no semicolon needed) allows you to leave the SQL interface and return to the command line.
Now that you've created a MariaDB user account for yourself, use it to log into the SQL interface. An example of doing this is shown here:
$ mysql --user 'sysadmin@ubuntu-server' --password
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 47
Server version: 10.3.25-MariaDB-0ubuntu0.20.04.1 Ubuntu 20.04
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab
and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current
input statement.
MariaDB [(none)]>
For your MariaDB account's password, instead of entering it on the same line as the mysql
command, you just use the --password
option with no argument. When you do this, the SQL interface will prompt you for the password, and your password is not displayed as you type it.
Besides creating an account to access the MariaDB database server, you'll need to grant permissions to access tasks and items within MariaDB for the account. If this is not done, when the user account tries to perform a task, such as creating a database, access will be denied as shown here:
$ mysql --user 'sysadmin@ubuntu-server' --password
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
[…]
MariaDB [(none)]> CREATE DATABASE FruitTrees;
ERROR 1044 (42000): Access denied for user
'sysadmin@ubuntu-server'@'%' to database 'FruitTrees'
MariaDB [(none)]> exit
Bye
$
To grant access for the first account, you'll again need to use super user privileges. The basic syntax for doing this is as follows:
GRANT access ON objects TO user;
The access
is essentially commands that the user
can use when dealing with the listed objects
. Wildcards are allowed when specifying objects
. For example, to allow a user to issue the SQL SELECT
command on any database in the system, you'd use the GRANT SELECT ON *.* TO
user
;
SQL statement syntax.
In the case of granting access for the first account, assuming it is an administrative account, it's best to provide full-blown access by using ALL
as the access
granted, as shown snipped here:
$ sudo mysql
[sudo] password for sysadmin:
Welcome to the MariaDB monitor. Commands end with ; or \g.
[…]
MariaDB [(none)]> SHOW GRANTS FOR 'sysadmin@ubuntu-server';
+--------------------------------------[…]+
| Grants for sysadmin@ubuntu-server@% […]|
+--------------------------------------[…]
| GRANT USAGE ON *.* TO `sysadmin@ubuntu-server`@`%`
IDENTIFIED BY PASSWORD '*3429168B1E2FE4[…]|
+--------------------------------------[…]+
1 row in set (0.000 sec)
MariaDB [(none)]> GRANT ALL ON *.* TO 'sysadmin@ubuntu-server';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> SHOW GRANTS FOR 'sysadmin@ubuntu-server';
+--------------------------------------[…]+
| Grants for sysadmin@ubuntu-server@% […]|
+--------------------------------------[…]+
| GRANT ALL PRIVILEGES ON *.* TO `sysadmin@ubuntu-server`@`%`
IDENTIFIED BY PASSWORD '*3429168B1E2FE4[…]|
+--------------------------------------[…]+|
1 row in set (0.000 sec)
MariaDB [(none)]> exit
Bye
$
The SHOW GRANTS FOR
user
;
SQL statement shows the current access granted to that user
. When the access was modified by the GRANT
command, the user
now has ALL PRIVILEGES
granted.
After you have the database server installed and appropriate access granted, you can begin creating databases and their tables and populating them with data.
The SQL command to create a database is logically CREATE DATABASE
. Using the fruit tree example from previously, an appropriately named database is created in MariaDB through the SQL interface as shown snipped here:
$ mysql --user 'sysadmin@ubuntu-server' --password
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
[…]
MariaDB [(none)]> CREATE DATABASE FruitTrees;
Query OK, 1 row affected (0.001 sec)
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| FruitTrees |
| information_schema |
| mysql |
| performance:schema |
+--------------------+
4 rows in set (0.036 sec)
MariaDB [(none)]>
Notice you can see all the databases within MariaDB using the SHOW DATABASES;
command, including the newly created FruitTrees
database.
After a database is created, assuming you have normalized your data, you are ready to begin creating tables. The USE
database
;
command is needed to select the database to create a table in, as shown here:
MariaDB [(none)]> USE FruitTrees;
Database changed
MariaDB [FruitTrees]> CREATE TABLE AppleTrees (
-> item_number int not null,
-> tree_type text,
-> description text,
-> tree_size text,
-> apple_color text,
-> blooming_period text,
-> pollinator_group int,
-> harvest_period text,
-> grow_zones text,
-> primary key (item_number));
Query OK, 0 rows affected (0.755 sec)
MariaDB [FruitTrees]>
The CREATE TABLE
command starts the process of creating a designated table (AppleTrees
in the example). While you could type the field information for the table all on the same line, it's easier to see what you are doing by putting a single field designation on each line. Each field designation has a name and a data type (see Table 21.1), as well as any options. Also, you have to designate a primary key, and you need to prevent that particular field from being set to blank or null. In the example, the item_number
is the primary key, and it is blocked from being empty through the not null
option in its field designation.
To view any tables, use the SHOW TABLES
syntax as shown in the example here:
MariaDB [FruitTrees]> SHOW TABLES IN FruitTrees;
+----------------------+
| Tables_in_FruitTrees |
+----------------------+
| AppleTrees |
+----------------------+
1 row in set (0.000 sec)
MariaDB [FruitTrees]>
To view field description details within a particular table of a selected database, you can use the DESCRIBE
command, as shown here:
MariaDB [FruitTrees]> DESCRIBE AppleTrees;
+------------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+---------+------+-----+---------+-------+
| item_number | int(11) | NO | PRI | NULL | |
| tree_type | text | YES | | NULL | |
| description | text | YES | | NULL | |
| tree_size | text | YES | | NULL | |
| apple_color | text | YES | | NULL | |
| blooming_period | text | YES | | NULL | |
| pollinator_group | int(11) | YES | | NULL | |
| harvest_period | text | YES | | NULL | |
| grow_zones | text | YES | | NULL | |
+------------------+---------+------+-----+---------+-------+
9 rows in set (0.046 sec)
MariaDB [FruitTrees]>
Now that you have a table created, you can start populating it with data. Sticking with our AppleTrees
table scenario, we added three data records to it in this example:
MariaDB [FruitTrees]> INSERT INTO AppleTrees VALUES (3247,
-> 'Baldwin', 'Impressive American variety…',
-> 'Std', 'Red and Green',
-> 'Mid-Late Spring', 4, 'October', '5-8');
Query OK, 1 row affected (0.067 sec)
MariaDB [FruitTrees]> INSERT INTO AppleTrees VALUES (3248,
-> 'Baldwin', 'Impressive American variety…',
-> 'Dwarf', 'Red and Green',
-> 'Mid-Late Spring', 4, 'October', '5-8');
Query OK, 1 row affected (0.074 sec)
MariaDB [FruitTrees]> INSERT INTO AppleTrees VALUES (3251,
-> 'Redfree', 'Sweet and a little acidic…',
-> 'Std', 'Red and Green',
-> 'Early-Mid Spring', 4, 'August', '4-8');
Query OK, 1 row affected (0.075 sec)
It's a good idea to check the data you've entered into your database tables to ensure all is well. Using the SELECT * FROM
tablename
;
SQL statement will allow you to view all the current data in tablename
, as shown snipped here:
MariaDB [FruitTrees]> SELECT * FROM AppleTrees;
[…]
| item_number | tree_type | description
| tree_size | apple_color | blooming_period | pollinator_group
| harvest_period | grow_zones |
[…]
| 3247 | Baldwin | Impressive American variety…
| Std | Red and Green | Mid-Late Spring | 4
| October | 5-8 |
| 3248 | Baldwin | Impressive American variety…
| Dwarf | Red and Green | Mid-Late Spring | 4
| October | 5-8 |
| 3251 | Redfree | Sweet and a little acidic…
| Std | Red and Green | Early-Mid Spring | 4
| August | 4-8 |
[…]
3 rows in set (0.001 sec)
MariaDB [FruitTrees]>
If you find mistakes in your data or just need to update information, you can do that rather easily. Just use the UPDATE
command along with the data field you'd like to change and a WHERE
statement to select the record identified by its primary key (item_number
in this case):
MariaDB [FruitTrees]> UPDATE AppleTrees SET
-> pollinator_group=3 WHERE item_number=3248;
Query OK, 1 row affected (0.120 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [FruitTrees]> SELECT * FROM AppleTrees;
[…]
| item_number | tree_type | description
| tree_size | apple_color | blooming_period | pollinator_group
| harvest_period | grow_zones |
[…]
| 3247 | Baldwin | Impressive American variety…
| Std | Red and Green | Mid-Late Spring | 4
| October | 5-8 |
| 3248 | Baldwin | Impressive American variety…
| Dwarf | Red and Green | Mid-Late Spring | 4
| October | 5-8 |
| 3251 | Redfree | Sweet and a little acidic…
| Std | Red and Green | Early-Mid Spring | 3
| August | 4-8 |
[…]
3 rows in set (0.001 sec)
MariaDB [FruitTrees]> exit
Bye
$
After your database and its tables are created and you have populated the tables and checked their data, you are ready to let your database applications roll.
Knowing how to install and use the MySQL and MariaDB databases will provide you with invaluable skills in your system administration career. However, it's always a good idea to expand your database knowledge so that your experience has some variety to it. We'll explore another RDBMS next.
PostgreSQL has a history that goes all the way back to the 1980s, though its current name wasn't designated until 1995. In fact, many administrators still refer to it by a variant of its previous name, Postgres.
PostgreSQL's evolutionary life has brought about some popular features. It supports standard SQL, with a few exceptions, and has data integrity structures, such as multiversion concurrency control (MVCC), which allows each database transaction to have a copy of the data. This way, creating or modifying data does not prevent any data queries and vice versa. MVCC not only provides higher levels of data integrity, but it speeds things up.
Security-wise, PostgreSQL has the ability to provide mandatory access control (MAC) security levels similar to that of SELinux (see Chapter 18, “Exploring Red Hat Security”). In addition, it can work with several different authentication systems, such as Kerberos, Lightweight Directory Access Protocol (LDAP), pluggable authentication modules (PAM), and so on.
Installing PostgreSQL is a little different depending on the Linux distribution you are using. You need super user privileges and the correct package name, which is postgresql
for Ubuntu and postgresql-server
for Red Hat–based distributions.
Here is a snipped example of installing PostgreSQL on Ubuntu, after updating the system's package information:
$ sudo apt update
[sudo] password for sysadmin:
[…]
Fetched 4124 kB in 22s (187 kB/s)
Reading package lists… Done
Building dependency tree
Reading state information… Done
[…]
$
$ sudo apt install postgresql
[sudo] password for sysadmin:
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following additional packages will be installed:
libllvm10 libpq5 libsensors-config libsensors5
postgresql-12 postgresql-client-12
postgresql-client-common postgresql-common
ssl-cert sysstat
[…]
0 upgraded, 11 newly installed, 0 to remove […]
Need to get 30.6 MB of archives.
After this operation, 122 MB of additional […]
Do you want to continue? [Y/n] Y
Get:1 http://us.archive.ubuntu.com/ubuntu focal/main
amd64 libllvm10 amd64 1:10.0.0-4ubuntu1 [15.3 MB]
[…]
Fetched 30.6 MB in 46s (659 kB/s)
Preconfiguring packages …
[…]
Unpacking sysstat (12.2.0-2) …
Setting up postgresql-client-common (214ubuntu0.1) …
[…]
Setting up postgresql-common (214ubuntu0.1) …
Adding user postgres to group ssl-cert
[…]
The files belonging to this database system will be owned
by user "postgres".
This user must also own the server process.
[…]
syncing data to disk …
[…]
[…]
Processing triggers for libc-bin […]
$
$ systemctl status postgresql
postgresql.service - PostgreSQL RDBMS
Loaded: loaded […] enabled; vendor pr>
Active: active (exited) since […]
Main PID: 2690 (code=exited, status=0/SUCCESS)
Tasks: 0 (limit: 2282)
Memory: 0B
CGroup: /system.slice/postgresql.service
[…]ubuntu-server systemd[1]: Starting PostgreSQL RDBMS…
[…]ubuntu-server systemd[1]: Finished PostgreSQL RDBMS.
lines 1-10/10 (END)
$
$ which createdb
/usr/bin/createdb
$
When you install PostgreSQL on Ubuntu, it is automatically enabled to start when the system boots. Also, the service is started for you. One simple check you can perform to see if PostgreSQL is installed on a system outside of package management is through the which createdb
command. If you see a file when this command is issued, PostgreSQL is installed on your system, as was done in the preceding installation example.
Installing PostgreSQL on a Red Hat–based distribution is a little different. In the following snipped example, we used the su -c '
command
'
syntax to issue single commands as the root
user to escalate to super user privileges, when needed:
$ su -c 'dnf install postgresql-server'
Password:
Last metadata expiration check: […]
Dependencies resolved.
[…]
Installing:
postgresql-server […]
Installing dependencies:
libpq […]
postgresql […]
Enabling module streams:
postgresql […]
Transaction Summary
[…]
Install 3 Packages
Total download size: 6.7 M
Installed size: 26 M
Is this ok [y/N]:y
Downloading Packages:
[…]
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
[…]
Installed products updated.
Installed:
libpq[…]
postgresql[…]
postgresql-server[…]
Complete!
$
When you install PostgreSQL on CentOS, it is not automatically enabled or started, so you'll have to issue those systemctl
commands manually. But before you do that, you have to run a PostgreSQL database initialization with super user privileges, as shown here:
$ su -c '/usr/bin/postgresql-setup --initdb'
Password:
* Initializing database in '/var/lib/pgsql/data'
* Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log
$
After the database is initialized, you can enable the PostgreSQL to start during the system's boot and get the service running. The process is shown snipped in this example:
$ systemctl status postgresql
• postgresql.service - PostgreSQL database server
Loaded: loaded ([…]disabled; vendor>
Active: inactive (dead)
$
$ su -c 'systemctl enable postgresql'
Password:
Created symlink
[…]
$
$ su -c 'systemctl start postgresql'
Password:
$
$ systemctl status postgresql
• postgresql.service - PostgreSQL database server
Loaded: loaded […]enabled; vendor>
Active: active (running) since […]
[…]
$
When you have your PostgreSQL RDBMS software installed and properly initialized, you can move forward on setting up proper access to it and then loading data into the database.
You access and manage data within the PostgreSQL server through database user accounts, which are called roles. Instead of using the root
account, a special all-powerful account called postgres
is a role created in this RDBMS. The postgres
role has full access to everything in PostgreSQL, so it is a good security practice to create a single database role for every user account that needs access to it.
A quick check lets you determine whether your current user account has a role set up for it within a PostgreSQL server. Attempt to create a database with the createdb
command. If you get a role "
username
" does not exist
message when issuing the command, a role for you is not yet created:
$ createdb AppleTrees
createdb: error: could not connect to database template1:
FATAL: role "sysadmin" does not exist
$
To create your role, you first have to log into the postgres
account. To do this, you need super user privileges as shown here:
$ sudo --login -u postgres
postgres@ubuntu-server:~$ whoami
postgres
postgres@ubuntu-server:~$
postgres@ubuntu-server:~$ psql
psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1))
Type "help" for help.
postgres=#
The command to access the SQL interface to PostgreSQL is psql
. When you are in the interface, your prompt will look like this: postgres=#
. The name (postgres
) lets you know the current role you are using in the RDBMS. The pound sign (#
) indicates that this role has super user privileges within the database. A greater-than sign (>
) in place of the pound sign indicates that the super user privileges are not granted for a role.
It's a good practice to use the same role name for the database account as the Linux system account's username. The SQL interface syntax to create a database user account is as follows:
CREATE ROLE role-name access;
When you create a role in PostgreSQL, you grant the allowed access for that role at the same time. The access
portion of the CREATE
command is what grants access, and it can be set to one or more of the items listed in Table 21.3.
TABLE 21.3: A Few PostgreSQL Role Access Settings
ACCESS NAME | DESCRIPTION |
---|---|
CREATEDB |
Creation of databases is permitted. |
CREATEROLE |
Creation of database roles is permitted. This is a potential security risk, because the role can create other roles with SUPERUSER access. |
LOGIN |
Sets the role as a database user. Passwords for database authentication are set with PASSWORD '
password' . |
SUPERUSER |
Grants full access to all database objects. This is a dangerous access level and should be used with caution. |
The access
list in Table 21.3 is not complete, but it will get you started on your journey of exploring PostgreSQL. If you make a mistake or need to grant more privileges later, you can use the ALTER ROLE
command. Use DROP ROLE
if you need to remove a role from the database.
An example of creating a role for the user sysadmin
in the psql
SQL interface with the postgres
role is shown snipped here:
$ sudo --login -u postgres
postgres@ubuntu-server:~$ psql
psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1))
Type "help" for help.
postgres=# CREATE ROLE sysadmin
postgres-# CREATEDB LOGIN PASSWORD 'Project42Password';
CREATE ROLE
postgres=#
To see all the roles you've created and the ones that came with the default installation, use the special psql
command of \du
. This command will show the role information using a pager, so you'll need to press the Q key to exit out of the display when you are done viewing the role information. A snipped example of this using this command is shown here:
postgres=# \du
List of roles
Role name | Attributes […]
-----------+------------------------------------[…]
postgres | Superuser, Create role, Create DB, […]
sysadmin | Create DB […]
(END)
postgres=#
After you're done creating the initial role, it's a good idea to exit from the psql
interface and log out of the postgres
account. You can use the exit
command to do both actions:
postgres=# exit
postgres@ubuntu-server:~$
postgres@ubuntu-server:~$ exit
logout
$ whoami
sysadmin
$
After a role has been created for a user and prior to them entering into the psql
SQL interface for the first time, they will need to perform an initialization by issuing the createdb
command with no database name listed after it. An example of this is shown here:
$ whoami
sysadmin
$
$ createdb
$
$ psql
psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1))
Type "help" for help.
sysadmin=>
Notice that the SQL interface prompt in psq
l has changed. It now shows the role name of the user who is accessing the interface. When the RDBMS has been installed and an initial role is created, you're ready to start creating and using a PostgreSQL database.
PostgreSQL generally follows standardized SQL. For example, creating a database looks the same as it did when using MariaDB:
sysadmin=> CREATE DATABASE FruitTrees;
CREATE DATABASE
sysadmin=>
However, you'll find that within the psql
SQL interface, some SQL statements do not work, such as the SHOW DATABASES
command. Instead, you need to use \l
(a lowercase L) to see all the databases, as shown snipped here:
sysadmin-> \1
List of databases
Name | Owner | Encoding | Collate |[…]
------------+----------+----------+---------+[…]
fruittrees | sysadmin | UTF8 | C.UTF-8 |[…]
postgres | postgres | UTF8 | C.UTF-8 |[…]
sysadmin | sysadmin | UTF8 | C.UTF-8 |[…]
template0 | postgres | UTF8 | C.UTF-8 |[…]
template1 | postgres | UTF8 | C.UTF-8 |[…]
(5 rows)
sysadmin->
Notice in the preceding example that even though we named our database FruitTrees
when we created it, PostgreSQL changed the name to fruittrees
. If you want an object name to be a different case than lowercase, you'll have to enclose it in quotation marks. This is important to note, because you have to have the right case when you use an object, such as a database name, in your SQL command syntax.
Before creating tables in your newly created database, you need to connect to it. Use the \c
command to accomplish this as shown here:
sysadmin-> \c fruittrees;
You are now connected to database "fruittrees" as user "sysadmin".
fruittrees->
When you connect to a database, the psql
prompt will change and replace your role name with the current database. Creating a table follows standard SQL syntax, as shown in this test example:
fruittrees=> CREATE TABLE test (
fruittrees(> id_number int not null,
fruittrees(> type text,
fruittrees(> brand text,
fruittrees(> primary key (id_number));
CREATE TABLE
However, displaying a table is a little different. Instead of using the SHOW TABLES
SQL command, you need to use the \dt
command, which stands for display table:
fruittrees=> \dt
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | test | table | sysadmin
(1 row)
fruittrees=>
After a table is created and defined, you can start populating it with data. An example of doing this is shown here:
fruittrees=> INSERT INTO test VALUES (1,'first test','data1');
INSERT 0 1
fruittrees=> INSERT INTO test VALUES (2,'2nd test','data2');
INSERT 0 1
fruittrees=>
Viewing data in a table follows standard SQL syntax, which is nice:
fruittrees=> SELECT * FROM test;
id_number | type | brand
-----------+------------+-------
1 | first test | data1
2 | 2nd test | data2
(2 rows)
fruittrees=> exit
$
When you have completed your work within the psql
SQL interface, be sure to use the exit
command to leave. If you need to access this database or its table again through this interface, you'll need to reconnect to the database using the \c
command.
Database administration is a rather deep topic, and we've just scratched the surface. However, you've got a little experience now that will assist you as you continue your database server management journey.
ArtificialFlowers
within the Florist
database. The artificial flower records listed in this table have only a few fields: ProductID
(which is the primary key), FlowerName
, FlowerColor
, and StemColor
. The store manager of the florist shop wants to check the data you've entered into this table. What steps should you take after you have logged into the MariaDB server's command line where this data exists?admin
. This role has super user privileges in the database as well as the ability to create roles and databases. What, if any, changes should be made to your account to improve the security levels of administering this database?