Whether you establish a formal FOREIGN KEY rule on messages(user_id) or not, the simple fact is that this is a foreign key relationship.
First, remember that a proper primary key on a table should be sufficient to uniquely identify each record in the table. Considering that each message will already have that with the id
field, you don't need nor do you particularly want to wrap the user_id
into the primary key of the messages table.
Second, as Charles already stated declaring a FOREIGN KEY on messages(user_id) that REFERENCES users(id) will allow you to ensure the integrity of your data. Using a foreign key constraint you can specify what to do when a record in the users table is deleted that has corresponding records in the messages table. Your choices are ON DELETE CASCADE (delete all of the child records for this user record), ON DELETE RESTRICT (don't allow a user to be deleted that has records in the messages table), ON DELETE NO ACTION (ignore delete operations), ON DELETE SET NULL (preserves the child records but sets the user_id field to NULL).
Each of these options is appropriate depending on the circumstances, but the most important thing here is that you can prevent unexpected null pointers from the child table to the parent table.
Third, establishing the FOREIGN KEY relationship will provide performance gains as this will generate an INDEX on messages(user_id) that corresponds with the PRIMARY KEY on the users table. When performing any query that joins on these fields, you will see that the number of records that have to queried to return the child records is substantially reduced as compared to not having the FOREIGN KEY established.
@Charles Bretana - The question you link to is specific to Microsoft SQL Server. The question here is regarding MySQL / InnoDB.
I would recommend that you look at the documentation for InnoDB Foreign Key Constraints.
InnoDB requires indexes on foreign
keys and referenced keys so that
foreign key checks can be fast and not
require a table scan. In the
referencing table, there must be an
index where the foreign key columns
are listed as the first columns in the
same order. Such an index is created
on the referencing table automatically
if it does not exist. (This is in
contrast to some older versions, in
which indexes had to be created
explicitly or the creation of foreign
key constraints would fail.)
index_name, if given, is used as
described previously.