The hosts, needing a win to keep the three-match series alive after losing the opening game by four wickets on Saturday, stuttered to 62-3 after electing to take first strike.
Mahela Jayawardene and Mathews retrieved the situation by adding 122 for the fourth wicket, with both batsmen recording their second successive half-centuries.
But the dismissal of Jayawardene for 67 in the 34th over -- the first of three wickets in as many overs by Hafeez-- saw Sri Lanka collapse from a commanding 184-3 to 194-6.
Perera smashed 65 off 36 balls as the hosts plundered 101 runs in the last 10 overs.
More From This Section
Hafeez, who also trapped Seekkuge Prasanna and Ashan Priyanjan leg-before in successive overs, finished with three for 39 from 10 economical overs. Riaz had four for 65.
Hafeez stepped in for the prolific Saeed Ajmal, who was yet to return from Australia where he underwent tests on his bowling action after being reported by the umpires during the preceding Test series.
Sharjeel Khan replaced Younis, while Sri Lanka dropped batsman Dinesh Chandimal to play leg-spinner Prasanna.
The match was originally slated to be played in Colombo on Wednesday, but heavy rains in the Sri Lankan capital forced officials to change the venue and advance the game by a day.
The third and final one-dayer will be held in Dambulla on Saturday.