Why select statement requests exclusive locks?
Always consider locktype when analyzing locks.

In this case locktype = virtualxid, i. e. virtual transaction id. This is an identifier that is local for a backend. PostgreSQL uses such identifiers for read-only transactions to save "normal" transaction ids, that are global to all backends. (You can read why it is doing so, although it is not relevant to the question.) For read-write transaction you will have locktype = transactionid instead.

So, this row in pg_locks basically says that a backend process has an exclusive lock on transaction id of the transaction it is currently executing. PostgreSQL uses this lock to allow other transactions to wait for ours transaction to finish. Citing the doc:


  When a process finds it necessary to wait specifically for another
  transaction to end, it does so by attempting to acquire share lock on
  the other transaction's ID (either virtual or permanent ID depending
  on the situation). That will succeed only when the other transaction
  terminates and releases its locks.