Tuesday, December 31, 2013

A MySQL DBA looks at PostgreSQL

So this is a journey of the/a MySQL DBA looking into PostgreSQL. It is not an attack just observations and examples. 

Using CentOS 6.5 64Bit:

rpm -ivh  http://yum.postgresql.org/9.3/redhat/rhel-6.5-x86_64/pgdg-centos93-9.3-1.noarch.rpm

yum groupinstall "PostgreSQL Database Server 9.3 PGDG"
---> Package postgresql93.x86_64 0:9.3.2-1PGDG.rhel6 will be installed
---> Package postgresql93-contrib.x86_64 0:9.3.2-1PGDG.rhel6 will be installed
---> Package postgresql93-libs.x86_64 0:9.3.2-1PGDG.rhel6 will be installed

---> Package postgresql93-server.x86_64 0:9.3.2-1PGDG.rhel6 will be installed

yum install postgresql93-server

service postgresql-9.3 initdb
Initializing database:                                     [  OK  ]
service postgresql-9.3 start
Starting postgresql-9.3 service:                           [  OK  ]
chkconfig postgresql-9.3 on


All of the following examples are based on the PostgreSQL Wiki 
# su - postgres
-bash-4.1$ psql

psql (9.3.2)

postgres=# CREATE USER testuser PASSWORD '1234';
CREATE ROLE
postgres=# GRANT ALL ON SCHEMA test TO testuser;
GRANT

postgres=# GRANT ALL ON ALL TABLES IN SCHEMA test TO testuser;
GRANT
postgres=# \q
-bash-4.1$ exit
logout
# su testuser

$ pwd
/home/testuser
$  psql -d postgres
psql (9.3.2)

Type "help" for help.
postgres=> CREATE TABLE test.test (coltest varchar(20));
CREATE TABLE
postgres=> insert into test.test (coltest) values ('It works!');
INSERT 0 1
postgres=> SELECT * from test.test;
  coltest  
-----------
 It works!
(1 row)

postgres=> DROP TABLE test.test;
DROP TABLE
postgres=> 

I did notice that these grant statements worked well with 9.3 but the distro originally installed an 8.* version and some of the commands failed. 

Btw...You do of course still have features you would expect from a stable RDBM system. Granted these are simple examples.  

postgres=> EXPLAIN SELECT * from test.test;
                       QUERY PLAN                       
--------------------------------------------------------
 Seq Scan on test  (cost=0.00..19.20 rows=920 width=58)

Show databases == \l
postgres-> \l
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +

           |          |          |             |             | postgres=CTc/postgres

USE is standard SQL: 
postgres-> use postgres  

List all schemas:

postgres-> \dn
 public | postgres

 test   | postgres

Show create table and etc are a little more work. Granted a MySQL DBA will see it as more work because of what we are used to doing. PostgreSQL uses tablespaces more than MySQL users are used to doing. 

postgres=> CREATE TABLE sometable (somefield varchar(255), anotherfield varchar(150), datefield date );
CREATE TABLE
postgres=> INSERT INTO sometable (somefield, anotherfield, datefield) VALUES ('fubar', 'rabuf', '2013-12-30');
INSERT 0 1
postgres=> INSERT INTO sometable (somefield, anotherfield, datefield) VALUES ('fubar', 'rabuf', NOW());
INSERT 0 1
postgres=> INSERT INTO sometable (somefield, anotherfield, datefield) VALUES ('fubar2', 'rabuf2', NOW());
INSERT 0 1
postgres=> select * from sometable;
 somefield | anotherfield | datefield  
-----------+--------------+------------
 fubar     | rabuf        | 2013-12-30
 fubar     | rabuf        | 2013-12-30
 fubar2    | rabuf2       | 2013-12-30
(3 rows)

postgres=> select * from sometable WHERE somefield='fubar'; somefield | anotherfield | datefield -----------+--------------+------------ fubar | rabuf | 2013-12-30 fubar | rabuf | 2013-12-30 (2 rows)

postgres=> \? <-- The help will show you how to navigate around.

Show tables == \dt

postgres=> \dt
           List of relations
 Schema |   Name    | Type  |  Owner   
--------+-----------+-------+----------
 public | sometable | table | testuser

postgres=> ALTER TABLE sometable ADD COLUMN intfield int[11]; ALTER TABLE

postgres=> select * from sometable; somefield | anotherfield | datefield | intfield -----------+--------------+------------+---------- fubar | rabuf | 2013-12-30 | fubar | rabuf | 2013-12-30 | fubar2 | rabuf2 | 2013-12-30 | (3 rows)

Show create table == \d+ tablename
postgres=> \d+ sometable
                                 Table "public.sometable"
    Column    |          Type          | Modifiers | Storage  | Stats target | Description 
--------------+------------------------+-----------+----------+--------------+-------------
 somefield    | character varying(255) |           | extended |              | 
 anotherfield | character varying(150) |           | extended |              | 
 datefield    | date                   |           | plain    |              | 
 intfield     | integer[]              |           | extended |              | 
Has OIDs: no


To help more you can install pgadmin 
yum install pgadmin3_93

Getting that to work and how it works could be another entire blog post. 

So far.... I will stick with MySQL but this is just a simplistic example of using PostgreSQL. This can get you started to you can evaluate for yourself. 

Helpful links below. Please refer to these as they have more experience with PostgreSQL than I do. 

Saturday, December 7, 2013

ERROR 1356 (HY000)

The most important thing to understand when coming upon an error is to take a moment and relax. 
Sometimes people run across an error and become flustered and frustrated.  Take a deep breath and relax. Sometimes "Madness is like gravity. All that needs is a little push" and Sometimes the questions are complicated and the answers are simple.”

What is all this about? Well for example I recently was asked to help solve a problem that was troubling another DBA. Nothing meant in disrespect at all to that DBA but being in a rush people just overlook the answer that is in front of them and instead spiral down into madness

Here is the general concept of the situation. 

After doing a mysqldump of a database the user moved it to another database for others to being testing. The import worked just fine. However, the users began to see errors when they tried to query from a prebuilt view. 

mysql> select * from <View_name> limit 1; 

ERROR 1356 (HY000): View '<DB_NAME>.<ViewName>' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them 

The first reaction was to assume that the something went wrong with the import. Did the view or actually the related tables become corrupt? 

No. 

To solve this error the first thing todo was to:    mysql> show create view <View_Name> \G 

You likely will see something that begins like this:
*************************** 1. row *************************** 
View: Visitors 

Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`<Some_user>`@`<Some_host_or_IP>` SQL SECURITY DEFINER VIEW

After you see who  the definer is : `<Some_user>`@`<Some_host_or_IP>`   you can view the grants for that user. 

mysql> show grants for `<Some_user>`@`<Some_host_or_IP>`; 

It turns out the the solution was just what the error said in the first place:  "definer/invoker of view lack rights to use them"

To make it easy you can do a show grants in the database where it already works and copy the grant statement, or you can review what type of permissions you need to implement in the new database to enable the view to gather the required data. 

A simple update of permissions for the user and the error was gone.  

Sometimes the answers are simple.”