Check my new blog, includes old contents and newer ones!
Monday, November 23, 2020
Saturday, March 7, 2020
How To Monitor MySQL With dim_STAT
Monitoring a database is a critical mission: collecting information over time allows tracking how's behaving certain instance in response to a determined workload. There are several solution on the market, and MySQL offers its own solution in the Enterprise Edition, MySQL Enterprise Monitor (MEM). Today I'd like to remember that there's also another nice solution that is free, and designed by MySQL performance architect, Dimitri Kravtchuk (hence not to be considered as an Oracle MySQL solution, not supported and "as is"). I'm talking about dim_STAT. dim_STAT has a slightly different purpose than MEM as it is specialized to make some low level analysis of the impact of the workload on our MySQL Server instance (e.g. can profile mysqld process), and above all, permits offline metrics captures.
Extensive instructions to setup, configure and use dim_STAT are presented here. In this post I will share a practical summary of what I did to set it up. First of all it's worth clarifying that dim_STAT is composed of a server, dim_STAT-Server, and allows two modalities: online and offline.
This will start the minimal Apache web server and the internal MySQL instance used internally to store all the metrics that will be imported after the collection. Test the internal MySQL instance, can be accessed with:
Check the installation is successful by loading in your browser:
http://127.0.0.1/cgi-bin/WebX.mySQL/dim_STAT/x.welcome
At the end of the collection, a gunzipped series of files will be collected under /opt/stats/data.
Read more details about BatchLoad. Three important things to keep in mind to complete import of metrics:
Prepare the database
A single collection done with EasySTAT will be imported into a dedicated MySQL schema. This must be created in advance and configured in LoadDATA.sh. I decided to call my schema "mortensi" (BASE=${BASE:=mortensi}). This schema must come prepared with all the tables beneath, and must be created from dim_STAT preferences panel, choosing a name under "Create a New Database".
Enable Add-Ons
Upgrade patch delivers several add-ons that must be installed. To the purpose, from main menu, browse to "Add-On STAT(s)" and install all new add-ons at the bottom of the page. Only after this operation it is convenient to import metrics into the system, so that all collected data will be stored and used, otherwise data collected by a more recent agent (EasySTAT or STAT-service) won't be imported and simply discarded. Important note: add-ons must be enabled for every new database created in the previous step!
Troubleshoot errors
If you are trying this import procedure, for one reason or another you will fail, then it's handy to refer to the sql.error error log to understand what's gone wrong. It's generated under the install directory chosen.
It is now possible to start the import with LoadDATA.sh, which will log all the metrics imported, one by one:
Extensive instructions to setup, configure and use dim_STAT are presented here. In this post I will share a practical summary of what I did to set it up. First of all it's worth clarifying that dim_STAT is composed of a server, dim_STAT-Server, and allows two modalities: online and offline.
- Online: can monitor live instances (STAT-service) from multiple hosts
- Offline: can collect metrics for later analysis (EasySTAT), useful for instances that are not accessible e.g. behind a firewall
Here's a brief recap of the architecture: STAT-service is the remote Agent that monitors the instance and delivers metrics back to a backend, which in turn stores them into an own MySQL Server for later processing. The web interface allows configuration and it's the main entry point to retrieve data, make graphs and in general consult captured data. Following picture summarises the architecture.
In this post I'll explore the offline analysis: this is using EasySTAT.
Download
dim_STAT-v90-linux-x64.tgz here's the main package
WebX_apps-v90-u19-12.tgz the upgrade package to apply on top of the main install
STATsrv-v5-Linux-x64-mysql.tgz includes EasySTAT tool, to allow data collection "offline"
STATsrv-v5-Linux-x64-mysql.tgz includes EasySTAT tool, to allow data collection "offline"
There are also packages for macOS (which I will use in this post).
Install
Once uncompressed the main package dim_STAT-v90-linux-x64.tgz, run INSTALL.sh as root. This will prompt different choices, like paths for install, user and group to run processes, MySQL (if running other MySQL instance on the same host, specify a port) and STAT-service port.
If everything is correct, installation will finalise with:
** =========================================================================
**
** You can start dim_STAT-Server now from /opt/packages/ADMIN:
**
** # /opt/packages/ADMIN/dim_STAT-Server start
**
** NOTE: for the very first start you'll need to type "start-force"
** (instead of simple "start" command)
**
** and access homepage via Web browser - http://mortensi:80
**
** To collect stats from any Solaris, Linux or MacOSX machines just
** install & start on them a corresponding [STAT-service] package...
**
** Enjoy! ;-)
**
** -Dimitri
** =========================================================================
Upgrade
After installation, it is possible to apply the latest patch. Uncompress WebX_apps-v90-u19-12.tgz and then copy its content over /opt/WebX/apps. Patching is hot, so can be done later as well, especially when dim_STAT-Server is already running.Start
In order to start dim_STAT-Server, this one command will do the job:
sh-3.2# /opt/packages/ADMIN/dim_STAT-Server start-force
================[ dim_STAT-Server: start-force ]================
*
* MySQL Database Server
*
=> Log output : /opt/packages/mysql/data/mysqld.log
=> Local socket: /opt/packages/mysql/data/mysql.sock
=> Admin Access: root# /opt/packages/mysql/bin/mysql -S /opt/packages/mysql/data/mysql.sock
Starting...
200305 01:21:40 mysqld_safe Logging to '/opt/packages/mysql/data/mysqld.log'.
200305 01:21:40 mysqld_safe Starting mysqld daemon with databases from /opt/packages/mysql/data
Done.
** CHECK MySQL Server connection...
Starting HTTP server from: /opt/packages/httpd
Done.
================[ dim_STAT-Server: start-force -- done. ]================
sh-3.2#
This will start the minimal Apache web server and the internal MySQL instance used internally to store all the metrics that will be imported after the collection. Test the internal MySQL instance, can be accessed with:
sh-3.2# /opt/packages/mysql/bin/mysql -S /opt/packages/mysql/data/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 5.5.53 Source distributionCheck the installation is successful by loading in your browser:
http://127.0.0.1/cgi-bin/WebX.mySQL/dim_STAT/x.welcome
Collect metrics with EasySTAT
As mentioned, here I am interested in doing an offline audit of an instance, then I have used EasySTAT to capture metrics from the MySQL instance under observation. Instructions to deploy, configure, test and start the collection can be followed here:
http://dimitrik.free.fr/blog/posts/collect-stats-howto.html
I have tested a 8 hours collection of a MySQL 8 instance:
And once collection is started, make sure something is running in background:
http://dimitrik.free.fr/blog/posts/collect-stats-howto.html
I have tested a 8 hours collection of a MySQL 8 instance:
nohup ./EasySTAT.sh /opt/stats/data/ 10 8 "20200228-mortensi"
And once collection is started, make sure something is running in background:
[root@host1 bin]# ps aux | grep STAT
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1448 0.0 0.0 6356 624 pts/1 S 18:51 0:00 /opt/stats/STATsrv/bin/vmstat 10
root 1450 0.0 0.0 5096 884 pts/1 S 18:51 0:00 /opt/stats/STATsrv/bin/WebX /opt/stats/STATsrv/bin/x.Timer -Timeout 10
root 1462 0.0 0.0 4328 764 pts/1 S 18:51 0:00 /opt/stats/STATsrv/bin/mpstat -P ALL 10
root 1463 0.0 0.0 5096 876 pts/1 S 18:51 0:00 /opt/stats/STATsrv/bin/WebX /opt/stats/STATsrv/bin
...
At the end of the collection, a gunzipped series of files will be collected under /opt/stats/data.
Import metrics with BatchLOAD
Now it's time to import data with BatchLOAD under the database (that back-end MySQL instance started by dim_STAT-Server).
First, configure file ./LoadDATA.sh (this is generated by EasySTAT under data folder collection: /opt/stats/data/2020_02_28.host1.12503/LoadDATA.sh), this import procedure uses socket authentication, so make sure there is no conflicting "~/.my.cnf".
As an example, my header for LoadDATA.sh will look like:
As an example, my header for LoadDATA.sh will look like:
BatchLOAD=$1
BatchLOAD=${BatchLOAD:=/opt/packages/ADMIN/BatchLOAD}
BASE=$2
BASE=${BASE:=mortensi}
TITLE="20200228-mortensi"
HOST=$3
HOST=${HOST:=127.0.0.1}Read more details about BatchLoad. Three important things to keep in mind to complete import of metrics:
Prepare the database
A single collection done with EasySTAT will be imported into a dedicated MySQL schema. This must be created in advance and configured in LoadDATA.sh. I decided to call my schema "mortensi" (BASE=${BASE:=mortensi}). This schema must come prepared with all the tables beneath, and must be created from dim_STAT preferences panel, choosing a name under "Create a New Database".
Enable Add-Ons
Upgrade patch delivers several add-ons that must be installed. To the purpose, from main menu, browse to "Add-On STAT(s)" and install all new add-ons at the bottom of the page. Only after this operation it is convenient to import metrics into the system, so that all collected data will be stored and used, otherwise data collected by a more recent agent (EasySTAT or STAT-service) won't be imported and simply discarded. Important note: add-ons must be enabled for every new database created in the previous step!
Troubleshoot errors
If you are trying this import procedure, for one reason or another you will fail, then it's handy to refer to the sql.error error log to understand what's gone wrong. It's generated under the install directory chosen.
It is now possible to start the import with LoadDATA.sh, which will log all the metrics imported, one by one:
sh LoadDATA.sh
***==================================================================
*** START dim_STAT BatchLOAD
*** Collect ID: 1 Host: goldgate Command: ADD
***==================================================================
* DTSET: 2020-02-28 20:52:11
* STAT: mysqlFILE_IO
* END [#359]
***==================================================================
*** END BatchLOAD
*** Collect ID: 1
***==================================================================Generate reports
After all this effort, time to extract information from the data captured.- Go to preferences and choose the default database, where this capture metrics were stored (mortensi, in the example followed)
- Go back to main menu and choose "Analyze". Documentation available here.
Choosing graphs to show, and also how many different metrics combinations, has a wide set of options to generate ad-hoc reports. For that, official online documentation and experimenting are the best ways to get the most out of this very interesting tool.
Saturday, November 2, 2019
Manage InnoDB Cluster using MySQL Shell Extensions
At times, when playing with different InnoDB Clusters for testing (I usually deploy all Group Replication instances on the same host on different ports) I find myself stopping the group and doing operations on every instance (e.g. a static reconfiguration). Or I may need to shutdown all instances at once. Scripting is the usual approach, but in addition, MySQL Shell offers a very nice (and powerful) way to integrate custom scripts into the Shell itself to manage an InnoDB Cluster. This is the purpose of MySQL Shell extensions, to create new custom reports and functions and have the flexibility to manage one or more instances at once. I found particularly practical the new plugin feature, introduced in MySQL Shell 8.0.17, that can aggregate reports and functions under the same umbrella: the plugin.
As an example of the things that are possible, I have modified Rene's great example so to stop Group Replication in a shot from MySQL Shell, and it's particularly easy, check the following script.
The script defines stop_cluster function that is invoked with idc.stopCluster() and:
As an example of the things that are possible, I have modified Rene's great example so to stop Group Replication in a shot from MySQL Shell, and it's particularly easy, check the following script.
- Create directory ~/.mysqlsh/plugins/ext/idc/
- Create there init.js script as follows, it will be loaded at MySQL Shell startup.
// Get cluster object, only if session is created
function get_cluster(session, context) {
if (session) {
try {
return dba.getCluster();
} catch (err) {
throw "A session to a cluster instance is required: " + err.message
}
} else {
throw "A session must be established to execute this " + context
}
}
function stop_cluster() {
var cluster = get_cluster(shell.getSession(), "function");
var data = cluster.status();
var topology = data.defaultReplicaSet.topology;
var sess = shell.getSession()
var uri = sess.getUri()
var user = (uri.split('//')[1]).split('@')[0]
// iterate through members in the cluster
for (index in topology) {
if (topology[index].status=="ONLINE")
print("\n-----> " + topology[index].address + " is ONLINE and will be evicted from GR\n")
var sess = shell.connect(user + "@" + topology[index].address)
var result = sess.runSql("STOP GROUP_REPLICATION;")
//print(JSON.stringify(result, null, 4))
}
// Reconnect original session
shell.connect(uri)
return;
}
// Creates the extension object
var idc = shell.createExtensionObject()
// Adds the desired functionality into it
shell.addExtensionObjectMember(idc, "stopCluster", stop_cluster, {
brief: "Stops GR on all nodes, secondaries first, primary instance the last.",
details: [
"This function will stop GR on all nodes.",
"The information is retrieved from the cluster topology."]});
// Register the extension object as a global object
shell.registerGlobal("idc", idc, {
brief:"Utility functions for InnoDB Cluster."})
The script defines stop_cluster function that is invoked with idc.stopCluster() and:
- Get the cluster object from the session (session against any member must be created beforehand)
- Fetch topology from cluster object
- Iterate through members belonging to the topology and get the address
- For every member, establish a session using same session user (e.g. root or whatever, it is a prerequisite to administer a cluster with the same user)
- Send command to stop Group Replication
- After iterating through all members, reset the original session
The script also creates an extension object, registers it as global object and adds the function so it can be invoked as follows:
It is also possible to restart the cluster with the built-in dba global object, with function dba.rebootClusterFromCompleteOutage();
So in short, it is possible to start and stop the cluster with one command and from the same MySQL Shell session. This is only a quick skeleton (can be improved e.g. like stopping GR starting by secondary instances, and the primary at last) to connect to instances and do operations, there is no limit to the number of things that are possible. Read more on LeFred's blog here.
Saturday, September 21, 2019
MySQL Server Performance Tuning: The Perfect Scalability
When data and concurrency grow, together with queries complexity, a standard configuration does not fit anymore. This content walks through the ways MySQL has to adapt to an ever-increasing amount of data in context of tuning, under the heading “multiplication”:
—Scaling up through partitioning and how partitioning can help manage/archive data
—How to relocate binlog, undo, redo, tablespaces, or disk temporary tables and more on different mount points to take advantage of multiple storages and tackle I/O bottlenecks
—All improvements to parallel slave replication
—A quick OS approach, to verify swapping and affinity tuning take the most out of the machine.
All of this with different approaches to monitor the instance to spot what parts of the system and what queries need to be considered, mainly using:
—Sys Schema
—Global Status
—SHOW ENGINE INNODB STATUS
I presented this content at last Oracle Open World 2019 as a Hands-On Lab.
—Scaling up through partitioning and how partitioning can help manage/archive data
—How to relocate binlog, undo, redo, tablespaces, or disk temporary tables and more on different mount points to take advantage of multiple storages and tackle I/O bottlenecks
—All improvements to parallel slave replication
—A quick OS approach, to verify swapping and affinity tuning take the most out of the machine.
All of this with different approaches to monitor the instance to spot what parts of the system and what queries need to be considered, mainly using:
—Sys Schema
—Global Status
—SHOW ENGINE INNODB STATUS
I presented this content at last Oracle Open World 2019 as a Hands-On Lab.
Friday, September 20, 2019
How To Bulk Import Data Into InnoDB Cluster?
If you need to do bulk importing into InnoDB Cluster, it is certainly possible to do so by using any of:
Unfortunately both imports will add load to instances and to channels interconnecting instances: data imported on the primary instance needs to be replicated to the rest of instances. And the bigger the data to import, the higher the load (and this could end up affecting performance). The import operation could be batched to reduce load, and Group Replication allows at least to throttle workload with flow control or to split messages in several smaller messages with group_replication_communication_max_message_size option.
But in case data to import is a whole table (MySQL 8 adds also flexibility to swap partitions and tables, may become handy), or data can be first loaded into an InnoDB table, there's simple way to have an arbitrary amount of data pushed to InnoDB Cluster, and it takes advantage of tablespaces copying feature. I made a quick test to import a table.
I created the table t5 on an arbitrary instance and added a few rows. Then exported as in the instructions (does nothing but flush it and create an auxiliary .cnf file for definition validation at import time, not mandatory to use it but recommended):
On the InnoDB Cluster setup, I created the table t5 with same definition from the primary, then again on the primary:
This will remove the t5.ibd tablespace on all the 3 instances. And with a simple SELECT, I made sure that this is as expected:
After that, I copied t5.ibd from the former instance under the related schema folder in *each* GR node.
Let's check initial GTID set:
Then on the primary, did:
I am lazy and did not perform validation using .cfg (more from the instructions):
And all the tablespaces are loaded from local file system into the GR member. And new GTID set is:
Let's test it's all ok:
So data will be available on the rest of the nodes at no bandwidth and protocol cost, only this is indeed replicated, from binlog.
Most important, I broke nothing!
To wrap up, instead of loading GB or TB into InnoDB Cluster and have the cluster replicate massive amount of rows, this trick can push your data at no cost.
Comments are welcome!
- mysqldump logical dump
- tab separated dump, exported with SELECT..INTO OUTFILE statement or by using mysqldump with --tab option. And import with LOAD DATA..INFILE
Unfortunately both imports will add load to instances and to channels interconnecting instances: data imported on the primary instance needs to be replicated to the rest of instances. And the bigger the data to import, the higher the load (and this could end up affecting performance). The import operation could be batched to reduce load, and Group Replication allows at least to throttle workload with flow control or to split messages in several smaller messages with group_replication_communication_max_message_size option.
![]() |
| How to import data into InnoDB Cluster? |
I created the table t5 on an arbitrary instance and added a few rows. Then exported as in the instructions (does nothing but flush it and create an auxiliary .cnf file for definition validation at import time, not mandatory to use it but recommended):
FLUSH TABLES t5 FOR EXPORT;
On the InnoDB Cluster setup, I created the table t5 with same definition from the primary, then again on the primary:
ALTER TABLE t5 DISCARD TABLESPACE;
This will remove the t5.ibd tablespace on all the 3 instances. And with a simple SELECT, I made sure that this is as expected:
mysql> select * from test.t5;
ERROR 1814 (HY000): Tablespace has been discarded for table 't5'
After that, I copied t5.ibd from the former instance under the related schema folder in *each* GR node.
Let's check initial GTID set:
mysql> select @@GLOBAL.GTID_EXECUTED;
+------------------------------------------------------------+
| @@GLOBAL.GTID_EXECUTED |
+------------------------------------------------------------+
| 550fa9ee-a1f8-4b6d-9bfe-c03c12cd1c72:1-270:1000011-1000014 |
+------------------------------------------------------------+
1 row in set (0.00 sec)
Then on the primary, did:
mysql> ALTER TABLE t5 IMPORT TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.03 sec)
I am lazy and did not perform validation using .cfg (more from the instructions):
mysql> show warnings;
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory) Error opening './test/t5.cfg', will attempt to import without schema verification |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
And all the tablespaces are loaded from local file system into the GR member. And new GTID set is:
mysql> select @@GLOBAL.GTID_EXECUTED;
+------------------------------------------------------------+
| @@GLOBAL.GTID_EXECUTED |
+------------------------------------------------------------+
| 550fa9ee-a1f8-4b6d-9bfe-c03c12cd1c72:1-271:1000011-1000014 |
+------------------------------------------------------------+
1 row in set (0.00 sec)
Let's test it's all ok:
mysql> select * from test.t5;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 777 |
+------+
8 rows in set (0.00 sec)
So data will be available on the rest of the nodes at no bandwidth and protocol cost, only this is indeed replicated, from binlog.
# at 2714
#190919 1:34:34 server id 1 end_log_pos 2821 Query thread_id=34 exec_time=0 error_code=0
SET TIMESTAMP=1568849674/*!*/;
ALTER TABLE t5 IMPORT TABLESPACE
/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
Most important, I broke nothing!
mysql> SELECT MEMBER_ID, MEMBER_STATE FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+
| MEMBER_ID | MEMBER_STATE |
+--------------------------------------+--------------+
| 43a67ea3-e1a0-11e7-8a9a-0021f66e910e | ONLINE |
| 45ab082d-e1a0-11e7-8b73-0021f66e910e | ONLINE |
| 48be28c0-e1a0-11e7-8c19-0021f66e910e | ONLINE |
+--------------------------------------+--------------+
3 rows in set (0.00 sec)
To wrap up, instead of loading GB or TB into InnoDB Cluster and have the cluster replicate massive amount of rows, this trick can push your data at no cost.
Comments are welcome!
Tuesday, July 31, 2018
High Availability with MySQL Cluster, Setup From Command Line (II)
In the first delivery of this series of posts, delivered for whom who are interested to understand the basics of MySQL Cluster "by examples", I wrote about installing MySQL Cluster with a python utility called ndb_setup-py, which offers a nice web graphical interface to define and start our brand new cluster.
In this post I will share an example to do everything from scratch and manually, instead. Doing things manually is always the best recommendation to learn everything about processes life cycle through their:
Let's get down to business and deal today with processes initialization; I will discuss about setting up a MySQL Cluster environment from scratch and step by step on a Linux machine.
If no error is reported, we can check if the management process is running with ndb_mgm command line client tool like this:
Check again status with ndb_mgm:
We're done! Now that the cluster is up and running, we only need to connect through the SQL node and play! Remember that future data nodes restart, must be done without --initial option, otherwise data nodes data directories will be erased!
All processes declared as belonging to the cluster (topology was defined in the config.ini file) are now up and running, mission accomplished!
In this post I will share an example to do everything from scratch and manually, instead. Doing things manually is always the best recommendation to learn everything about processes life cycle through their:
- Initialization
- Administration (start/stop/reconfigure)
- Monitoring (logs/counters/status)
- Troubleshooting
The resulting topology I'd like to setup is composed of 2 data nodes, 1 management node and 1 SQL node, as in the following picture:
- Download generic binaries release for Linux
- File system preparation
- Initialize and start the management node
- Initialize and start the data nodes
- Initialize and start the SQL node
- Monitor the status
In order to run a MySQL Cluster deployment, I will need to create:
- A cluster configuration file, usually named config.ini. This is unique for all cluster processes.
- The SQL node configuration file, usually named my.cnf. Must have one per SQL node.
1. Download generic binaries release for Linux
My favorite MySQL Cluster install method is using binaries, as to the purpose of learning how to install and administer a cluster it is not needed to install RPMs and their related scripts to start/stop a process as a service. Hence I recommend to download binaries by choosing "Linux - Generic" from related download page.
2. File system preparation
Processes need to store stuff on the disk: not only to achieve durability, but also to store logs and other support files necessary to perform their duties. So every process will have a data directory. Plus, every process must define a nodeid, which is an integer number used to identify a process. Therefore, for simplicity, I recommend to create 4 folders under the desired path and name them with the nodeid I will set later in the configuration file. Important note: in order to make things easier, I will setup a whole cluster on my machine, while this is not the recommended topology in a real production environment, where data nodes and the management node should all run on dedicated hosts.
- 49. This folder will store data directory for the management node
- 1. This folder will store the data directory for data node 1
- 2. This folder will store the data directory for data node 2 (replica of data node 1)
- 50. This will store the data directory for the SQL node
Now that the four directories are created, let the fun begin!
3. Initialize and start the management node
Before starting the management node for the first time, I need to setup a config.ini file. Let's use this bare simple one.
This configuration file, the easiest possible (all configuration parameter have default values), is telling that:
[NDB_MGMD]
HostName=127.0.0.1
DataDir=/home/mortensi/cluster/49
NodeId=49
[NDBD]
NodeId=1
HostName=127.0.0.1
DataDir=/home/mortensi/cluster/1
[NDBD]
NodeId=2
HostName=127.0.0.1
DataDir=/home/mortensi/cluster/2
[MYSQLD]
HostName=127.0.0.1
NodeId=50
This configuration file, the easiest possible (all configuration parameter have default values), is telling that:
- Node ids are: 49 for the management node, 1 and 2 for the data nodes and 50 for the SQL node (the mysqld instance)
- We're setting up a topology where all processes are co-located on the same localhost machine
- We will use those folders we created as data directory.
ndb_mgmd --config-file=/home/mortensi/cluster/config.ini --configdir=/home/mortensi/cluster/49 --initial &
If no error is reported, we can check if the management process is running with ndb_mgm command line client tool like this:
ndb_mgm -e show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=1 (not connected, accepting connect from 127.0.0.1)
id=2 (not connected, accepting connect from 127.0.0.1)
[ndb_mgmd(MGM)] 1 node(s)
id=49 @127.0.0.1 (mysql-5.7.22 ndb-7.6.6)
[mysqld(API)] 1 node(s)
id=50 (not connected, accepting connect from 127.0.0.1)
This output is telling that our 2 data nodes defined in the config.ini have not been started, but the management was started successfully. Finally, the SQL node is not connected, yet.
4. Initialize and start the data nodes
Now it's time to start the core processes for any cluster setup: data nodes! Data nodes can only be started after the management node, as they need to connect to it to retrieve the configuration of the cluster. Run the following:
ndbmtd --connect-string=localhost --initial --ndb-nodeid=1 &
ndbmtd --connect-string=localhost --initial --ndb-nodeid=2 &Check again status with ndb_mgm:
ndb_mgm -e show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=1 @127.0.0.1 (mysql-5.7.22 ndb-7.6.6, Nodegroup: 0, *)
id=2 @127.0.0.1 (mysql-5.7.22 ndb-7.6.6, Nodegroup: 0)
[ndb_mgmd(MGM)] 1 node(s)
id=49 @127.0.0.1 (mysql-5.7.22 ndb-7.6.6)
[mysqld(API)] 1 node(s)
id=50 (not connected, accepting connect from 127.0.0.1)
We're done! Now that the cluster is up and running, we only need to connect through the SQL node and play! Remember that future data nodes restart, must be done without --initial option, otherwise data nodes data directories will be erased!
5. Initialize and start the SQL node
To finalize this cluster installation, we need to initialize SQL node data directory as follows (must indicate the path to the binary release and to the brand new datadir candidate folder):
mysqld --initialize-insecure --datadir="/home/mortensi/cluster/50" --basedir="/export/home/mortensi/software/mysql-cluster-gpl-7.6.6-linux-glibc2.12-x86_64/" --user=mortensi
Now that the SQL node has been initialized, let's use this simple my.cnf configuration file to start it:
[mysqld]
ndbcluster=on
ndb_nodeid=50
datadir=/home/mortensi/cluster/50
basedir=/export/home/mortensi/software/mysql-cluster-gpl-7.6.6-linux-glibc2.12-x86_64/
socket=/home/mortensi/cluster/50/mysqld.sock
log_error=/home/mortensi/cluster/50/mysqld.log
Save the file, and let's go:
mysqld --defaults-file=/home/mortensi/cluster/my.cnf &
You will now be able to connect:
mysql -h127.0.0.1 -uroot
And check your brand new cluster status!
mysql> select * from ndbinfo.nodes;
+---------+--------+---------+-------------+-------------------+
| node_id | uptime | status | start_phase | config_generation |
+---------+--------+---------+-------------+-------------------+
| 1 | 1691 | STARTED | 0 | 1 |
| 2 | 1690 | STARTED | 0 | 1 |
+---------+--------+---------+-------------+-------------------+
2 rows in set (0.02 sec)
Cool, isn't it?
6. Monitor status
To complete this mini tutorial, let's just check status for this cluster as already done:ndb_mgm -e show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=1 @127.0.0.1 (mysql-5.7.22 ndb-7.6.6, Nodegroup: 0, *)
id=2 @127.0.0.1 (mysql-5.7.22 ndb-7.6.6, Nodegroup: 0)
[ndb_mgmd(MGM)] 1 node(s)
id=49 @127.0.0.1 (mysql-5.7.22 ndb-7.6.6)
[mysqld(API)] 1 node(s)
id=50 @127.0.0.1 (mysql-5.7.22 ndb-7.6.6)All processes declared as belonging to the cluster (topology was defined in the config.ini file) are now up and running, mission accomplished!
Wednesday, July 25, 2018
Top 5 Things to Consider to Get Started with MySQL Performance Tuning
Today I'll share a few slides I prepared last year for a presentation delivered at Oracle Open World. This is a quick and easy hands-on lab for fresh MySQL Server DBAs. I chose 5 among the most relevant topics when tuning and scaling a MySQL Server using InnoDB tables.
In particular, in this hands-on, I will talk about:
In particular, in this hands-on, I will talk about:
- Scaling connections
- The threads model
- InnoDB REDO log
- InnoDB Buffer Pool
- The Execution plan
MySQL Performance Tuning 101 from Mirko Ortensi
Rate at which MySQL is delivering new features and improvements is impressive, in fact MySQL Server 8 boosts performance in many fields, especially regarding InnoDB REDO logging. Hence while the rest of recommendations still apply for new MySQL Server 8, the tuning REDO log flushing strategy is not mandatory anymore to achieve an improved throughput starting from MySQL 8. Improvements in such a field are mentioned by this blog post edited by Dimitri Kravtchuk, MySQL Performance Architect at Oracle MySQL (Twitter).
For an overview of optimization techniques, I recommend having a look at official documentation.
Rate at which MySQL is delivering new features and improvements is impressive, in fact MySQL Server 8 boosts performance in many fields, especially regarding InnoDB REDO logging. Hence while the rest of recommendations still apply for new MySQL Server 8, the tuning REDO log flushing strategy is not mandatory anymore to achieve an improved throughput starting from MySQL 8. Improvements in such a field are mentioned by this blog post edited by Dimitri Kravtchuk, MySQL Performance Architect at Oracle MySQL (Twitter).
For an overview of optimization techniques, I recommend having a look at official documentation.
Tuesday, July 24, 2018
High Availability with MySQL Cluster, a Quick How-To Guide for Dummies (I)
I have been playing with MySQL Cluster for some years now, and today I'd like to start writing a bit about it, how to set it up, configure, backup and also how to use it, as there's plenty of ways to drive operations towards the Cluster for brutal speed and concurrency. MySQL Cluster, the open source in memory database from Oracle MySQL, is available for free from MySQL Cluster download page (Community version has GPL license).
But before starting with an overview of installation and setup, if you're new to MySQL Cluster, I would strongly recommend to have a look at this video.
But.. what is MySQL Cluster?
MySQL Cluster is a cluster of processes, they are:
- ndb_mgmd management process. A MySQL Cluster setup must have at least one (can have more, for redundancy). It is recommended to execute it on a host where ndbmtd processes are not running, but does not need to be on a dedicated host, though. It consumes little resources and act as arbitrator to rule out eventual split brain situations and serves a number of functions.
- ndbmtd data node process. Default configuration includes 2 data nodes processes, they implement the NDB (NDB stands for Network Database) storage engine and store data in memory. The recommendation is to execute one ndbmtd on its own host. Data nodes are replicated synchronously, hence any of these can crash and Cluster would survive and be serviceable.
- mysqld instances, aka SQL nodes. These are the classical MySQL Servers delivered with MySQL Cluster distribution (they differ from standard standalone distribution in that they are compiled to make use of NDB storage engine). They can be used to retrieve MySQL Cluster metrics, to execute SQL queries against the cluster (as we'll see this is not the only way to fetch data from it) and also are used to implement geographical replication (among other uses). SQL nodes can run on dedicated hosts but can also share host with data nodes or ndb_mgmd node. Best option is always away from a host running ndbmtd data nodes, as resources needed by SQL nodes can be variable depending on operations, then it's better not to add variable load to the host, which may affect data nodes performance (at least data nodes footprint is quite stable over time).
There are two main distributions: the RPM/DEB package and the binary compressed package, I usually prefer to get the binary one, as it is more flexible and also easier to manage for new users. With binary distribution, everything is contained within a folder.
To get started quickly with MySQL Cluster, I would recommend to deploy a cluster on a single host using ndb_setup.py utility, available under the folder of binaries (bin). This command will open a graphical interface in a browser served by a minimalistic Python web server. It is really a simple tool and better suited to deploy all cluster processes at localhost (not the production recommended topology, but it's a good idea to start up quickly). This video shows a basic installation on multiple hosts (can be virtual machines as well).
MySQL Cluster documentation is pretty good at explaining the basics about the database, its specifications and tuning options, but I would also like to point to a couple of books:
- Pro MySQL NDB Cluster, written by Jesper Wisborg Krogh and Mikiya Okuno, Support Engineers at Oracle MySQL. The book contemplates the basics and much more to get started and administer a MySQL Cluster database.
- MySQL Cluster 7.5 Inside and Out, written by Mikael Ronstrom, NDB creator and Senior Architect at Oracle MySQL. It offers an in depth description of MySQL Cluster guts, together with the story of the product.
Thursday, August 3, 2017
Raspberry Surveillance System, The Complete Solution
I have shown how to build a basic system based on a Raspberry to capture a picture through a PiCamera and share it on a web page. Now I'd like to share a bit more of my experiments by describing an end-to-end approach to detect movements in the monitored area and alert of a possible intrusion. To the purpose, I'll share what I did setup with basic pieces of code found browsing around the internet. This minimal system is made of three simple elements:
- Telegram bot
- Motion detection algorithm
- Alert system
The Telegram Bot
A Telegram Bot is a nice and free manner to:
- Send commands to your surveillance system from your personal Telegram account, start/stop services, reconfigure them...Indeed you can still use an SSH connection but Telegram is quick, visual, and immediate. Last but not least, it will allow you to receive alerts on your smartphone.
- Receive messages coming from your surveillance system. When an alert is generated you will be informed by a message from your bot with the information and format you configure.
So how to create a Telegram bot? That's easier to do than to explain. Just add the BotFather to your contact list and start messaging! Send "/start" for the list of functionalities. To create a bot you'll have to send "/newbot". Check the example:
Nice! Now you have your bot entity ready to talk to your surveillance system! Write down the API token, which you'll use to authenticate to your bot as bot administrator and send/receive messages.
Mirko Ortensi, [Jul 20, 2017, 9:06 PM]:
/newbot
BotFather, [Jul 20, 2017, 9:06 PM]:
Alright, a new bot. How are we going to call it? Please choose a name for your bot.
Mirko Ortensi, [Jul 20, 2017, 9:06 PM]:
mybotname
BotFather, [Jul 20, 2017, 9:06 PM]:
Good. Now let's choose a username for your bot. It must end in `bot`. Like this, for example: TetrisBot or tetris_bot.
Mirko Ortensi, [Jul 20, 2017, 9:07 PM]:
mybotnameBot
BotFather, [Jul 20, 2017, 9:07 PM]:
Done! Congratulations on your new bot. You will find it at t.me/mybotnameBot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. By the way, when you've finished creating your cool bot, ping our Bot Support if you want a better username for it. Just make sure the bot is fully operational before you do this.
Use this token to access the HTTP API:
447633501:AAH_wZZupcBIGQEC_pPV7[...]
For a description of the Bot API, see this page: https://core.telegram.org/bots/api
Nice! Now you have your bot entity ready to talk to your surveillance system! Write down the API token, which you'll use to authenticate to your bot as bot administrator and send/receive messages.
As the system is written in Python, you'll manage your Telegram bot with python-telegram-bot, so be sure to install it in your Raspberry. You can accomplish that by running:
python -m pip install python-telegram-botMotion Detection
This is the core of every surveillance system: the capability to detect any change in the monitored area and take a decision (which is usually inform the administrator). I started from a very basic Google search and hit this lightweight motion detection Python algorithm which is pretty intuitive: few lines, easy to read, quick and, most important, it works pretty well. This piece of code will analyse frames captured with raspistill and detect changes based on previous buffered frame. If a change is detected, the captured frame is written to disk. The algorithm will allow configuration for:
- Threshold (how much a pixel has to change by to be marked as "changed")
- Sensitivity (how many changed pixels before capturing an image)
- ForceCapture (whether to force an image to be captured every forceCaptureTime seconds)
- Disk space to reserve: once hit, no more frames will be written to disk
I have been trying it for some weeks and it works pretty well, I will share the code with the thresholds I set:
#!/usr/bin/python
import StringIO
import subprocess
import os
import time
from datetime import datetime
from PIL import Image
# Motion detection settings:
# Threshold (how much a pixel has to change by to be marked as "changed")
# Sensitivity (how many changed pixels before capturing an image)
# ForceCapture (whether to force an image to be captured every forceCaptureTime seconds)
threshold = 30
sensitivity = 60
forceCapture = True
forceCaptureTime = 60 * 60 # Once an hour
# File settings
saveWidth = 1280
saveHeight = 960
diskSpaceToReserve = 400 * 1024 * 1024 # Keep 400 mb free on disk
# Capture a small test image (for motion detection)
def captureTestImage():
print("capture..")
command = "raspistill -w %s -h %s -t 3000 -e bmp -o -" % (100, 75)
imageData = StringIO.StringIO()
imageData.write(subprocess.check_output(command, shell=True))
imageData.seek(0)
im = Image.open(imageData)
buffer = im.load()
imageData.close()
return im, buffer
# Save a full size image to disk
def saveImage(width, height, diskSpaceToReserve):
keepDiskSpaceFree(diskSpaceToReserve)
time = datetime.now()
filename = "/tmp/capture-%04d%02d%02d-%02d%02d%02d.jpg" % (time.year, time.month, time.day, time.hour, time.minute, time.second)
subprocess.call("raspistill -w 1296 -h 972 -t 3000 -e jpg -q 15 -o %s" % filename, shell=True)
print "Captured %s" % filename
# Keep free space above given level
def keepDiskSpaceFree(bytesToReserve):
if (getFreeSpace() < bytesToReserve):
for filename in sorted(os.listdir(".")):
if filename.startswith("capture") and filename.endswith(".jpg"):
os.remove(filename)
print "Deleted %s to avoid filling disk" % filename
if (getFreeSpace() > bytesToReserve):
return
# Get available disk space
def getFreeSpace():
st = os.statvfs(".")
du = st.f_bavail * st.f_frsize
return du
# Get first image
image1, buffer1 = captureTestImage()
# Reset last capture time
lastCapture = time.time()
while (True):
# Get comparison image
image2, buffer2 = captureTestImage()
# Count changed pixels
changedPixels = 0
for x in xrange(0, 100):
for y in xrange(0, 75):
# Just check green channel as it's the highest quality channel
pixdiff = abs(buffer1[x,y][1] - buffer2[x,y][1])
if pixdiff > threshold:
changedPixels += 1
# Check force capture
if forceCapture:
if time.time() - lastCapture > forceCaptureTime:
changedPixels = sensitivity + 1
# Save an image if pixels changed
if changedPixels > sensitivity:
lastCapture = time.time()
saveImage(saveWidth, saveHeight, diskSpaceToReserve)
# Swap comparison buffers
image1 = image2
buffer1 = buffer2Alert System
Now the final piece of code; we have to inform the user whenever a motion is detected. I wrote two lines of code to send a Telegram message from the bot. This simple algorithm counts frames captured in /tmp folder (every 5 seconds, let's say) Whenever this number is increased, the user receives a message. Something like this:
Don't forget to:
#!/usr/bin/python
import sys
import time
import random
import datetime
import telegram
import os
import logging
import fnmatch
bot = telegram.Bot(token='447633501:AAH_wZZupcBIGQEC_pPV7[...]')
elems = len(fnmatch.filter(os.listdir("/tmp"), '*.jpg'))
print elems
while (True):
if (elems != len(fnmatch.filter(os.listdir("/tmp"), '*.jpg'))):
bot.sendMessage(chat_id=<id_from_userinfobot>, text="Motion!")
elems = len(fnmatch.filter(os.listdir("/tmp"), '*.jpg'))
time.sleep(5)
Don't forget to:
- Create the bot object by using the token provided by BotFather
- Send the message to the user id to be notified. In order to find out your user id, send "/start" command to userinfobot.
Wrap everything up
Now that you have the Telegram bot created, the motion detection loop algorithm and a manner to send alerts, you'll have to wrap it up. This simple architecture is composed of just three daemons:
- Telegram bot daemon to receive commands from Telegram user and perform actions
- Motion detection daemon to parse frames looking for movements
- Alert system daemon which, based on motion detection daemon, send a Telegram notification
These three daemon can be run as start/stop/status services in /etc/init.d as usual, whereas Telegram bot code could be something like:
#!/usr/bin/python
from telegram.ext import Updater, CommandHandler
import subprocess
def status(bot, update):
command = "sudo ps ax | grep ".py" | grep -v grep | grep -v sudo"
try:
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
p_status = p.wait()
update.message.reply_text(output)
except Exception as e:
output = str(e)
update.message.reply_text(output)
def startm(bot, update):
command = "sudo /etc/init.d/motiond start"
try:
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
p_status = p.wait()
update.message.reply_text("Motion Detection Enabled")
except Exception as e:
output = str(e)
update.message.reply_text(output)
def stopm(bot, update):
command = "sudo /etc/init.d/motiond stop"
try:
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
p_status = p.wait()
update.message.reply_text("Motion Detection Disabled")
except Exception as e:
output = str(e)
update.message.reply_text(output)
def hello(bot, update):
update.message.reply_text(
'Hello {}'.format(update.message.from_user.first_name))
updater = Updater('447633501:AAH_wZZupcBIGQEC_pPV7[...]')
updater.dispatcher.add_handler(CommandHandler('startm', startm))
updater.dispatcher.add_handler(CommandHandler('stopm', stopm))
updater.dispatcher.add_handler(CommandHandler('status', status))
updater.start_polling()
updater.idle()
Here I implemented three basic commands like:
- Start motion detection
- Stop motion detection
- Check Python processes running, so to be sure all the processes are running
You can add more controls, like starting/stopping alerting system...
This is a demonstrative code, you could think of adding a watchdog to make sure everything is running or join the three daemons into one.
Wednesday, July 26, 2017
Raspberry surveillance system, your house goes live on the internet
After leaving my brand new Raspberry 3 on the shelf for months (I admit being an impulsive buyer) I decided to give it some use by setting up a surveillance system with it. Raspberry 3 has more than enough power for easy image processing, and the camera developed for its GPU has nice quality at a very accessible price.
So, in order to start with this project, I got this PiCamera v2. I got that one with InfraRed (IR) filter, as I don't plan to take nightly shots with added IR lighting (maybe next prototype). It is really easy to connect its flex cable to the Raspberry (though unfortunately I'll have to leave the original case open and remove the top lid, as the case does not have a slot for the flex cable).
Once the camera is connected (beware to shut the system down before trying any connect/disconnect), I upgraded the whole Raspbian system with:
Now it's time to enable PiCamera module, this can be done by launching:
Related option to toggle is under "Interfacing options".
Now that the camera is ready to be used, it's time to start playing with it. It is easy to take advantage of the official tool to take snapshots, raspistill.
You can take a snapshot with the bare:
Ok, now we have everything to start playing seriously!
Next step is to install the bare minimum NGINX web server. Purpose of our prototype is to take a picture every n minutes, and show it on a web page hosted locally on your Raspberry and served by NGINX.
Before doing that, remember to:
So this snippet is basically serving one picture captured by your PiCamera and stored locally to index.html file, this would be at "/var/www/html/my.jpg".
Last step is setting up a cron job with the related instructions to capture a periodical snapshot, this would be something like:
So, in order to start with this project, I got this PiCamera v2. I got that one with InfraRed (IR) filter, as I don't plan to take nightly shots with added IR lighting (maybe next prototype). It is really easy to connect its flex cable to the Raspberry (though unfortunately I'll have to leave the original case open and remove the top lid, as the case does not have a slot for the flex cable).
Once the camera is connected (beware to shut the system down before trying any connect/disconnect), I upgraded the whole Raspbian system with:
sudo apt-get update
sudo apt-get upgrade
sudo rpi-updateNow it's time to enable PiCamera module, this can be done by launching:
sudo raspi-configRelated option to toggle is under "Interfacing options".
Now that the camera is ready to be used, it's time to start playing with it. It is easy to take advantage of the official tool to take snapshots, raspistill.
You can take a snapshot with the bare:
raspistill -o pic.jpgOk, now we have everything to start playing seriously!
Next step is to install the bare minimum NGINX web server. Purpose of our prototype is to take a picture every n minutes, and show it on a web page hosted locally on your Raspberry and served by NGINX.
Before doing that, remember to:
- Make yourself with a dynamic DNS service, I tried Dynu which is free and easy to setup. Everything is clearly explained, you'll have to remember to setup "~/dynudns/dynu.sh" script with cron, which will update the dynamic DNS with your home IP.
- Set a static IP for your Raspberry in your local network (e.g. 192.168.x.x)
- Log into you router configuration panel and set port forwarding to your Raspberry (port 8080 should reach the static IP set at previous step)
<!DOCTYPE html>
<html>
<head>
<title>Welcome to my house!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<img src="my.jpg" alt="myhouse" style="width:100%;">
</body>
</html>
So this snippet is basically serving one picture captured by your PiCamera and stored locally to index.html file, this would be at "/var/www/html/my.jpg".
Last step is setting up a cron job with the related instructions to capture a periodical snapshot, this would be something like:
*/10 * * * * sudo raspistill -q 15 -w 1024 -h 768 -o /var/www/html/my.jpg
This will capture every 10 minutes a medium quality picture, quick to be served over the internet. Tune at your own preferred quality and capture rate!
Wednesday, May 20, 2015
Things I learnt to improve communication at work
What happens when communication between people is not that efficient and clear in the business world? I am sure you know pretty well the following picture. Misunderstandings happen all the time when the actors in discussions, conversations or negotiations have an idea in mind which is tough to convey. Or when one is not really listening to the other and just have his own idea in mind.
Sadly, misunderstandings happen. Quite often. And this problem is time and money consuming. But above all, relationships get severely affected when expectation is betrayed, somehow, by too many assumptions.
What I learnt is that in order to make ideas caught by a partner and across the different communication channels, simple rules need to be followed. Let's go through some ideas.
Be careful to death by Power Point
According to a statistics, there are 300 millions Power Point users in the world. Everyday 30 millions presentations are done. It is pretty clear that a bad and boring presentation lead to bad communication and may bring undesidered consequences? Imagine you are trying to sell something but your presentation is damn bad.
- Send content beforehand. Everybody will have an idea, and eventually will come with intelligent questions.
- Attractive visuals. Put images as background. Nice images. Choose carefully images you plan to present. There are lots of media libraries with content ready and licensed to use. Don't simply steal from Google Images, you never know where your presentation is going and who's reading it.
- 3 to 5 bullets, no further text. Use Power Point for what it is, a tool to visualize and summarize ideas. Not the script for your speech. Besides, people read faster than you speak, If you plan to fill your slides with text, just send them. You're useless.
- Never, ever, look at the slides. Look at people.
- Why are you presenting? Make sure you have a clear objective. Remember to follow the pattern why-what-how and not the other way round.
- Pay attention to the overall message, and put some passion there.
- Reherse, and ask for feedback.
- Check remote control, check that your laptop is fine and make sure you have a backup on usb. Make it happen!
Again, don't bore people do death
You are presenting something to an audience, and soon you realize that from the bottom, people start snoring. You are boring them. My presentations were like that, some deeply technical speeches full of details. Since I started studying the art of presenting, my life changed. And I saved hundreds of lives.
- Catch people's attention, say something great to start your presentation "Today I am here to change your life and make you rich!". You can even interact with people "how many of you know...?"
- Keep eye contact, Otherwise you will lose the audience.
- Change tone of voice, presentations tend to get monotonous. A pitch from time to time will wake people up. DO YOU NEED AN EXAMPLE?
- Make jokes, use an informal tone. Use a friendly tone.
- Make a great unexpected conclusion
Video and teleconference
When the meeting is in a virtual room, first make sure that all the equipment works. To the purpose, connect some minutes before. Yes, common sense. But too many meetings starts late because the pin is wrong, the camera does not work and the voice is silent. Let's then summarize.
- Check all the equipment is working fine in advance.
- You may want to schedule meetings 5 minutes past the hour. That is 12:05, so people have time to move from one room to another, to setup a conference bridge or take a cup of coffee.
- Speak clear and loud; and use your plain English. This may be a problem with non native speakers, not everybody has full control on english language. Keep it simple, then.
- Remember to pay attention to people on the camera. If you are divided between a physical room and the camera, divide yourself between the two effectively.
- Send material in advance, slides, documents and whatever is needed so people can follow you easily.
Make emails more visual
People don't like reading flat, long, detailed emails. People will most probably read your email top to bottom, with a glance to bullets, possibly. Then here you have some ideas to make the most out of this channel.
- Keep it short, but keep all the details in.
- Use bullets to explain the main points
- Use bold, underline and italic.
- Use colors to state that something deserves further attention
Tuesday, May 20, 2014
Differences between Copyright, Copyleft and Creative Commons
Motivated by the suspension of famous Spanish writer Javier Marias' blog because of license infringement, I searched the web and found the following comparison of licenses to stay on the safe side when reusing, mentioning or modifying content found on the web.
The infringement was reported by Michael Magras: part of a post from his blog was copied in Marias' blog without acknowledging the authorship. This resulted in a claim to Wordpress blogging platform and consequent suspension of the blog.
All the three licenses have something in common: they all deal with author's rights. They just differs in the way they protect them. Let's get down to business.
Copyright
This is the most popular license, and unfortunately it's the most used one. It allows full rights to the owner of the work (that may not be the very author), and he's the only one that may decide what to do with it, whether to charge for it or not, besides having to request permission for usage. Distribution is only restricted to the owner of the creation, that means the license only allows possession but not distribution. This is usually applied to books, music, movies and software, as an example.
The infringement was reported by Michael Magras: part of a post from his blog was copied in Marias' blog without acknowledging the authorship. This resulted in a claim to Wordpress blogging platform and consequent suspension of the blog.
All the three licenses have something in common: they all deal with author's rights. They just differs in the way they protect them. Let's get down to business.
Copyright
This is the most popular license, and unfortunately it's the most used one. It allows full rights to the owner of the work (that may not be the very author), and he's the only one that may decide what to do with it, whether to charge for it or not, besides having to request permission for usage. Distribution is only restricted to the owner of the creation, that means the license only allows possession but not distribution. This is usually applied to books, music, movies and software, as an example.
Tuesday, May 6, 2014
Your first meditation in three steps: Anapanasati yoga
There's a lot of buzz around meditation, and for those who are not into that, it sounds a bit like a mysterious way to achieve who knows what. Enlightenment, peace of senses, eternal pleasure or visits to other dimensions?
This is not exactly like that, but benefits that people receive by practicing meditation are tangible and immediate. Mind relaxation, better concentration and improved consciousness of oneself. The good thing is that everybody can meditate and no special preparation is needed nor a special place or time of the day.
So let's dive into this fascinating world of meditation with one simple yet effective technique, it may be your first meditation ever. Follow these simple steps.
Don't feel guilty for that, but once you notice you have abandoned the practice, go back to it, go back to breath observation.
Don't expect things will happen. Keep expectation low. Just consider the way you feel once the session is over.
Once you are used to this practice, don't wait for the perfect moment for it. Every moment of the day and in any place it's perfect. In the bus, while waiting the subway... these are perfect places for Anapanasati yoga. You don't even need to keep you eyes opened. You can even observe your breath while walking in the street, this method won't take consciousness away from what's happening around you. And why not, try that for some minutes in front of your computer at work. Nobody will notice that!
This meditation is explained in its simplest form, there are lots of things one may do to complicate these few steps. But let's keep it simple, not for being simple it is less effective. Once you master this meditation, beautiful things will happen and you will be ready for the next step.
This is not exactly like that, but benefits that people receive by practicing meditation are tangible and immediate. Mind relaxation, better concentration and improved consciousness of oneself. The good thing is that everybody can meditate and no special preparation is needed nor a special place or time of the day.
![]() |
| Try this simple meditation technique to learn more about you |
- Sit down comfortably on the ground, on a sofa or even lay down on your bed. Once you feel comfortable with your position, you are ready to start. Otherwise, make sure you make all the adjustments until you feel fine. There are precise meditation postures, but to get into the technique, you don't need to master them. Just make sure you feel good. An uncomfortable posture may distract you from what's next.
- Close your eyes. Bring attention to the tip of your nose and observe the air flowing through it: observe the flow of air when inhaling and observe it again when exhaling. Feel the air in your nostrils when you inspire. Feel the air in your nostrils and on the tip of the upper lip when you exhale. That's it. Remember you are just observing your breath, you don't need to change the pace of your breathing. Just observe.
- Observe your breath during 10 minutes. If you think previous step was
easy, here comes the essential motivation of this method. Try, at
least, to extend breath observation for some minutes, up to 10. Purpose
is not getting distracted by other thoughts.
That's all. Now let's discuss all the implications of this simple yet powerful method.
Don't feel guilty for that, but once you notice you have abandoned the practice, go back to it, go back to breath observation.
Don't expect things will happen. Keep expectation low. Just consider the way you feel once the session is over.
Once you are used to this practice, don't wait for the perfect moment for it. Every moment of the day and in any place it's perfect. In the bus, while waiting the subway... these are perfect places for Anapanasati yoga. You don't even need to keep you eyes opened. You can even observe your breath while walking in the street, this method won't take consciousness away from what's happening around you. And why not, try that for some minutes in front of your computer at work. Nobody will notice that!
This meditation is explained in its simplest form, there are lots of things one may do to complicate these few steps. But let's keep it simple, not for being simple it is less effective. Once you master this meditation, beautiful things will happen and you will be ready for the next step.
Tuesday, April 29, 2014
The Untouchables, shocking project by Erik Ravelo
Today I bumped into this project from the Cuban artist Erik Ravelo to raise awareness on abuses that are committed by society against children.
First image is referring to scandals related to pedophilia committed by Catholic church
Second image refers to sexual tourism in Thailand
Third image refers to war in Siria
Fourth image refers to organs traffic in poor countries, in which first victims are children
Fifth image refers to free and non controlled weapon license in the States
Sixth image refers to large food distributions that targeted children with low quality aliments (fast foods) causing obesity
I posted this image in my Facebook account and received different comments, some agreeing that strong message is delivered. According to some other friend, this project is disrespectful with Catholic people.
My first feeling is that a lot of painful truth is portrayed here, it makes one think.
See the whole project here
http://erikravelo.info/los-intocables/
Wednesday, March 19, 2014
Free Open Source Software in your company
The vast majority of companies in software industry struggle to cut costs down while trying to keep quality of software high, but this is not easy to accomplish. Software development is radically different from any other industry you may want to consider for a comparison; in order to be a successful firm neither large investments nor brute force are strategic assets.
The new wave of millionaire start-up businesses prove that besides a brilliant idea, user experience, great design and definitely competitive time to market are critical. Consider the main resource of any business: employees, as an example. Increasing number of employees does not ensure goals are achieved either faster or even with better quality (back to the start-up mention, Instagram started with less than ten employees). Nevertheless, hiring top class experts in this business may be the added value: experience and talent are essential when building intellectual value.
The new wave of millionaire start-up businesses prove that besides a brilliant idea, user experience, great design and definitely competitive time to market are critical. Consider the main resource of any business: employees, as an example. Increasing number of employees does not ensure goals are achieved either faster or even with better quality (back to the start-up mention, Instagram started with less than ten employees). Nevertheless, hiring top class experts in this business may be the added value: experience and talent are essential when building intellectual value.
Monday, June 10, 2013
A technique for persuading people
This is a nice example to show how you can subtly persuade people to do what you want them to do. This short video tells about the experience of famous director Steven Spielberg when at the age of 15 had to face a troublesome situation.
This contribution basically suggests that in order to persuade people, first one need to match people's needs against own personal abilities. Then remember:
This contribution basically suggests that in order to persuade people, first one need to match people's needs against own personal abilities. Then remember:
- The objective is meeting people's basic needs.
- Look into your own resources and capabilities to meet others' basic needs
Tuesday, June 4, 2013
My 10th Toastmasters speech: What is life like
I am here today with a humble purpose, I want to share with you a simple reflection to help you improve your life. And I am here because it is useful for me therefore I thought that this may be interesting for you to know.
I would like to ask just one thing. Take a few seconds and think about something you hate to do. Something that makes you feel uncomfortable. Let’s make it easier. Something that happened this very morning. No no, it’s not a meeting or that uncomfortable mail.
What, can’t you find anything? I will help you with something you really cannot stand. From the very beginning of your day. And ladies and gentleman, that is the very beginning of the day. You hate waking up in the morning. Who doesn’t?
Now let’s make it even worse: what if you have to get up on Monday? Isn’t it quite uncomfortable to get up on Mondays, after a pleasant weekend with your family or friends? Yes it is. Mondays are there for you to be annoyed. But of course I can find something even more terrible than that. And it’s getting up early in the morning on Monday back from vacations. Wow, that’s pretty hard.
Of course there are hundreds of ways to make it worse. With rain, coffee's over at home, your car is broken or you can’t find your keys. You have headache and must attend a meeting. No hot water in the shower. Or... all these things altogether.
Small tragedies. That’s just an example of those kind of little things you will bump into during the day and along the path. To this you may want to add a quarrel with your parents, a misunderstanding with your partner and bad behavior of your children. Rain on weekends, too much work, stress, disappointing situations, people late, compromises, the mortgage, the car, responsibilities and one thousand of other things. We are used to live life in rush. Everyone has his own little secret to get over all these unpleasant situations and enjoy life as much as possible. I do have mine.
When it’s difficult to get up in the morning, or I am puzzling over personal issues, discussing with someone, too busy at work or troubled by any uncomfortable situation, this reflection helps me going back to relax in my mind and consider things for what they are.
My method is a real recipe for a lot of situations, and not only benefits me, it may have effects on people all around. It all started once when discussing futile things with my wife,I took a breath and suddenly said that. A moment of silence please. I said: “Why should I worry about that? Life is a party, and I want to live it like a never ending party”.
After that, I suddenly felt better, relaxed, as if all the stress had melt away. I thought about it and took it seriously. Life is a party. You don’t think so?
This is guy is crazy, you might be thinking right now. Ladies and gentleman, yes I am. For me life is the biggest party of the whole universe. I wish everybody may live life as such. Let’s have a look.
Who am I to say life is a party? I can prove you. Here’s my CV.
We love parties because there is food, drinks, music and people. We may dance, sing, laugh and be serious. There are plenty of people you don’t know, some of them you know, funny and boring ones. You may get late to the party or be on time. Whatever the party is, it’s always full of surprises. Parties may be boring or not. Parties are made for lovers, and for haters too. Parties give a meaning to our lives.
Life is expectation, like before a party. When you are expectant for something to happen, when you are excited and when you put a lot enthusiasm and effort for a big outcome. It’s when you wish to meet new people, make friendship, enjoy food and drinks. It’s when everything is ready to go to the party.
Life is full of surprises. When you enjoy talking and talking, getting into a new conversation and also being serious into a discussion. When you meet that person it was a long time since you met last time. This is only at a party.
Life is supporting people, like in a party when you notice that girl in the corner alone, because she knows nobody, and you go next to her, speak to her, introduce to your friends because she’s shy and she doesn’t want to be under everybody’s eyes. You want the party to be a party for her too.
Life is awful moments, like in a party. When you notice that your friend drank to much and he’s silly and boring. When he starts crying about her girlfriend, and that he cannot forget her and he must go right away. When he is so drunk, or it’s you or it's me, so drunk, someone is there to bring you to the toilet to help you vomit.
Life is love. Because I met my wife at a party.
I am at the end of my presentation and I just want you to do something. Do it for you. Every time it’s difficult to get up in the morning, you are angry at someone, you are stressed by your work, you feel sad for something not really important... Every moment you spend of your life in a bad mood, always remember that probably it’s not that important. Celebrate with others all the good things of your life. Remember every time you get prepared for a party, a wedding party, a birthday, your company summer party. Keep the expectation high in life as if going to a party.
Always remember the main ingredients to make a great party. Food, wine, and great organization. Music, a DJ and rhythm. Ice cubes, glasses, and good spirit.
But overall, the main ingredient: people, because every moment of your life is good to share with others, when you are old...
...when you are young...
...and when you are very very young.
Because life is a party.
I would like to ask just one thing. Take a few seconds and think about something you hate to do. Something that makes you feel uncomfortable. Let’s make it easier. Something that happened this very morning. No no, it’s not a meeting or that uncomfortable mail.
What, can’t you find anything? I will help you with something you really cannot stand. From the very beginning of your day. And ladies and gentleman, that is the very beginning of the day. You hate waking up in the morning. Who doesn’t?
Now let’s make it even worse: what if you have to get up on Monday? Isn’t it quite uncomfortable to get up on Mondays, after a pleasant weekend with your family or friends? Yes it is. Mondays are there for you to be annoyed. But of course I can find something even more terrible than that. And it’s getting up early in the morning on Monday back from vacations. Wow, that’s pretty hard.
Of course there are hundreds of ways to make it worse. With rain, coffee's over at home, your car is broken or you can’t find your keys. You have headache and must attend a meeting. No hot water in the shower. Or... all these things altogether.
Small tragedies. That’s just an example of those kind of little things you will bump into during the day and along the path. To this you may want to add a quarrel with your parents, a misunderstanding with your partner and bad behavior of your children. Rain on weekends, too much work, stress, disappointing situations, people late, compromises, the mortgage, the car, responsibilities and one thousand of other things. We are used to live life in rush. Everyone has his own little secret to get over all these unpleasant situations and enjoy life as much as possible. I do have mine.
When it’s difficult to get up in the morning, or I am puzzling over personal issues, discussing with someone, too busy at work or troubled by any uncomfortable situation, this reflection helps me going back to relax in my mind and consider things for what they are.
My method is a real recipe for a lot of situations, and not only benefits me, it may have effects on people all around. It all started once when discussing futile things with my wife,I took a breath and suddenly said that. A moment of silence please. I said: “Why should I worry about that? Life is a party, and I want to live it like a never ending party”.
After that, I suddenly felt better, relaxed, as if all the stress had melt away. I thought about it and took it seriously. Life is a party. You don’t think so?
This is guy is crazy, you might be thinking right now. Ladies and gentleman, yes I am. For me life is the biggest party of the whole universe. I wish everybody may live life as such. Let’s have a look.
Who am I to say life is a party? I can prove you. Here’s my CV.
- 18 shared flats across my life with over 50 mates
- Hundreds of birthday parties and celebrations at students’ houses
- Salsa and bachata dancing parties
- Liters of wine and gallons of beer drunk all over parties. Hangover expert
- Absolutely senior as a party attendant and great socialization skills.
- Hire me!
We love parties because there is food, drinks, music and people. We may dance, sing, laugh and be serious. There are plenty of people you don’t know, some of them you know, funny and boring ones. You may get late to the party or be on time. Whatever the party is, it’s always full of surprises. Parties may be boring or not. Parties are made for lovers, and for haters too. Parties give a meaning to our lives.
Life is expectation, like before a party. When you are expectant for something to happen, when you are excited and when you put a lot enthusiasm and effort for a big outcome. It’s when you wish to meet new people, make friendship, enjoy food and drinks. It’s when everything is ready to go to the party.
Life is full of surprises. When you enjoy talking and talking, getting into a new conversation and also being serious into a discussion. When you meet that person it was a long time since you met last time. This is only at a party.
Life is supporting people, like in a party when you notice that girl in the corner alone, because she knows nobody, and you go next to her, speak to her, introduce to your friends because she’s shy and she doesn’t want to be under everybody’s eyes. You want the party to be a party for her too.
Life is awful moments, like in a party. When you notice that your friend drank to much and he’s silly and boring. When he starts crying about her girlfriend, and that he cannot forget her and he must go right away. When he is so drunk, or it’s you or it's me, so drunk, someone is there to bring you to the toilet to help you vomit.
Life is love. Because I met my wife at a party.
I am at the end of my presentation and I just want you to do something. Do it for you. Every time it’s difficult to get up in the morning, you are angry at someone, you are stressed by your work, you feel sad for something not really important... Every moment you spend of your life in a bad mood, always remember that probably it’s not that important. Celebrate with others all the good things of your life. Remember every time you get prepared for a party, a wedding party, a birthday, your company summer party. Keep the expectation high in life as if going to a party.
Always remember the main ingredients to make a great party. Food, wine, and great organization. Music, a DJ and rhythm. Ice cubes, glasses, and good spirit.
But overall, the main ingredient: people, because every moment of your life is good to share with others, when you are old...
...when you are young...
...and when you are very very young.
Because life is a party.
Subscribe to:
Posts (Atom)

























