Nie używasz bind_param, zgodnie z paradygmatem przygotowanych instrukcji.
Do wyboru:
$sql = "SELECT id,msg,time,msg.from,msg.to
FROM msg
WHERE msg.from IN (?, ?)
AND msg.to IN (?, ?)
ORDER BY time";
$ex = $conn->prepare($sql);
$ex->bind_param("s", $_SESSION["username"]);
$ex->bind_param("s", $_SESSION["tousermessage"]);
$ex->bind_param("s", $_SESSION["username"]);
$ex->bind_param("s", $_SESSION["tousermessage"]);
$ex->execute();
A w Twojej aktualizacji:
$sql = "UPDATE msg
SET readmsg=1
WHERE id = ?
AND msg = ?";
$ex1 = $conn->prepare($sql);
$ex1->bind_param("i", $result['id']);
$ex1->bind_param("s", $result["msg"]);
$ex1->execute();
Powyższe pozwala twojej przygotowanej instrukcji akceptować parametry w sparametryzowanym formacie ciągu (używając znaku „?” do reprezentowania parametru) oraz akceptować parametry z informacją o typie za pomocą metody bind_param().
Pozwala to silnikowi DB na prawidłowe rzutowanie i zmianę parametrów przed wykonaniem zapytania.
Nie ma sensu używać przygotowanych oświadczeń, jeśli nie wiążesz parametrów, i prawdopodobnie dlatego otrzymujesz to ostrzeżenie.
Na marginesie, konkatenacja zapytań (jak to robisz powyżej) jest bardzo złym nawykiem - otwiera cię na Wstrzykiwanie SQL
Więcej informacji na temat przygotowanych wyciągów znajdziesz w dokumentacji:
http://php.net/manual/en/mysqli-stmt.prepare .php